Promise index tuples for UPSERT
Summary of algorithm to use "promise tuples" for concurrency control
during UPSERT
1. Perform btree search to location of key, if it exists.
a) If an unkilled index tuple exists, we decide this is an UPDATE and
drop straight thru to step 2
b) If it does not exist, insert a "promise" tuple into unique index(s)
- marked with the xid of the inserting transaction, but using the key.
This happens while the page is locked, so it is not possible to insert
a second promise tuple concurrently.
Record the btree blockid on the index scan and move to step 3
When later insert scans see the promise tuple they perform
XactLockTableWait() and when they get control they look again for the
key. If they find a promise tuple with an aborted xid they replace
that value with their own xid and continue as a). Otherwise b).
2. Find existing heap tuple
Find heap tuple.
Check it is actually valid. If not, go back to (1), kill the prior
tuple and follow 1b) path
If it is valid, perform heap_update as normal.
3. Insert new heap tuple
Perform heap_insert
Re-find index tuple using the btree blockid recorded at step 1; this
may require moving right until we find the actual value we are looking
for, so block splits don't negatively affect this approach.
Once re-found we change the index tuple from a promise tuple to a
normal index tuple, by setting tid and removing promise flag. Tuple
remains same length because the value was known when promise tuple
inserted, so this is an inplace update.
Insert other index values normally.
If a transaction that inserted a promise tuple dies, how is that cleaned up?
Any user that sees a dead promise tuple with a value they want will clean it up.
Dead promise tuples can be removed as needed, just as killed tuples
currently are.
VACUUM can remove dead transactions from index as it scans, no problems.
Index bloat is less of a problem than with normal inserts since there
are additional ways of removing promise tuples. Only one index tuple
at a time can have a specific value, so we would actually reduce heap
bloat caused by concurrent inserts.
It's possible we find existing rows that we can't see according to our
snapshot. That is handled in exactly the same as the way we treat
UPDATEs.
There is a potential loop here in that we might find an index tuple,
follow it, find out the tuple is actually dead then return to insert a
promise tuple, only to find that someone else just did that and we
have to wait/re-follow the link to update the new tuple. That is an
extremely unlikely race condition, though possible; there is no heavy
locking to prevent that in this approach. In principle deadlocks are
possible from that, but that is not any different from the current
case where people that insert same key at same time might cause
deadlocks. Its not a common application pattern and not something we
should be protecting against.
All of this is only needed for unique indexes.
It can handled by a new API call for acquire_value_lock() and
release_value_lock(), or similar.
Advantages
* We don't do anything weird in the heap - if this breaks, data is not corrupt
* There is no heap bloat or index bloat above existing levels
* The approach leverages existing mechanism for transaction waiting
* Optimistic approach to value locking will improve performance over
heavy weight locking
Disadvantages
* Not written yet - <1 month to code, still possible for 9.5, doesn't look hard
Other stated possible disadvantages
* Violates existing invariant that every index tuple has a
corresponding heap tuple, which goes back to the Berkeley days.
Currently, we always create heap tuples first, and physically delete
them last. [Why is that a problem? Could be, but why?]
("Deleting them last" implies something is being touched in that
regard by this suggestion. I'm not sure what you are referring to)
* Relatedly, concern about breaking VACUUM. VACUUMing of btrees occurs
with a list of TIDs to kill in index, built from the heap. Current
bulk delete callback cannot be used for this. Super-exclusive lock is
needed to delete tuples in btree page (i.e. VACUUM). Normally skipping
of LockBufferForCleanup() (as added by bbb6e559) works okay in heap
because it tends to imply that list of tids won't be bulk deleted in
index, where we currently cannot skip for failure to quickly acquire
super exclusive lock. So this could make the problem addressed by
bbb6e559 return to some extent.
[Don't see any problems; just test the xid as we scan a promise tuple
and remove it if needed]
"Index-only" bloat becomes a possibility. Implications are not well understood.
[FUD, no reason to believe there is a problem.]
We have to re-find any items using an ordinary index scan, not a tid.
Must match our xid to that.
[Explained above, easy and efficient.]
Doesn't have a strategy for dealing with unprincipled deadlocks, at
least at the moment. Presumably some aspects of #2 could be adopted
here.
[FUD. Unprincipled deadlock still not properly explained as yet. No
way of telling whether it will happen with this approach, or not].
Comments please.
--
Simon Riggs http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 10/01/2014 02:34 PM, Simon Riggs wrote:
Summary of algorithm to use "promise tuples" for concurrency control
during UPSERT1. Perform btree search to location of key, if it exists.
a) If an unkilled index tuple exists, we decide this is an UPDATE and
drop straight thru to step 2
b) If it does not exist, insert a "promise" tuple into unique index(s)
- marked with the xid of the inserting transaction, but using the key.
This happens while the page is locked, so it is not possible to insert
a second promise tuple concurrently.
Record the btree blockid on the index scan and move to step 3
When later insert scans see the promise tuple they perform
XactLockTableWait() and when they get control they look again for the
key. If they find a promise tuple with an aborted xid they replace
that value with their own xid and continue as a). Otherwise b).
XactLockTableWait() waits until the end of transaction, that's not you
want here. If the backend that inserted the promise tuple decides to not
proceed with the insertion, and removes the promise tuple, the backend
waiting on it needs to be woken up more or less immediately, not when
the transaction completes.
I had this exact same issue in my earlier patch versions, fixed it with
a new kind of heavy-weight lock, and a new field in PGPROC
(/messages/by-id/52D00D2D.6030307@vmware.com). That
wasn't very pretty, but it got the job done. Some other design might be
better.
- Heikki
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Wed, Oct 1, 2014 at 4:34 AM, Simon Riggs <simon@2ndquadrant.com> wrote:
Summary of algorithm to use "promise tuples" for concurrency control
during UPSERT
Index bloat is less of a problem than with normal inserts since there
are additional ways of removing promise tuples. Only one index tuple
at a time can have a specific value, so we would actually reduce heap
bloat caused by concurrent inserts.
I am not all that concerned about bloat. I didn't think it was a major
advantage of #1 relative to #2 when I investigated the differences,
and looked at the numbers. And I'm speaking as the advocate of the
design with zero bloat.
It's possible we find existing rows that we can't see according to our
snapshot. That is handled in exactly the same as the way we treat
UPDATEs.
This isn't a special case in the patch. It's more like REPEATABLE READ
and SERIALIZABLE have a special responsibility to make sure they're
not updating an invisible-to-MVCC-snapshot (not "instantaneously
invisible", by which I mean invisible in the
HeapTupleSatisfiesUpdate() sense). Otherwise, we don't care if it's
MVCC-visible or not.
I imagine that by "That is handled in exactly the same as the way we
treat UPDATEs", you mean that we do the EvalPlanQual() stuff. We only
do that in the event of a concurrent UPDATE/DELETE, though. Otherwise,
we trust the underlying relation scan to accurate represent that
tuples pulled up are visible. So I don't understand the comparison
(but tell me if I've misunderstood).
There is a potential loop here in that we might find an index tuple,
follow it, find out the tuple is actually dead then return to insert a
promise tuple, only to find that someone else just did that and we
have to wait/re-follow the link to update the new tuple. That is an
extremely unlikely race condition, though possible; there is no heavy
locking to prevent that in this approach. In principle deadlocks are
possible from that, but that is not any different from the current
case where people that insert same key at same time might cause
deadlocks. Its not a common application pattern and not something we
should be protecting against.
People are going to use this feature in cases where they could almost
use an UPDATE. It will happen if you let it happen. But even if you
don't, a guarantee is infinitely more useful than a non-guarantee to
app developers. I'll be up-front about this: you have very little
chance of getting me to budge on this point. I *really* hate the idea
of allowing this kind of thing. I don't think I'm alone here.
All of this is only needed for unique indexes.
It can handled by a new API call for acquire_value_lock() and
release_value_lock(), or similar.Advantages
* We don't do anything weird in the heap - if this breaks, data is not corrupt
Index corruption leads to wrong answers. I don't think this is a very
good argument, fwiw.
* There is no heap bloat or index bloat above existing levels
Fair enough.
* The approach leverages existing mechanism for transaction waiting
That's not really an advantage. That more or less applies to all designs.
* Optimistic approach to value locking will improve performance over
heavy weight locking
There is no evidence that promise index tuples will perform better. #2
didn't perform better than #1.
Disadvantages
* Not written yet - <1 month to code, still possible for 9.5, doesn't look hard
Maybe, but that is beside the point, which is: If there were any
fundamental problems with either #1 or #2, I think I'd have figured
them out by now. They are less risky today - it might be that #3 turns
out to have the same properties, but I cannot be sure. That counts for
something. I feel perfectly entitled to hold that kind of uncertainty
against any design, tbh.
Other stated possible disadvantages
* Violates existing invariant that every index tuple has a
corresponding heap tuple, which goes back to the Berkeley days.
Currently, we always create heap tuples first, and physically delete
them last. [Why is that a problem? Could be, but why?]
Unknown unknowns. Huge amounts of code must be audited to figure out
that it isn't an issue. So I don't know, but then I'm not the one
making the proposal.
("Deleting them last" implies something is being touched in that
regard by this suggestion. I'm not sure what you are referring to)
The uncertain scope of the problem is a big part of the problem.
* Relatedly, concern about breaking VACUUM. VACUUMing of btrees occurs
with a list of TIDs to kill in index, built from the heap. Current
bulk delete callback cannot be used for this. Super-exclusive lock is
needed to delete tuples in btree page (i.e. VACUUM). Normally skipping
of LockBufferForCleanup() (as added by bbb6e559) works okay in heap
because it tends to imply that list of tids won't be bulk deleted in
index, where we currently cannot skip for failure to quickly acquire
super exclusive lock. So this could make the problem addressed by
bbb6e559 return to some extent.
[Don't see any problems; just test the xid as we scan a promise tuple
and remove it if needed]"Index-only" bloat becomes a possibility. Implications are not well understood.
[FUD, no reason to believe there is a problem.]
"no reason to believe there is a problem" isn't that good a defense. I
know this from experience.
Doesn't have a strategy for dealing with unprincipled deadlocks, at
least at the moment. Presumably some aspects of #2 could be adopted
here.
[FUD. Unprincipled deadlock still not properly explained as yet. No
way of telling whether it will happen with this approach, or not].
What's unclear about unprincipled deadlocks? Heikki went to
considerable effort to have his design meet my standard of not doing
that. I think that there is almost no controversy about whether or not
we need to avoid that at this stage.
If you want a more practical definition, I think it's very unlikely
that I'll accuse any implementation of exhibiting this problem once it
doesn't deadlock with the test-case I presented Heikki with last year
[1]: /messages/by-id/CAM3SWZShbE29KpoD44cVc3vpZJGmDer6k_6FGHiSzeOZGmTFSQ@mail.gmail.com -- Peter Geoghegan
[1]: /messages/by-id/CAM3SWZShbE29KpoD44cVc3vpZJGmDer6k_6FGHiSzeOZGmTFSQ@mail.gmail.com -- Peter Geoghegan
--
Peter Geoghegan
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Wed, Oct 1, 2014 at 12:54 PM, Heikki Linnakangas
<hlinnakangas@vmware.com> wrote:
XactLockTableWait() waits until the end of transaction, that's not you want
here. If the backend that inserted the promise tuple decides to not proceed
with the insertion, and removes the promise tuple, the backend waiting on it
needs to be woken up more or less immediately, not when the transaction
completes.
Simon has not been inconsistent here: he has said that deadlocks may
be possible. I happen to think that allowing them would be a major
mistake on our part, but that's another story.
--
Peter Geoghegan
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Wed, Oct 1, 2014 at 12:59 PM, Peter Geoghegan <pg@heroku.com> wrote:
On Wed, Oct 1, 2014 at 12:54 PM, Heikki Linnakangas
<hlinnakangas@vmware.com> wrote:XactLockTableWait() waits until the end of transaction, that's not you want
here. If the backend that inserted the promise tuple decides to not proceed
with the insertion, and removes the promise tuple, the backend waiting on it
needs to be woken up more or less immediately, not when the transaction
completes.Simon has not been inconsistent here: he has said that deadlocks may
be possible. I happen to think that allowing them would be a major
mistake on our part, but that's another story.
Don't forget that not waiting on XactLockTableWait(), but rather
waiting on a "speculative insertion token" wasn't just the thing that
made your prototype not deadlock - it was also the thing that made its
performance more or less comparable to that of my original value
locking design. Your prototype performed only a fraction as well as my
design before that last revision.
So that's two *excellent* reasons to not use XactLockTableWait() here.
--
Peter Geoghegan
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 1 October 2014 20:54, Heikki Linnakangas <hlinnakangas@vmware.com> wrote:
On 10/01/2014 02:34 PM, Simon Riggs wrote:
...
When later insert scans see the promise tuple they perform
XactLockTableWait() and when they get control they look again for the
key. If they find a promise tuple with an aborted xid they replace
that value with their own xid and continue as a). Otherwise b).XactLockTableWait() waits until the end of transaction, that's not you want
here. If the backend that inserted the promise tuple decides to not proceed
with the insertion, and removes the promise tuple, the backend waiting on it
needs to be woken up more or less immediately, not when the transaction
completes.
There is no "remove promise tuple" part of the above design.
I had this exact same issue in my earlier patch versions, fixed it with a
new kind of heavy-weight lock, and a new field in PGPROC
(/messages/by-id/52D00D2D.6030307@vmware.com). That
wasn't very pretty, but it got the job done. Some other design might be
better.
Currently, if some fool developer decides to insert rows that already
duplicate values in the table, then currently he inserts a heap row,
then sees a potential conflict in the index and waits for the
conflicting xact to end. His fool insert, his wait. That's how btree
does this now.
I don't see any reason why we need to do better for Upsert.
If the row already exists we need to be able to quickly change into an
update, but we still only support one write xact at a time.
The value in the index needs to be protected by a block level lock, so
we can check it quickly, but the eventual heap work is serialized by
transactional semantics.
I think a little perspective is due here and we should stick to the
main use case, not cater for bizarre edge cases. What we are looking
for is something that can decide whether it is an insert or an update
and progress quickly with that. It needs to be correct, but there is
no requirement to be faster than currently possible, in the case of
concurrency.
Any form of tuple locking that uses the general lock manager will not
be usable. I can't see it is worth the overhead of doing that to
protect against deadlocks that would only be experienced by people
doing foolish things.
Please let's not over think and over engineer this. No flying cars please.
--
Simon Riggs http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 10/03/2014 11:07 AM, Simon Riggs wrote:
On 1 October 2014 20:54, Heikki Linnakangas <hlinnakangas@vmware.com> wrote:
On 10/01/2014 02:34 PM, Simon Riggs wrote:
...
When later insert scans see the promise tuple they perform
XactLockTableWait() and when they get control they look again for the
key. If they find a promise tuple with an aborted xid they replace
that value with their own xid and continue as a). Otherwise b).XactLockTableWait() waits until the end of transaction, that's not you want
here. If the backend that inserted the promise tuple decides to not proceed
with the insertion, and removes the promise tuple, the backend waiting on it
needs to be woken up more or less immediately, not when the transaction
completes.There is no "remove promise tuple" part of the above design.
I had this exact same issue in my earlier patch versions, fixed it with a
new kind of heavy-weight lock, and a new field in PGPROC
(/messages/by-id/52D00D2D.6030307@vmware.com). That
wasn't very pretty, but it got the job done. Some other design might be
better.Currently, if some fool developer decides to insert rows that already
duplicate values in the table, then currently he inserts a heap row,
then sees a potential conflict in the index and waits for the
conflicting xact to end. His fool insert, his wait. That's how btree
does this now.
I don't see any reason why we need to do better for Upsert.If the row already exists we need to be able to quickly change into an
update, but we still only support one write xact at a time.
That lowers the bar from what I thought everyone agreed on. Namely, if
two backends run a similar UPSERT command concurrently on a table that
has more than one unique constraint, they might deadlock, causing one of
them to throw an error instead of INSERTing or UPDATEing anything.
I'm sure that's useful enough in many applications, but I'd like to have
a more robust implementation. The shorter we can keep the list of
caveats, the better.
The value in the index needs to be protected by a block level lock, so
we can check it quickly, but the eventual heap work is serialized by
transactional semantics.I think a little perspective is due here and we should stick to the
main use case, not cater for bizarre edge cases.
I'm trying to bisect your thoughts on exactly what use cases you think
we must support, and which ones you consider bizarre edge cases, and
what exactly is acceptable behavior in those edge cases.
What we are looking for is something that can decide whether it is an
insert or an update and progress quickly with that. It needs to be
correct, but there is no requirement to be faster than currently
possible, in the case of concurrency.
I believe we all agree on that.
Any form of tuple locking that uses the general lock manager will not
be usable. I can't see it is worth the overhead of doing that to
protect against deadlocks that would only be experienced by people
doing foolish things.
Maybe, maybe not, but let's define the acceptable behavior first, and
think about the implementation second. I'm pretty sure all of the
approaches discussed so far can be made fast enough, and the bloat
issues can be made small enough, that it doesn't matter much which one
we choose from a performance point of view. The differences are in what
use cases they can support, and the maintainability of the code.
- Heikki
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Fri, Oct 3, 2014 at 2:03 AM, Heikki Linnakangas
<hlinnakangas@vmware.com> wrote:
That lowers the bar from what I thought everyone agreed on. Namely, if two
backends run a similar UPSERT command concurrently on a table that has more
than one unique constraint, they might deadlock, causing one of them to
throw an error instead of INSERTing or UPDATEing anything.
It lowers the bar to a level that I am not willing to limbo dance
under. You don't even need two unique constraints. Nothing as
"complicated" as that is required.
When this happens with MySQL, they have the good sense to call it a
bug [1]MySQL bug #52020 -- Peter Geoghegan, and even fix it. I find the comparison with conventional
insertion entirely unconvincing.
I'm sure that's useful enough in many applications, but I'd like to have a
more robust implementation. The shorter we can keep the list of caveats, the
better.
INSERT and UPDATE are supposed to be fairly well balanced here.
Conflicts are the norm.
The value in the index needs to be protected by a block level lock, so
we can check it quickly, but the eventual heap work is serialized by
transactional semantics.I think a little perspective is due here and we should stick to the
main use case, not cater for bizarre edge cases.I'm trying to bisect your thoughts on exactly what use cases you think we
must support, and which ones you consider bizarre edge cases, and what
exactly is acceptable behavior in those edge cases.
"Lots of concurrency" is not an edge-case.
Any form of tuple locking that uses the general lock manager will not
be usable. I can't see it is worth the overhead of doing that to
protect against deadlocks that would only be experienced by people
doing foolish things.Maybe, maybe not, but let's define the acceptable behavior first, and think
about the implementation second.
+1. Updating a lot with UPSERT is not foolish. That's all it took to
make earlier prototypes deadlock.
I'm pretty sure all of the approaches
discussed so far can be made fast enough, and the bloat issues can be made
small enough, that it doesn't matter much which one we choose from a
performance point of view. The differences are in what use cases they can
support, and the maintainability of the code.
+1
What do we get for giving up on not having unprincipled deadlocks
here? What's the advantage? Assuming that this is a bizarre edge-case
(note: it isn't), what do we get in return for giving up on fixing it?
[1]: MySQL bug #52020 -- Peter Geoghegan
--
Peter Geoghegan
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 3 October 2014 10:03, Heikki Linnakangas <hlinnakangas@vmware.com> wrote:
That lowers the bar from what I thought everyone agreed on. Namely, if two
backends run a similar UPSERT command concurrently on a table that has more
than one unique constraint, they might deadlock, causing one of them to
throw an error instead of INSERTing or UPDATEing anything.
Now we get to a productive discussion, this is good.
When we first make requirements, obviously everyone agrees a long list
of things since there is initially not much reason to say No to it. As
we go towards implementation we begin to understand the true price of
meeting each requirement. It was good that this detail was raised and
sensible to attempt to avoid unprincipled deadlocks. If the price of
avoiding them is high, it is worth reconsidering how important that
is.
My view is that I can't see the above use case from happening in real
situations, except by infrequent mistake. In most cases, unique
indexes represent some form of object identity and those don't change
frequently in the real world. So to be changing two unique fields at
the same time and it not representing some form of business process
error that people would like to see fail anyway, I'd be surprised by.
If someone has an example of that in a real, common case then I would
like to see it and I would revise my view accordingly
We are frequently hampered by trying to design something that can sing
and dance at the same time. That thought is exactly how we are looking
at upsert now, not merge. So trimming our objectives to what makes
sense is an accepted part of this project already.
Any form of tuple locking that uses the general lock manager will not
be usable. I can't see it is worth the overhead of doing that to
protect against deadlocks that would only be experienced by people
doing foolish things.Maybe, maybe not, but let's define the acceptable behavior first, and think
about the implementation second.
Hand in hand, I think, given the other constraints of time, review,
maintainability etc..
I'm pretty sure all of the approaches
discussed so far can be made fast enough, and the bloat issues can be made
small enough, that it doesn't matter much which one we choose from a
performance point of view. The differences are in what use cases they can
support, and the maintainability of the code.
The discussion of approaches has up to now focused only on what
impossibities exist, with a "we must do this because feature A can't
do aspect X". I haven't yet seen much discussion of maintainability of
code, but I would guess simpler is better, overall.
Realistically, I won't be coding any separate approaches, so this is
down to Peter and maybe yourself Heikki. I hope only to avoid
foreclosing viable and simple approaches for the wrong reasons. There
are many other considerations that make up the final view.
--
Simon Riggs http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Fri, Oct 3, 2014 at 2:50 AM, Simon Riggs <simon@2ndquadrant.com> wrote:
My view is that I can't see the above use case from happening in real
situations, except by infrequent mistake. In most cases, unique
indexes represent some form of object identity and those don't change
frequently in the real world. So to be changing two unique fields at
the same time and it not representing some form of business process
error that people would like to see fail anyway, I'd be surprised by.
Are we talking about two different things here?
Unprincipled deadlocks can be seen without updating any constrained
column in the UPSERT. The test-case that originally highlighted the
issue only had one unique index, and it was *not* in the update's
targetlist. See:
https://wiki.postgresql.org/wiki/Value_locking#.22Unprincipled_Deadlocking.22_and_value_locking
--
Peter Geoghegan
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 3 October 2014 10:32, Peter Geoghegan <pg@heroku.com> wrote:
On Fri, Oct 3, 2014 at 2:03 AM, Heikki Linnakangas
<hlinnakangas@vmware.com> wrote:That lowers the bar from what I thought everyone agreed on. Namely, if two
backends run a similar UPSERT command concurrently on a table that has more
than one unique constraint, they might deadlock, causing one of them to
throw an error instead of INSERTing or UPDATEing anything.It lowers the bar to a level that I am not willing to limbo dance
under. You don't even need two unique constraints. Nothing as
"complicated" as that is required.When this happens with MySQL, they have the good sense to call it a
bug [1], and even fix it. I find the comparison with conventional
insertion entirely unconvincing.
Is there a test case that demonstrates the problem?
--
Simon Riggs http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 3 October 2014 10:57, Peter Geoghegan <pg@heroku.com> wrote:
On Fri, Oct 3, 2014 at 2:50 AM, Simon Riggs <simon@2ndquadrant.com> wrote:
My view is that I can't see the above use case from happening in real
situations, except by infrequent mistake. In most cases, unique
indexes represent some form of object identity and those don't change
frequently in the real world. So to be changing two unique fields at
the same time and it not representing some form of business process
error that people would like to see fail anyway, I'd be surprised by.Are we talking about two different things here?
Unprincipled deadlocks can be seen without updating any constrained
column in the UPSERT. The test-case that originally highlighted the
issue only had one unique index, and it was *not* in the update's
targetlist. See:https://wiki.postgresql.org/wiki/Value_locking#.22Unprincipled_Deadlocking.22_and_value_locking
I followed that to a wiki page, then clicked again to an old email. No
test case.
--
Simon Riggs http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Fri, Oct 3, 2014 at 3:04 AM, Simon Riggs <simon@2ndquadrant.com> wrote:
Is there a test case that demonstrates the problem?
Yes. See my e-mail to Heikki here:
/messages/by-id/CAM3SWZShbE29KpoD44cVc3vpZJGmDer6k_6FGHiSzeOZGmTFSQ@mail.gmail.com
Testcase is attached.
--
Peter Geoghegan
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 10/03/2014 01:05 PM, Peter Geoghegan wrote:
On Fri, Oct 3, 2014 at 3:04 AM, Simon Riggs <simon@2ndquadrant.com> wrote:
Is there a test case that demonstrates the problem?
Yes. See my e-mail to Heikki here:
/messages/by-id/CAM3SWZShbE29KpoD44cVc3vpZJGmDer6k_6FGHiSzeOZGmTFSQ@mail.gmail.com
Testcase is attached.
Simon's approach would actually pass that test case just fine. It
inserts the (promise) index tuple first, and heap tuple only after that.
It will fail the test case with more than one unique index, however.
- Heikki
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Fri, Oct 3, 2014 at 3:54 AM, Heikki Linnakangas
<hlinnakangas@vmware.com> wrote:
Simon's approach would actually pass that test case just fine. It inserts
the (promise) index tuple first, and heap tuple only after that. It will
fail the test case with more than one unique index, however.
Oh, I see. Still, I don't think you need to UPDATE a
uniquely-constrained attribute - even if updating constrained
attributes is rare (dubious), non-HOT updates will have the same
effect, no? I still think that's unacceptable.
In any case, I still don't see what this buys us over the other two
designs. What's the pay-off for giving up on the general avoidance of
unprincipled deadlocks?
--
Peter Geoghegan
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 3 October 2014 11:54, Heikki Linnakangas <hlinnakangas@vmware.com> wrote:
Simon's approach would actually pass that test case just fine. It inserts
the (promise) index tuple first, and heap tuple only after that. It will
fail the test case with more than one unique index, however.
Please explain what you mean by "fail" here?
My understanding of what you're saying is that if
* we have a table with >1 unique index
* and we update the values of the uniquely index columns (e.g. PK update)
* on both of the uniquely indexed column sets
then we get occaisonal deadlocks, just as we would do using current
UPDATE/INSERT.
Is their a business use case that requires that? (Or exactly what you
meant, if that isn't it?)
My view is if we are going to base the whole design on this point,
then we need to have it very clearly accessible for all to understand.
--
Simon Riggs http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 10/06/2014 03:05 PM, Simon Riggs wrote:
On 3 October 2014 11:54, Heikki Linnakangas <hlinnakangas@vmware.com> wrote:
Simon's approach would actually pass that test case just fine. It inserts
the (promise) index tuple first, and heap tuple only after that. It will
fail the test case with more than one unique index, however.Please explain what you mean by "fail" here?
I meant that the test case will sometimes deadlock, and some
transactions will therefore be rolled back.
My understanding of what you're saying is that if
* we have a table with >1 unique index
* and we update the values of the uniquely index columns (e.g. PK update)
* on both of the uniquely indexed column sets
then we get occaisonal deadlocks, just as we would do using current
UPDATE/INSERT.
Right. To be precise: you don't need to update both of the columns in
the same transaction, it's enough that some of the concurrent
transactions update one column, while other transactions update the
other column.
Is their a business use case that requires that?
I don't know. Conceivably any use case where you have two unique
constraints to begin with.
- Heikki
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 10/06/2014 03:21 PM, Heikki Linnakangas wrote:
On 10/06/2014 03:05 PM, Simon Riggs wrote:
My understanding of what you're saying is that if
* we have a table with >1 unique index
* and we update the values of the uniquely index columns (e.g. PK update)
* on both of the uniquely indexed column sets
then we get occaisonal deadlocks, just as we would do using current
UPDATE/INSERT.Right. To be precise: you don't need to update both of the columns in
the same transaction, it's enough that some of the concurrent
transactions update one column, while other transactions update the
other column.
Ok, that didn't make much sense. With UPSERT, you have to specify values
for both columns. But it's sufficient that you have a mix of
transactions where only some are UPSERTs, and others are regular UPDATEs
on one of the columns.
- Heikki
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 6 October 2014 13:21, Heikki Linnakangas <hlinnakangas@vmware.com> wrote:
My understanding of what you're saying is that if
* we have a table with >1 unique index
* and we update the values of the uniquely index columns (e.g. PK update)
* on both of the uniquely indexed column sets
then we get occaisonal deadlocks, just as we would do using current
UPDATE/INSERT.Right. To be precise: you don't need to update both of the columns in the
same transaction, it's enough that some of the concurrent transactions
update one column, while other transactions update the other column.
CREATE TABLE foo
(id1 integer not null primary key
,id2 integer not null unique
,val integer);
Given the table above, which one do we mean?
1. When we mix UPDATE foo SET id2 = X WHERE id1 = Y; and UPDATE foo
SET id1 = Y WHERE id2 = X; we can deadlock
2. When we mix UPDATE foo SET val = Z WHERE id1 = Y; and UPDATE foo
SET val = W WHERE id2 = X; we can deadlock
(2) is a common use case, (1) is a very rare use case and most likely
a poor design
If the user wishes to protect against such deadlocks they retain the
option to use row locking. Yes?
--
Simon Riggs http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 10/06/2014 04:44 PM, Simon Riggs wrote:
On 6 October 2014 13:21, Heikki Linnakangas <hlinnakangas@vmware.com> wrote:
My understanding of what you're saying is that if
* we have a table with >1 unique index
* and we update the values of the uniquely index columns (e.g. PK update)
* on both of the uniquely indexed column sets
then we get occaisonal deadlocks, just as we would do using current
UPDATE/INSERT.Right. To be precise: you don't need to update both of the columns in the
same transaction, it's enough that some of the concurrent transactions
update one column, while other transactions update the other column.CREATE TABLE foo
(id1 integer not null primary key
,id2 integer not null unique
,val integer);Given the table above, which one do we mean?
1. When we mix UPDATE foo SET id2 = X WHERE id1 = Y; and UPDATE foo
SET id1 = Y WHERE id2 = X; we can deadlock
2. When we mix UPDATE foo SET val = Z WHERE id1 = Y; and UPDATE foo
SET val = W WHERE id2 = X; we can deadlock(2) is a common use case, (1) is a very rare use case and most likely
a poor design
Well, at least one of the statements has to be an UPSERT, and at least
one of them has to update a column with a unique constraint on it. This
pair of transactions could deadlock, for example:
Transaction 1:
INSERT INTO foo VALUES (Y, X, Z) ON CONFLICT IGNORE;
Transaction 2:
UPDATE foo SET id2 = X WHERE id1 = Y;
That's made-up syntax, but the idea is that the first transaction
attempts to insert a row with values id1=Y, id2=X, val=Z. If that fails
because of a row with id1=Y or id2=X already exists, then it's supposed
to do nothing.
If the user wishes to protect against such deadlocks they retain the
option to use row locking. Yes?
Sorry, I didn't understand that. Row locking?
In general, this is of course a lot easier to implement if we restrict
it so that it only works in some limited cases. That may be fine, but
then we have to be able to document clearly what the limitations are,
and throw an error if you violate those limitations.
- Heikki
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 6 October 2014 15:04, Heikki Linnakangas <hlinnakangas@vmware.com> wrote:
On 10/06/2014 04:44 PM, Simon Riggs wrote:
On 6 October 2014 13:21, Heikki Linnakangas <hlinnakangas@vmware.com>
wrote:My understanding of what you're saying is that if
* we have a table with >1 unique index
* and we update the values of the uniquely index columns (e.g. PK
update)
* on both of the uniquely indexed column sets
then we get occaisonal deadlocks, just as we would do using current
UPDATE/INSERT.Right. To be precise: you don't need to update both of the columns in the
same transaction, it's enough that some of the concurrent transactions
update one column, while other transactions update the other column.CREATE TABLE foo
(id1 integer not null primary key
,id2 integer not null unique
,val integer);Given the table above, which one do we mean?
1. When we mix UPDATE foo SET id2 = X WHERE id1 = Y; and UPDATE foo
SET id1 = Y WHERE id2 = X; we can deadlock
2. When we mix UPDATE foo SET val = Z WHERE id1 = Y; and UPDATE foo
SET val = W WHERE id2 = X; we can deadlock(2) is a common use case, (1) is a very rare use case and most likely
a poor designWell, at least one of the statements has to be an UPSERT, and at least one
of them has to update a column with a unique constraint on it. This pair of
transactions could deadlock, for example:Transaction 1:
INSERT INTO foo VALUES (Y, X, Z) ON CONFLICT IGNORE;
Transaction 2:
UPDATE foo SET id2 = X WHERE id1 = Y;That's made-up syntax, but the idea is that the first transaction attempts
to insert a row with values id1=Y, id2=X, val=Z. If that fails because of a
row with id1=Y or id2=X already exists, then it's supposed to do nothing.
Lets look at a real world example
CREATE TABLE citizen
(ssn integer not null primary key
,email text not null unique
,tax_amount decimal);
Transaction 1:
INSERT INTO citizen VALUES (555123456, 'simon@2ndQuadrant.com',
1000.00) ON CONFLICT IGNORE;
Transaction 2:
UPDATE foo SET email = 'simon@2ndQuadrant.com', tax_amount = 1000.00
WHERE ssn = 555123456;
OK, now I understand how a deadlock is possible. Thanks for your help.
Again I note that there is no isolation test that refers to this
situation, nor any documentation, internal or user facing that
describes the situation or its workaround.
My feeling is that is an unlikely situation. To have two actors
concurrently updating the same data AND in different ways from two
different angles.
How likely is it that we would issue those two transactions
concurrently AND we would be concerned because this caused an error?
If the tax_amount was the same, it wouldn't matter that one failed.
If the tax_amount differeed, we would want to know about the error,
not accept it in silence.
Are any of those things substantially worse than the current situation
using INSERT/UPDATE loops?
It might be nice if the above never deadlocked. What is the price of
ensuring that in terms of code maintainability and performance? What
would this do to COPY performance?
If the user wishes to protect against such deadlocks they retain the
option to use row locking. Yes?Sorry, I didn't understand that. Row locking?
I think that thought doesn't apply here.
In general, this is of course a lot easier to implement if we restrict it so
that it only works in some limited cases. That may be fine, but then we have
to be able to document clearly what the limitations are, and throw an error
if you violate those limitations.
Seems reasonable.
My point here is to establish that...
a) there are multiple ways to implement the UPSERT feature and none
should be thrown away too quickly
b) the current patch does not implement something we all agree on yet
c) not all requirements have been properly documented, understood or
agreed by hackers
If we want to move forwards we need to agree things based upon clarity
and real world usage.
It may be that people on reading this now believe Peter's HW locking
approach is the best. I'm happy to go with consensus.
My feeling is that substantially more work is required on explaining
the details around multiple unique index constraints, trigger
behaviour and various other corner cases.
--
Simon Riggs http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Mon, Oct 6, 2014 at 5:33 PM, Simon Riggs <simon@2ndquadrant.com> wrote:
Lets look at a real world example
CREATE TABLE citizen
(ssn integer not null primary key
,email text not null unique
,tax_amount decimal);Transaction 1:
INSERT INTO citizen VALUES (555123456, 'simon@2ndQuadrant.com',
1000.00) ON CONFLICT IGNORE;
Transaction 2:
UPDATE foo SET email = 'simon@2ndQuadrant.com', tax_amount = 1000.00
WHERE ssn = 555123456;OK, now I understand how a deadlock is possible. Thanks for your help.
Again I note that there is no isolation test that refers to this
situation, nor any documentation, internal or user facing that
describes the situation or its workaround.
This seems like a concern specific to other approaches to value
locking. But fair enough.
My feeling is that is an unlikely situation. To have two actors
concurrently updating the same data AND in different ways from two
different angles.
Hard to say for sure.
How likely is it that we would issue those two transactions
concurrently AND we would be concerned because this caused an error?
If the tax_amount was the same, it wouldn't matter that one failed.
If the tax_amount differeed, we would want to know about the error,
not accept it in silence.Are any of those things substantially worse than the current situation
using INSERT/UPDATE loops?
Yes, because the new feature is supposed to make it so that you
yourself don't have to put your UPSERT statement in a loop with
subxacts. Taking away the burden of having to think about this stuff
is something I'm striving for here.
It might be nice if the above never deadlocked. What is the price of
ensuring that in terms of code maintainability and performance?
I am going to reserve judgement on that, at least for a little while.
It seems like the person proposing an alternative ought to have a
better sense of what the price of avoiding this is. I'd understand
what you were getting at more here if it immediately made our lives
easier in some obvious way. I don't see that it does, though I admit
that I may simply not understand where you're coming from. So sure,
let's not be prejudiced about what's important, but at the same time I
don't see that either Heikki or I have actually been inflexible to a
degree that hurts things WRT not giving up on important high-level-ish
goals.
I am not completely inflexible on "never error". I am very close to
totally inflexible, though. I think I could live with an error that
literally no one would ever see. For example, we could error if there
was an excessive number of retries, which I find acceptable because it
will never happen in the real world. I tend to think that what you're
talking about is pretty far from that, though.
My point here is to establish that...
a) there are multiple ways to implement the UPSERT feature and none
should be thrown away too quickly
b) the current patch does not implement something we all agree on yet
c) not all requirements have been properly documented, understood or
agreed by hackersIf we want to move forwards we need to agree things based upon clarity
and real world usage.
I certainly agree with that.
It may be that people on reading this now believe Peter's HW locking
approach is the best. I'm happy to go with consensus.
I bet you didn't think that you'd say that a week ago. :-)
I hope I don't sound smug when I say that. I just mean, as you say,
that we all need to keep an open mind on this. A healthy respect for
the problem is recommended. I think it's still possible that there are
problems with design #1, even on its own terms.
My feeling is that substantially more work is required on explaining
the details around multiple unique index constraints, trigger
behaviour and various other corner cases.
Probably. Ideally, we should do that in a way driven by real-world
prototypes. In that spirit, I attach a new version of my patch, but
now implemented using approach #2 to value locking. I haven't spent
all that much time testing this (at least recently, in this form), but
it does pass all existing tests, including my stress-tests when run
for half an hour.
A lot of those corner cases you mention are big concerns. It's much
easier to identify these issues by breaking real implementations. So
surprisingly, to a certain extent (with something like this) it makes
sense to have requirements driven by actual implementations. If we
cannot do this iteratively, we are likely to fail. That's just how it
is, I think.
--
Peter Geoghegan
Attachments:
0002-Support-INSERT-.-ON-CONFLICT-UPDATE-IGNORE.patch.gzapplication/x-gzip; name=0002-Support-INSERT-.-ON-CONFLICT-UPDATE-IGNORE.patch.gzDownload
�dO3T 0002-Support-INSERT-.-ON-CONFLICT-UPDATE-IGNORE.patch �[ys�6����Xo��l��|�y��c�m|�Gf�^��B$$1�H� }l���~� )R�<�$���"��F�t�3qp0:P����e�7;{-��{�������T��h,{#q�V�E�@�ZG����Z����k�H����TMd �g>�~���!i8���������������d�vW���Z������Z��m2�E9�������������?q���a���m��N4
qu)N�.��'w���������]~�����Q��M=-�0��X�����e����>iqzq.�"V3�B&�4���C�����/�x*c�"�*�iQ8J:S���}��8��J���� �k����x�92����z�4�����f�Q�G�'J����7�������#����K����]�\#��� �<*1��T���|PAC����,�H/s�����K�O������DQ���IH���g&��4
�ms6OgIc^�`F(A;�)!�(��c�d������+�D�� ?���=_(��&�NCt��!�i�[ '�4�s.�l�'�c("v��(�J��U�m��a���O�����I� �# &N� ����MR��g T��m��*�M�qr�1�v�gf�:�� �(�mhR�5��Wio�v�Z��y#l�i��Q���=x
04� ��~#�&���[�[��8� 5��<��e]��$��!�k_?%��n��r�+O�h�z�Ac�X��+2y�|OF/b���|
[�����O����2����\p|������I+,2JhXQ B��"M� z���H�B&.hO�^���ON��\O����f�/#:(��"�"�����:��%02K�$��� �wfh�@1�a`���c������!����I6D"������fbs^��i��?Z����}l������ ���W�-��4�����b����B�e���`�+���KYm��Wr�R���kF��y0��������;9�9S��10"��O����K��n���c���
���pZ����1W$q���9�3�yya�A�F�
���_
$�IzT���@�K &L|�>�N��Y�� �����-��R5�*�5m����;����t�L=f7U� (l2c�����c�$l:��3�mU�R2b����^�.u'I�d��[����E.�pX����X�y2bLX��0v�:�s�U�_q#�5,�z��w�\�� ��S�X �l�5��#Yb�7��b7��}����������'?#��+q�1���<�d,E��D&�)%�m�(�[g��f�M�1���83�0�p��v�`�&a;S�wWI �Z�h�I�q�������yQF_h�wL�"�k�E��D��7TR�B��C�!���?�* T0+m����b�P�1`�f���nL%2�O+��mzP!f�~ ��)���G�b2:�cp�Bx"5�nS��D����&������n�.Hl��9)T.P��~����o.�?�m�i �&��D6'�j�X�P"��f� T�R��+�Ho��O��M��$t����dV������=�O�/X��� �PGNsD��M�@&�9Ur������aG�W/Fq�}��0 9�2$\���I�}���)d�P�ljC�nfp����h=��e���A�g��������qQJ���!��u�d:�]��N�x2A��sD�$�%J�[�7A�\m�w���{�[�Gh��I���P����A�yH-(��`Y�
�{���� ����\�/�<��C��e���7�L�t��u������r�p�M�������,��%H�"��<0��*,�RxT�K������ZA���X�Y��c����.�Oja'\�K���[�COJ|M����d�l��j{�2��S��*�����H���� ���N���Q$����}c����l�?�~�pi 6!���n��r�\����e�
tB5c��5��{����"W���:]'T���+��g�U����L�l[����0��_��Z?\�(�r���o-4���
c-$��Wi]��h�3�t�|]��5��'J�^���D��s��w���qNW �+���d�H
y�
,��vk Y��4��T_WI5V����{���+��������� �{�SWhBuj{�L�����-<k�����yR��T���E�>�b!�oM�Go���j����t;�F�9tT�;]��n�2��SQ���|���w���8B�x��d���'*�������-���0����b������0�n����U�����]����7����<�U/���V���I8J��]o��s�; v6��������P���<as.}�=���_{c�� ������<g2R,'2Zr0_I}��$�b����&�����JA�JT��M=S,,W�W
�����J��zrW�FCtz�4r)U�W�,)�++Iy���R^�D���t����Hy����k���q(��0�k�q|d� ������>���r�2�#����B!���������2�������HQ+�������������"��'W���Y��Pw�����������]Mc���T7�4����l�K���������Ez��x����g!.T��_I%�4������~��%V'�j�9-8�C){��[��/"1
��e��Z�ve��#e8�������K���ck����,���������(����ye`���^&�j�`�YZPa�9`��>ST
�iR+�A�+;���������vH�s~|7��{|�����/^�}���S �)���J�����O��3A�a�����*#� �x�4���kz�6V�P����������������8k���$G�&X��q��%\Ks^S��b1AN5d�xF{����=�4����x}�[`��81���+�����/O�'7p�r7���n��Z�l��s�tR[N�� |2�x2mB;���L;�U��p#
HR2�F���XE<�h���u)���,��[�.��YJ5=7��;���&��@�����}@{�0Q�s��j���@�<�,��J��Q��kR��(��k�r����S���w�� �y&�!�q8��ah��jeA����]M����f��U�w���*55i�� �������`�� %���pD}q�������i��1Qp���7`yS�<��[�[���V��%A���2f�3��I�N���@��g&H4e
�mY�}� ;���{��Ox���� ����I9i����~�$:fD��� Z���V����n6�����y����(�A�����f6�n'�b;Fq����L�������Ax.k5����b�,�IR
3����$�ZV�����Xx��K�N������%�]e��0P,�fE|����(��q��
f�*sd���<���; |�����p�Pkf�<}��CVPH�2lO�������lI1������ah��2��� @�3��[���O�|
o��y���X�A��~�F���x�0�m�'~�<0����8��W�sW��p����o������c��59���f�)��/DH��tr|���������z�������a���pb�5���O���R -3��=�8�Y����0�B�|P����?��[����-�7#0���E8$���&tk�=����e�N�I$��@�l�S>�n��~�6���YF�%a���&B�ypj2).@��H�V=��=����-F��JeK.����*_����U�a��,��F�I���
�����*�e����X�P�-c��m���,BZ��N����#�[��^�����[�.%�f�\lR��1j�WO���g������r+�t�?X�o���"��pF���C�w���u��.%Z��m!�f�����-]b� ��c[�q�Hsi1�����H9�f���r�~������&�|�L�\�*���E�jR�� l�Do#)������ws���/��$Y�FjBc��#j"��Iq��?�����E�Dj�`0-v� �Qh�
Ew��M��n���b0�~!�OJP�S�(#�ST�<�<W�=��1Jb=-��e��L�^����.v%��IaJ�Qc8�@o�IS'|W��D
B��e��B;�N�sA����R��9����M�z�}��-�y16�L���>�b��g����?UN�B�Y�����B.�e�r8Vu�� 3�>~������rB=��C��CVW�������\z���>���'������8-�m�yF���4IA ���]2le��������i�T��_���3Y(�V#$�C2�oE���r��B�l��1����e�&59�n��GZ���o��@�|=u��L���eFy�D�����8�����2+LS������;�Py��e������2��&���MV����4��L���E����F�����n��o340w8{����|����/�V�{A��q�
OF�u4��t����g.Q�������\��ms���8�^���Cf�����lWq�l����2P�Nc.�T���
6sB����q�
���1��N���hJ6Ar����IL�*j�iS�-n�2��������M�*��� K����ER�-�4�l��`@P���fH�ok����fH)_-�����F��:�[��7p���s�Op}���� �g��������N�E�A�b����~a�A��Y 7e� dW�m��������v�����Go�F�F�Z��Y9_��f�s�&m`�fr�Ed5�����3<�:�qxI��j��7�n>���
B�+r�v��!d�<"�{ �e�s!>Q��E��&���*�m��O��d�D��*���s9x��i��$u���,���{��-&��0_����T�J��J,�B�1~�k�V�}����>���a�N�96�
�4@FNw���8�F���qJ���'�v_(��`��=�^��L���k8-��OrY�@�9��\����c�pM>����h����C������m�%,)�Fk+��dx��lN����n�g�R.�!H.�s[N����\�D��1����������n�ou�����Vk����*�{0�������a�Zs������������"6g(��;��G�����;����������U��{s���%��1�$=&~������?"�a\��b��h�]H�k�>5�����Ql*n��O;���
3��H��}�l��������x[�L����4^�����^�BP��l��u�T�����2l��M3?Hs��A��we�v�v.6�����C�pg6j��Rd�=Tzx�d�8���m�����^���;��N����8����;u��/?����Gh������!UB�s�����Y�`(AeF��l�3���Y|H,b]+�(W1m�>��:���d����@���S��[��kk�w���E�C�3��*��(���,?�G��j��7g ���6����
:6N��e<31h�U��h�� ��N5cJ�<�8��|~�ihF��{Ji��a&��WJ�f����z���%��j�(() ��Rw0��s ���,-G2���,ER`Hi��BK��}Y�_��+�1-����U"Q3��d�eN�R���o|U�$�1� ^�x���oLB�������[��z��aMf�tk��!rT��6
��.NPN/����*������� ������.����/P�1�FV
�p��K�{����{��6�dm�3�Y�n�0BF�����A�u
�`���^Z))�5�J���S���x"bO9H��Z�����m s��{��Vih"C�����B���G��v���k?"���Mz zf'��L56.�U9�Id[��H)q8�, ���q�Z�����z�8��`4��6������HyTf9�#_3�����6.%�7Fl���l��4�9Jx'����x�}A�c��vr�=��S��@u��o� ���8Q�������w����vvp~�<8fsC���R�n�p%������J���c� �Qi�U��{�U��-���<�1��D��c��#K��pD���#=J��� � b ���&��>?����d>BT��e��I����ys,����(������3�9/�������P�dyK��eBg��#�0�K�
�M���uHaY��
��J2�q�����Jc������*y%I}}{�V[_��&[q��������%�����d����Ux=����X��jW���
�z$��Zjs
/����rru|��Xz�@I�_4��"=X��<�T��$R_��������(�Q�k�����<t�++U�D \�A��k\Z��E]utG1����U����RV��4v���=����7��cLwT�����#]l�i2L�g��������Ui�)��(!V/g��^��Z�n/utD�s�wF}�/:��F��/p __�7������Q�7���^>�Sh���3�Z\�aN��bP�����;t�r
��
�F}�k��]��
�������p����v���\�<h#Pk~L$p�u�����N��P=��?�J���h��C�����t��u�`� ��q4��&I���d���s|�]a�f;��NDk�2���<�GZ�S���5�E�Q�������y ?g��3��h@�q�����2_���+���mtwh���6�6�yC<G�%�@���.y|��q�t�w��Qz��c����v���i�N ��\~��,���o3t��,�n"31f'�l�2�����=����XG|_n��_���F3Du��E�o��km�2
�
�\�����cc{wJ����S��$���^<�,!�iQ��_:_��q2~���{�GZ����%�a�����*�gV�eGce~�k�Jr��J����Q�s�:Y�������d8��}�L%r$��F��:����i�\��[� w[�?�����
��e��i�w���N�V�����3�S�[)�z
�1���* �At����+��r�������Z�o/VtS�������q#�+�:����$B�tC���s�������^��{7�3rc�\�vK�i����6�
/!�#����Y�/R�CgEKe1AJ7��&�no������~}{�����&��3��`����+�,��G��`��"�P%�l��X ��z-�n�,� ��S�n�#��Me�^1��)������?" �ie�P����x�������7�������a�/is���PU��up.3/+��`�U����a}��O~z�'M�����j���Y��0x��&������'I�w��L� *,H���=� n��U0�=��pM
W�`7��i��{�l���A���[��b����M���]�%����'�b{�6���S���='�� ��CTu�0��L���d�A)������tE'�oC���RZ�T| 5�����O�������~]�����4��������K��/�����U�T0���Z
\������q���8�]�� ��b��I9��1?� �B��B�mo
1��f� �?��VF'����@x����.v��i:%9�1�0�%)s��J@5��D|%����(Z]
�0A�D�E8o^�7����=����������~�4��y�z$����*Z��,�I�t�t���$��(]P\6�iQ�-�/b����?�P��������,u[6
87^����P"Z����,���c��Q���Q�����^%����l�#9j70�r��@�/�NMr���{��{�>�j�@��o#iT�u!J��I�~9���,�_T��(y{]+�U�����J�������
������6��{�����ZTJ�������u��
~}p%������@��z8��A��M�bA:�p���k���:&C��h�� ����]�������cj�O�H�L��W�I4����o���������������9��d?%@TF����]M�� ��3��z�F��'��k�p�y�J�����8�[O�n]m���,[�e��4F�4I)��'������C���M���`�e�� A3�rO\U�X%iZ����\�q��s\8NW���Jv ������:�W�,N$�I���k$a���<L4�|�������P4�n��nU�+�0���?5h ��2��3�Q��N���$Z�o�7�3< �C�L1v�f���>3���^82t����`���d8��0�*8H��<?Ba����� R�^�Q���_9�e8��z����%v��CF ����@���]��!��nI��K�i�v��;���Oo�.�F�5N���d�S{� ��uu�rQ!�4c��#i����tE;��8Hrt�k�����9<��r����Cs����������R�zM�}D8.�}}|���,>��n��g�i�0C���kJ?7�mQ�={R������i�X�`�@���=�/��0����z��8�0�s�!5i$�B8��2�����]��F��N�#��Xw(��a��{���z��98x�KDt���
�p�&id��:B� ��B�� j�"�[�3G�z:f�5�����j�S��t��k���ikr��j0�������D�T%�\V���?�
6���-�?c��BYX�S�E;huv�p���mgf������qa�UL��:�������<z7�)�����&�D����8��Q`���/����o�(rR����3���O5��ct�&�D�0�WBMcA�}6�E�h\���r�D��A'1�~�3g
[���,D�]���)��
O��6�����������a/�����������)��3>Dc$ G��{ z��YND���73�5L8�0�O�}�f�(/�d+�����l�I�b�=4����u�������H��Y8���2y��
�>~`�����
)�������Fy /R�Q^��:VeQ61�K���&M7�
����{��N�#&�H�a�HRRW���dM�D�[���UP�'��n_�;����?>��%�;�������*��~Z#�K�.tAxF�����O�����E��Y�u )o#J���m�Y�����(�LKK��o�5>��|j�����?Q@��sE�����V'�����:ye.����*O����y��M&�������\���_�)�a��v���OI��W�@����[ �\-�������),���������h�������/�������������d�):�n��A6�-��<N<K�"�X���N,`��4vr�I[���+nm�\��d� Dv�V����a��7"��p�a��m�f:���$������:agk)�*�yg�?��)����:xq��Q��Gr�pn��8���9�=<h�.��!�Nw�N7���Y�Je=3�'��L�&�1��w^E�6����P�@�>�~(gP?��C��dB���H����k�%F�f����.eQ'2^ee�w.����������3�+�A=�F+��C�� �\�5�Vcp����! ��c��|��O�N�&:�-�����r�V-�<�wg�j�A����*�-0�<nPj�����a�(�����^��I��gt��#u^����;����*v��4������9m���)�B��m �����=������^�"�HY5&|{b��4�n�pP��m�� ��L�]g����t���9���n�:EK��3N�pT�q���S�XP�2��$��h����0y ,,����+�k�}����P0`�*^����:����s �s��!Ks��B�?�x�B/s�6�
��B��Xs���s�kR�,1���������m���R/��{�mK �t��tp��P�J������R�����<k�l����Q������J(�a�^3D��8�w2sr%?��jN�"yu�Qg^��,����� ��_�1��}S�
�N��Y�>?HZ�H<�M�X,��H:�T��n��)Gc^d%��! Y�&���Fx��8;��4�����&~8�'�EW%+��A��[^b�Y�?Y��'x
�V���B�=�
Z}�8���Y���y�����_�����W>J��]aH�`�Y��}�#kT�4�<�^��Z�l�*�Y�w���'��.���0�4���H-�s��9�0#��&��
����K�-F��]�3lRM���c���G�VO�l%�D5���p��x�e��ANr
NYn �UljV��P?���R=O������oj����f"aL��e�?�e�Wp�iFi��i��N-2��W�_��k�a;��^-E�Z���>�u��3�������H�W4 ��k�&��������/�&^�5
-�����*�e1�P:���qN�R����U���w����y��(EY�U;X}�=����{�l�
���I���:_�} ���R���Y6y������u6�j�����G\�UO"9�����s�.w��3q�i�y�tM��4���&\�b5�����ay��_W�[��bXF���A,TS�p�����A�(��c��p�h��w�9�/�Xj�t���X1��W�`�h�cnZ�M�����G�aW� �-{I*a��Y�� d��1���u�BVA������N�����?{�l����S�]7��a�x�OE��9�A{�6k���������f��X�
�z�V���_��J�~v�|R��D�f=�����_s1�a�K���[?P�-O��7uc!FkW8������~8u��}4�h�Z���h6���C�3����7X�"��{�� �
0!'�
@��N8�u���U���,`�����_ �g�L/�-���{���B*B������t�<��B�C�,s��� &q�`t��k&����y���V~�S��N�*�"5�71�������q�������+�*-��}�f,3`4L>l5����~F����������a@e&>�� �0\W��J5a���aR-���E��Z���IlF,DO���O5�V��XK;�����Uu����Z����,��
D��������~c"��:Sm�������4��OL
������I��m?������;mf2���R���us�����'�<av�;�nf�����)��h�#�W��@�7K���m=�m�����m:~g|����~�����o��6��z}�8"�
��C^�9����m#���;�F�k�B���"�E�m#y�g��-W��$���p��C�E��>�AAC�����n�����L�g��hj�'��S��b����6����u��7{xC�(������eW���/P\�lJ���,��.-�[���T��Hf�d� S���l����UA�]1�@��!S�L><�����N;��a�tdD��o�I�a
�?r�P@�h�'����i��������z�k�1^����@U�����%���V��r�v��;B��A������'n��z9
O�A7�8I�J,���I�� � )2iIb��Pu~��C���Q6f)���m`0������5L�����w��0='1K�?H������"��5~bO�7Wd}���W���$q7�������(����PL�l�l���J���++���U*�2<�CP����/���Te��p����}l3!�}�x&���y��q�����H��A��
��z�l��o��� ����5���sPo����������I��Z������X��]���GW��L�f����q��0}��J�����A���s?�d�{����~�%`�@;rId��L���yv�D2��o����"`n�������798���]Y�]�=f�!�<!]q���'��|0F�I�%�x�D����kA���I���NM\��������P�����rc��"H�Y�I�k�\Ad������D�u��kB��?�>�X��h�e#��d��o���Z.,8f���Ka���|4\��5
��.����d��8���ctU�cf���~f5B����jy�D������d `@B�5�~�VL�a�d��e&q <�8�,���aj����%L�P2?����^���V{�3,e/��s���S�
E���� !L���r�p�V3��>}z������)n����e!!W�K�S�E�i�Ia�n�2&�k���{ �S�
�����Uk��FSe�&�q&5&v�� R����6n��&��jUHe1����0�����[h��7�����d:��;��ME� �F��A'�;UL�*^[�:��(�8sIb4�\3���1���o*���kR�i��<���KFU��$��M9]o5Z��\�>N�7���VV���0?�hXV���K�b�
L+w��'E��n�����M�oN�>�D��S=�z�7���u��7l5�z�jc�z��:����S�8�^L�u*��������1��p���0��u`�,H���{D�����d�P��:u~�� AM{G[��A�D�M�ER��Hj`?h������|
��c6�+�XM�Zp���^�
��$�d��P��!��q��d-����~���?-�����V��_+p�h��L��
��S�i7z�w]�d
�e�!A<B[8l��i�-f7�`��������g��W���-����R�J�x�z�Q�h��w�����_hv@���V'RB*9S�P!?S�W�P���(���������=����'{/r7����"��{���'�C�B���9L�y����1h�)����`9�����t������g[U���|1�c��L���=����!�����m�D��yy:�����.�h�O����M���c�$��1I3!��kml
��M���!���) ��i.e��I>'Cr�u�t
�
#��k*�������i�=�rk0��b��B�����bn���f��:��=��i(�`l���Ta����q0J��8��������/g]6������c6���������������Y�&-8������Ca!6�����#�R�e�,�S�kH���l.��wMN��
�1;���I*��Mb,�uY}S��pC�xmy]�\����t�+s`M3`�,�U��;b�$����1������9�7�V�-a��E�N]�F*jz&���|������d����a�Uo�������*�sY:��`�����z�������9$K��V��s�Cg��R��"�H ��?��)���"���R�]��w.:�������L��q��F���zf����L�JvH~��:�Q|�@�x������d[ )��o.
�s�������W�'����v��8��'�UGTF����uP��s E��R�|%2��1�s
HN{�����5Q_n�61�RTL��s�q�M�Y�K����n���=P�|�t�8;i���cQm� �*QL:�q2��d�Cg;O��)qr}���)���Q�K�}w�U�����
���S���f�����-�
��L�g��.�A������ID�3�p~>����L�eU��mT������5�~�t��$�={�r^ ,�8��+�HyfB){����1/DI�Zu���^��
3#��i'�r�6n��*4f���Cn6�ei|���QohC�N+y�\D'� ��q��6��x�
w�&o����L���*�����. ��Y�����%�`
.[Ccg�j���'��%6�Tl8^U�s������i��=q]���R�_��Z�O�%5)������W�C^%�v8;$�B9R(� ���c�X��������t�X����#|��f��#W����{��[� f���%I�R�Q��QL0�[ED�����%�M�{�=9UOj�L4��|����Q�!�,��1�]��1�;c�k�=Q<&������C��KuW4�k������������L� @����K��C�8HYUS� �5��8."����1��y �[y=���VL
M��& �X7�����@(�a:��W/�LS�������h9<�� =��4������,�b�����JLL^��H��>J�
��U�g�s.x���}�c�\v+,���
���Qy#>O�
=���+����^'��0+�oP
�H����a����h
�&��"������������4T7e�_B�G+b����tCfU����`�h���xc(���XB4�X�j* ��F�iJ��g����I�:��+4XR����~z�����T���ec<f�(��s�p�y�4��4���(b�^ -�:�+��X����
&�� ��`�����G�iC,t��as
���9Y�����\k��'������4���5g�c������b?��Q}����NI"aC����� �)�I-� ���!���������m�7���1tp�E��� K�l�_��������B$ Wg��������9 E;P�jL�.P�&�$d��}0��.z�N� ��+yc��Yj�C���2�
m
�U�����A�W����l���ZG�\���B��)&������[Q�&�$c����} ���!�����Z1]3b��6�eU�S ���Q"[9~����$V�da��6�L�U����8����d�i�V���H��)�
+�;<8?j�7/����<=f�0�5-�
�)�K3-:�P�b�;X��-�f�C�tA"h�P9�*�������y�*��#.{���5��&�j�tN�E��iY�H�R'#���0'���Ir���=����M�=:C�7Wj�3���:Sx����2[�@d�T/w���.����N��T8�A�YL������`��2�T�%F��� �Al��Cl*��2<�������
{7VG������:����o�������w'o3O��ff�I����=��bb3����
��j�5+<3�������AI�����!~�����]|���8q����9!Ke�Go��3�U&Y8�b)�B��S�C�
���m���� ���Ao'��e�7���{�3c�{E6qe�x����:���-5��mb������3��#
����<^�|\�����1�����<���[$G�*�b�$��}G�3s"�]!F� ���B��g+�>��.9S�I5>�bzQ<3=���1 K{<`��h��6c��hGw�pb���7�t86���e��3���5�`v�@����pE}���}�<y���WM�JQ
h�#(��[���)�~G�dV���v`����<��V����Q&�J� (�J����&vs�#�&�7;�f�8<��S��\�� ��0�,��'i�8oE����7//G&�U`�xG�Z�K�m��M�)gD �2C��$N�J�"��_��y�=��Hl���dF���3����h�
B��d��4e
��|�6�����D�L'���H�`
-Ki�E�05�-�:�<�VIE�jc��%����sn�|���_��Vx���C"r>�$���+)�Zy��Ra���C�l�+�����S#;�zX���e!6�����Q3��S���o��d��V:�HhnhL!-�#V����0���9��`�������N�,(��?�N����]Zs5t
�xp;�^+/��r��P7L� %�9 ,�m��}� �>6v@��0M��:��#�T����-`���@��c N�,q`�#)�W���[L��������v��~�B�S�X�@9-=�X�J��&����#�'��HJ��8����$��pQxh���Nh;U���6������4��>�3o�s�z�J��_1������-�:���-��=�K�������gV��W?,0&{;Xu������fz2����l��=U_\� ������s��H���y�k�����,�-s���'�0eFe�a�xg�Q���Y
pC(�c*���PXr<�m��R�>ok���jt7�\U�u��76�&��(��8��k�D 8�y������+7KxAX� 0�$�c���r��_ p�VU_HR�z��4� <C���0g�sM�m�k�g���V�a1>s=���u�����:�ubd�����b
�\TXc6�S� f[�-������H�,(z�����D���3�C���7��b�k� Yhck1�^:�����
������"��4�����������u��Es�Ru�v�8��}���U�]`!%}7����8$���@]�{�Y�$'x���MlV�/���tk���!nS��s)a�BqL��W��J������|K����>��b4V{��>���:��"�E�}nF�n��J�f7��v�&�C�y�}z$-
&�t������h���AlC�"�xr��wvt�w�mW�i'�%�����_�b�gk��a�>�98 _�
=�8�3^����N�SSw��G��D_��,��z�@�r��{��a�*��
���m+&p `( 5QW�`������F`�W7���1A��me��;?����5")�N+������Y}��,O��y;�t8N:��!;OeqlpaN�����U�%Wr@�����rh8�Q�6�E���o��`9��������e�����\��'4=�x�����r���p�>��]D�/-����}���>�{�d������-��Ll��8�j�Q���[�V&?�������MML�6��I~��!8���G��s���{��~Ruv�4�'����ER��9E�3��< ��E����=��=�|^�p�:�w��:�z�<�
�����x��z����i��@�q�'���&���_����;��OG���;���8S�����~2���V�`��������sW���~�9\��"�n�Pi����!6����V1�>HP���(�����z%%�:�69S�Eps��b'Y~�z��E����M�#��������r�U<F�H���g�1���~��h&TD����9�T��n
Fc}s��d��������t%�9� Z7,U�6NE?��)�gw*~x��]����ERt ��c�-N���z��T8�L���+l�v�������'�FV�?��46x�<�a5���BD[�a=u��&s�L��r����X�Qy��"m�f���y���liiN�:�x��Geb�Z��������L�oJ�&��4���h?8���
��L6�_%���Es���O�0#]����=�� 8�.;�,��^�N�>���T���U��(�L4O>7�Z����qxI��M��=�D���Y����4g�S���A��N��5��
�T)��&�����I%��R�������{���OO��J�V�h�q7����n�8��������.&��3����H�I4=i|��cq"V�d�c�f������8���'����;�s�~Cm���#���8r�tL�%v�[E �8l���~�?Cb��L��D������bVo�����������������Q�"�����b�Z-��;�_��u�91�UE����I}:�9e���~�� �
#,"�a�� ���6��U@"v�vM�"L,1�s���������T0}a��B9�&A�1x��N����$���P�x���Z���4>�4O����Y+�����f`�f�'����\M�Y����R4��B�����Hz���]�u�p����� �j�;�n�N�|v��_&�aV��m��wF&�[��*����@ ��PM���q!<�q��tK"[�����w�C����%J������������"#���*���&�L�#�\�{I�Z��������!5b�F�h�p^VE��D���f�s��A#�Cp����}�X����7������'HM��-�V���t�x��a!���MJ���F�y�bhm�.� ����M@}[��XY.��D��2�
��jj�Px���;#���N"~�aA@��� 5 bl�3:�
���&�cd�3"��<q�����vf{z+�����^�O��5����D����D����tb \n�!C������]�Ap(DH�D��Q�F���^��*I���$�g 7V��"
!�����%� /�v�����b)H�$T/��h,����!8������LM����V��S���0�[����u\]c�]Lg'<G.����F����#e�m&���aG�l�/ 1K�2���B�~6������E
��W��������~��������P
�o!��/���'|��r��?�l���3)1��g#��D�7���Q�E4=\������<[JD��
E�j�M���E�/XT��+O�+�0�+Fx8� ����������u����S��G�%�������#>���K��=p��'f��c%u���X3+���Un8|��g��8p5�J?���������5��"���3�����^��y�X���1�N�$���3���y%E��Hg'xn�'SZ����o�n�����+F�
�����W��IR�i$�{f��9���8���y�) 6a���hzg?����
���dl��eZ7��U� ��D��=(����_|"�[@�����Y����=�+/�K��J����wkw]I.z����f���Vs�r4���o'_�>�, ��A��U�Hxz_c��P�dhc����6���ne�X�osnM�q�um�����������~����5#�NAegP�M��"�B�D!��Q�w[6��������{��
�%�!W.G!��l"QP&G'r_*"�Byj�+�#{{L�������I/�:���#"�w9:2w�����&��Y@P�IN��
Ao��\��w�L�d)�L�1��`��B|�m5��m���}����r^@�/�xI����j���W�M[��v`��$����$�x��~��o1����l��.�~H�l/F���M�����-���-��p����s��C���{������n�k�Ng{;N�����2����tj[b����| ��Xw��*�e� ��ZI�����nte�'����a��Y���+�m:s(f��'o[����vbA����u�?'��������L1-Z�y^�V�~���|��-phGc�!���������B@�g}f+�!�`���/������~��
��f�N \i���fF���jT�H�6^���g���mc5��?��t���Lk�������=xCl���|�4��Z4w[9����h_�����&��}�B�~��.5YA����Q[�O������-������._��5������|n�����F}�Z�~���hS������T ))ki���txU_�,������*J��Sz�����jn������* �n�2]�U��s���t2K|s�����l��������u{c���5Pvy{Exn��?Dp�����b@=�$I'c����O�����^5��B���rh����*P�J����{�����P^���Q����L�*�`�9]h�L�2��1&���B��\�z��N~ @��f��y�;��3o��������+���s�y�9EH���������l��������������PvT�2�I��fo���-�=! � q��� �2� ���@�Pf��Ev ,� ����?["��������~�w2~������P�3�J��[����_���lt�����P�R~W�����O�U��o�*5���?��3�=C�jj9L��=��Bw49G�\�QG����}QH����;��k�� ��d�aK+����|��+O������)��B7���Y���9y/qC7 uT��L@�1os\�=�-vzfhfpX�+�C��!I�db��c���)��f���9��6��D�-i�!��DWY �hr�w4���O@�U��rM�2�g^ �qz'_^}����[��� X����������W������V{�����m���l {B�8��F����������wv����\[3�F�4[v����?Y
����+�3!,|������Ii
���a{�fr��E�E�6���=n����#�@�|�����2��,�d�I�)U�1�Q�l��0a@|���r��$q����<u!#j�����\�^u9g�}���t��H�O?Z%���p�>`���4�������g�}�8��bE�e��������q��b[����52�`#}�M �i��#�G����� �`:`������������(�[�L����x.���e�������/��)�+]:��:e�$!��l;�x�HT��8�E�MT$���Gecz���3��_t��h�c�����^A=�(��.��� ����������x{}?�vk����x{�zar��K�]Q���:)�V�)�CK�����?j����
��q����k�p�3E��6|i��4�c�
�.���y
�tq����w3lq�q�G�����@��� l��hx2��=3 #�E�����j�z�w�0���;=.K��dI�������m��I���z���V�S �8
�����OM������6c���yH����E���8��8�*3���<'� �5�49�Z_����x'��r���?�-����!?����d!��jD$���]r������7n�UM��2'������|&`���R"�&����UV8�;�x�����x��1
�!]���Zx`bYOh��l��$#<�^�>o2F�-�����>����w�l�5�� �-6g��������b�=��V���8���d��rH��qn�f�|I:��6 q@:���0'�fCe��9t��k��&�=�a�?�K�O��C@�jHzn%� e�����Y�(nE��y�*��Gv�v���? hV@5�G��MIz)1����rE���xxn��t�F�8��8�'6L�z �(�4�U�F��
�s��'#�s�6N��d����n3�JzC�t1�o�Ce����5x�����QA'l�4?�o�0����+��A��t�A�>t�+-'���Zy�r���|��%p�?���
�������T����������4��&�UME��@2����%���L�N�������-���+
\}����#ql��z�� zl�T��:�0�*~^ F�I�?���Z5��&a�v��a/�Qe���b�&�a��&��q��5!�c�eE��$ kutW��N����!���nb-�QO���{q?�\)M�cI���aW��@S��T�n8dj�coV�62A�K��Q�) ��hK�u@1�
Y<��Ua%ds�����j$r��R�E���V���\��0_a7��db"�|j�������af���5�Z�d�N�i%;!�YDs�%E��s$=�V��c��h����/��s<��TM&C���f��z}cG��!+�9��'���fi�"ZN@�-�y�A��d2v\T
w����-�R�~����I
����;���R�kh���������Q�b)<�`�
h{T�(�:�1�/�TK�X4��i
!�o��40�Tf���Gk�=TR|9W4sZ�P>�u�A-�� ,\��D�$G^������D9�)��8������(��;w����� ��}�]��������u�~S�7�W��X��T������
����>o���M$[a�����N�>�-�(}�b ��|�'#+� q����hOC���,_?�R��V(0=f_�Zu����d�V�����[��k�k �B�"�����"������`�$
����b^��kqZ�s��i�o�����[���d���m��D}��t��G/M [IL����*�D_]���*5}3�����A�����G�����{CV��Oy�_ze?������6[�{���:��l��������_4��[��:L7����_��f��j�Y�ta�����(�����a�E wY���sOd������=Z�=/8~p'�qJ��&&~ �7���[1K��:DV������ ,����0(�c"�����m_4���� H����L��f��B�t�IW�R��lL��&~.��;^x���~�� ���]��:�#��-6�
��������{���_s�W�� ^T
�"����r�/�q^�Pg4I��H�4��L���$Rg<~��H~�a0&&=���*�l�Xdb�>Q���e82�Z�;��vw���������P���Bzhp*'w�d�$����1":q:�p����0����i!|�4��Fe�2xQ�T�y�n����9��pkn�-�� '������te�<M�&J
�|�����=i�X|8)vr��d�|3=���j�Z���H������27n�GQ?��$��g�(�F���vh�����<(�
T�JUIr���<)���v��3��H8(���*��!�!���PZ8^cJ��q`���r�j�����k^����f��`P����G�10���ya�#��7��e�
�`�6����������0T�Q����p�qf']0$���v+O[l?�8ev�f�v����>��Rp/���4F��&I���'T4x-Ge����O����n�'��vq����HA���0P�T��NP�m^��������R��^#��#Xn@�y��#���3��D� 7�I����($s�K�R��e��#{�i��{�)���)��*����vV�SuA�]���/��-��fX���se���v];�Y��&���_W�;M�\)�fj����S�}w��q��_��lnlu6�s�w�]*��{��
������)U����C/��-_N!\�E�G"1�q���Y��9�@6\z�$���H��a\a�|�����r(s>�7`gP�����x3h"#H)����H�r��j"�B_?�6$�����?l2��6<is��Jwp����IK�Cc~�E���o-�����%���3�*��S����j�?��������h0��d�����P^&�8�
���]�[�wt�NnO���nIH�����������t������'�=���������N v�O<��a����_H����P����:����_Z�Hn�HV"�W�&���p�!%9������<m����6Z�?l�@Z������q�qcoq���~f�`m�I%�����u.v�f����"��3�sZ���:he�3�G�vP'��-���G&��BeK�����:���mMw�����w������qD?.��'?��.������������A������ �rp������e����n�"���6O����z||z�@����vzp��8���C��M�����p>I$����`�����4I����9�>��w��W����b�����������:�����<�j������ghSq�_�E�.�fa7�����Ay~�i��id]�w]8��%-������������W�����������������)����qC��.9o��a��z����������C��m��A���c���������I��<��"��Y�|����4�&m��&��~��<x}���h���z����� ��5��Y`��-�(Nh��������i�5>������N������&����o�����s�n��^����|��qrA�?4�pL?.���y".o�� �����������p��l�>|��~hd�nzg{��"I�����tJ��������q���8��2���@N �zM�F?�&v�������3�� ���Q:��}%FBsCO� �.G^t��I���Hup����*��7�S2������S��A��\�e_C�����2����A+P�k�������<�$��M�1�k�� ���cT�W����-[�cu��x��tn�z��y�9\���A�/|���k�A"�U���������������5��a��7��m�����mq3���:���$�A���jfB���Y��o��z��H-�����S����w�=,���e������J���YdxB���A������HI�������\�m�[\�Z�q��k>��Q�7����Q�����}*�_�/�~���;���oD���?�_i�Gd�����f����qN��"�R
k&��0��P�����������E���iY<g�N�Z����<C;y����`'��e������ ��L-���,[��Bb���S�p�zDi��c����w��?��u��������g�����z�O�+fW�7��%A�f}]Q�`�a��n�s�p?w_������ ��������
�pE��v,�o������w�{;s�g8N������f#�W�[�����oa ��������:�e7a���Y�v�Zm'���$��v�VJ�w�rN-��<�`@������3�%��s$l���e��d���x���c)�vw��,�}+i���$����'��_�+��`����>�TP�76jE�~���]&��������&#����{��#q�����(��"��
G�ap
M�� :��E���(�,r�����t3��_i�������b���Od\����D^�/��q����"j������V���A_8�:.8s;W���3�j�qrm#��g6�Pj�4a����r�O��2KK����T����:�
5��o�cek
?�)K�|7��f'y2��-j4}|[�?����*��D���������@44�?��j���}��-L��4��t�L23���U���� ��|x?�-U�>��hn�����^��i�c��AjpD���d$6���[P^a]��9�����z+U�xLH��V��M�^E�����VJ�������OO��Te�;k�B�������?��X�~bC�{��
)�l���t�(����'�b�0M_�����$��|���� ��Jo36�
:x�L���������]�����A�U��#�GF�4���iJ��}eB=4�'�D��z�Qo���#�E���&�Y��+y=M���|�0!�6|=�@,y����R�O{g��t�k���xck�kY;s��$�$[�wY������z������= p�� ��R�D���y������
6 �
b*~�a�h$lR������`�Lw~M�F���d-{#Q`�P+`/������Zp����� �fs�R���k��K�w����f��ylu�R���P��������o�dFhD�!q�p�n�u�t�QN�g��G��4uk��O�D����i�6A�� Y1��%����G�M�b�#A��:D "G��'?����������z��; a2��� �f
.*��'�CG=1���J�3X���B��Et�,�}�f~.��v���E�@�^$�BL-��K�^���PV7��+)
���������W�q��N�������.�w9B�sZ�V�
�g�������(f��1�OO]�>���v���b$��Ti����.�K��c���J �x'����y���bJ����q{��V�X����"��
�ixiQ��X�g�=�����K9��|@�6�T\�����Jw����Kh0'��{��k2`j�V����x_OZ|?���V�d ��`��R!����si�OyXo{�D�8�U���X-4������Y[�9%�o�b�9<�����e�:��Q���:1[�i��Y�l��z��+V>sA��K��K�J����:�ln
H����r}��u-Gf�����/�����f�������^r������4ec�`������II`�c�r3x]������A��D�5up]KB�����-�*�il<&z��=���� VE�+���Jj�=���8�Es������^��x:��I9�K'�q|�<��u�n"F���+)��/��6��6j��d���������<�++�K�
����pqf���{ Q^�F*go��Oi���j��iJ��t�I0W���=����d@�`�{��F�� �z��~�5a<���te
�q�%������y����N-]����s"�L ����S��_q��$��w3���/+O��\��q��������8����\4u�t�Jg�&K��*�-K�~�R��|���%�L��7�2<}�����ppxu��u������_^�U���o?�M��;�4`���D`(���9qB�\�w<3����&�:S������ �fp�������.<B�5���?�O��1:$A5�Id�
)�i�eD#����&�������-�����t�G�T�A?�9#��?�� o
���f�ATx�&��q��u��?z�g/�Q�R�� �4�����fz��8�����*%�o4Y#9_�*u�������������AJ�����\���f6^�I|C�(O"Tv,6{�M�o��P��s�!�#��c�� ���� =7���e���'(Jg��l�����F�x��{����[{�YU���J�%� �;����r�Z���2��h�[c���M��`��isH��AV���b�����v�|"N������?cF�
����Qn;~��3��n�V�O�>
z� UQ@[�0t��DU�����Q�+ �R��>&
���������E�g���jR*e��7�+�eXq������5 n�8��0���wP�_�Q������Pv�
F�������[�p���HK�h5���Ts�_d`gtkMh!�7H����0w7���!�b��*���].Q �s����GB�7���v! Dgo?���L�JS���Ty����N��z%T���`�7�m�F�j���MT3Xv�D�oQ������� DG�c���QZ��V��@�e��;9ZGHr��%�^��\I������-
����R
�1���t������i�� ��J�F�48W������p8�.bD���f�����^ )w:��������1#�BQ���_J|�����m�nh����r�#����f���X+����$F(��ai��z{T���%mr���\���J�����E#~DJ������������L���v�N��t���E�S��$w������y8Dh2w�F9���M�P3���$��rc�8�F����d2������fJ�a4�����{
�&`���qA��D�&f(
��*�XAI������)��%��ry�vii��a,�����2��-����q��/��������*���'�FU.�ym ���|�����c�o��i�Vvqc�z�,��{�?����Gf�/���x.���s���O�BsBe'��5�
����#e%�����������lS�jT ���I�,�U��.�Mf=[����*s�Bj�C�$w�o~f��E��+�M=�s��T���v7�7~S�]GIJld;���i���kc�������23���n��~i��������a�U��3�A����E�uyuv���8d��h��WA��]#jU�y�x�
d���?O�����
$�gz'�:��Z���������G��%�W~g->�����6Sbm��qw��,N3VXF�������n\���;��r����<�S\N�J�G�^�&;G<9t�����������e�����[�^W}�������^]Z�%N��n�����0����W���KG���ysk�� x�� ��l�_o{s}kow��9o��&��:(�xR�J����$����]������#����}�����wt�M�T�����O������)3�n�����U�?��:�G@�q�\A����j�����~�&c� H���L�n����x�0[g����j}�w�D��Y.�g�G��=5������h�������O����LR�<���/�}}.o�����7�3���y:-�Sm�~�ZrY�U* ����Op���>8�a��>Z���"�l$S�x��3.��b�G���vW���r}�����B}�*��Ms��Y�"�����i���{'���}���o�I/c,�m�Lo�O�V����5n��N7���1�n|���@@{!����x�j�S�:u^%2����~K�'�����Kal��0����9�D���
g�������n�����<s�8w���-z��4�@G���P<��t�Y������Bh�����
����6��?��.�?s+��h�F�6��8���tY~��w���/��)�
m9�=�=]���h�9��$k�@�u�����Ng4������P_h�)G/jQt5d_�\��u�6D2nj����Y�������6 gn�$P��/U����rST����zn.
�n~���KL�'�'�`o��fyT1���M�\��K61ED�X�@�DO����8O`2����7��#!�����B#�����������t �N�U'_X�����=[fhvT����q/Ij~LMKh�G�Q'��nX����C�����\=��r�1(�fR;B�z�q�.��P-�&+E�N�0Mq0f�8�"���d58 %��������5�g��5�Vo�?�"6��3��M��!�BS�x�g����BUV{M"���l��,8 .���d�G�8�����:���(�E��+��X��=��t)Y�����m�_�j�;�v���y����Q-+�� �^7L����#�T�k]��<k}<8^Z����^�Q���{)�Q\�����j�,I��'��
9)?�r{���C)��i�����E<"1-z�yh�\7���us_nj�7����@|�y�ZB�*!����+��0M�9�?)AI�Ltz])2�,��li'>��w�W�s��s�����?s�t �u{"9qof�p
���a\���HQ�����}�QB[����:����y��i&����e��������f���"F��;�{�v������w|{g62�h�b,E2������S� �C|l.���i~��z�:=>�sc�/�Y�@\n�������]���S�?+r��9�������������V?�����{����\�5\�t
M%����_���&0��k��*3z�����y���a�\����:<�{puK��8Z��<BF;���u���$���A��uF����G�>��������%LJ�����&������f�[����o��R�6����h��gih�+<p%V��2�c����$W�
X9w�b9
���GW�o.XyU+�;3jC�������`J�J���1�}�V
|H� �(
-����8Q�;B��K���/D%@��ka7���������D��{H�dW��E���'����������)0{2��0��`�Ss�����M��E�mf
t4nI$�#���N�v��_��E+�^�U8pB�){~���z�p�����c^�od��{���?�����1�\p���<���<Onh�&c`��� ?��Q��v���UL�`t����~O t����{%y�����F�V�M�w����5�-� ^�� `
�%'�P��s�w���Y2^x��nF�$?�l�f�0NT0L2M�w���B����e&��y$b���L����z'�
��Ir�
YYP�UW|P��K��A��a�+���������$h���?�I7� 6�Zq���R���oFc���)�:i��� ��m�*
s��������w���?0�d��V�YF�����4��s�}��O'*g0�M �$��w|�x����q�ZZ�XD�;�fd~ng5��]�E�RT�qY���%��
�c��$�G��5~:|�������B���c����&��tw("���x##�n�`�x��L�a��9��8�&�����k#Dz�;�$�*���p��"c��������i�,f����49��Q?���~����uqgL��Kv�H�����~^�&}��
��b�9��\]r�E��������^jL����n��UrmP���I�4>�~7���&�O`��@�o���8y}q)�d)�;�09�P�Q"
7KE��[nE_���f�Y�}U����om�j����d� �_q���*������ZW���� �!y���\�t�M�D<�4�_$��`�'���e+���2�G����jn����$#�llT�;���7�kl.��FQ���/��6OZ����.WHh�G����esee6�uHn�,-��-���#�b���c�^� �R�yC�+��=4HU��w\��g����p�|��HL������UQ�$����)�������Ht�_G�p3nV���dr �!���V <=j\������������_�(O�v���;��u������D�D��
)^���i(P��K�����_,���\V�j���c��G�?4�8l��G���?���N��V���(�K���6����o1�Q�o9++G(�$4���@���O�D�����G%���F�[�q�+/� �@����uu_������F��9j��z��B
&T��A6�l���z ���lK6#4��7��g� 2���7j�^5�GzU��|������l\��Ez�C;#J����D�s��:�����K������`?�����\�M�daQ"�"��hR$U����X�
�d`L�����g\a�)j:�<�5X�V8/=;P�~�%� A}��9�d&}���f a �t������r����)�\�������g�����<u���y��..i� R��;&
���W��`gUs� ������M�!������;���!_u�M����xb���y�U�^%C��
v�}��kosk�V�Kv����|���WFp��`�d�, �5 2���I�1�C��������'