Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qEo1R-0007nq-UL for pgsql-hackers@arkaria.postgresql.org; Thu, 29 Jun 2023 09:33:06 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1qEo1Q-0004hE-RM for pgsql-hackers@arkaria.postgresql.org; Thu, 29 Jun 2023 09:33:04 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qEo1Q-0004ea-6c for pgsql-hackers@lists.postgresql.org; Thu, 29 Jun 2023 09:33:04 +0000 Received: from forward501a.mail.yandex.net ([2a02:6b8:c0e:500:1:45:d181:d501]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1qEo1K-0014h9-UF for pgsql-hackers@postgresql.org; Thu, 29 Jun 2023 09:33:03 +0000 Received: from mail-nwsmtp-smtp-production-main-52.vla.yp-c.yandex.net (mail-nwsmtp-smtp-production-main-52.vla.yp-c.yandex.net [IPv6:2a02:6b8:c15:2f8a:0:640:b50b:0]) by forward501a.mail.yandex.net (Yandex) with ESMTP id ACBC35EB4A; Thu, 29 Jun 2023 12:32:53 +0300 (MSK) Received: by mail-nwsmtp-smtp-production-main-52.vla.yp-c.yandex.net (smtp/Yandex) with ESMTPSA id pWJxr12DVCg0-bV9LvoCi; Thu, 29 Jun 2023 12:32:52 +0300 X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex.ru; s=mail; t=1688031172; bh=KgHnH8AgyDKS5hAUeFGRL3c4neh4vrj6BJstt92HeYA=; h=In-Reply-To:Cc:Date:References:To:Subject:Message-ID:From; b=r/XtIVh17iTXdi/ebCsowLcJvr32fyQ6te5w9HyRosXfPAy4fC8MhiHuQxtClYgzE /kzNYrJ8MemqTOEutFNAPFJTV6XLARbXGnF+z9AdPN3Qa479S7MgmUZk96kCEW7+ku KMxIRd/ypizNMVtE+7Yn1zTwUW33YNUFw6Zpji8M= Authentication-Results: mail-nwsmtp-smtp-production-main-52.vla.yp-c.yandex.net; dkim=pass header.i=@yandex.ru Content-Type: multipart/mixed; boundary="------------LxcDHSbxmLntC0r7Zn4MURVr" Message-ID: <9ea35f18-419d-efb7-b7c8-2e641a61f020@yandex.ru> Date: Thu, 29 Jun 2023 12:32:51 +0300 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.11.0 Subject: Re: POC, WIP: OR-clause support for indexes To: Peter Geoghegan Cc: Marcos Pegoraro , Alena Rybakina , Andrey Lepikhov , pgsql-hackers@postgresql.org, teodor@sigaev.ru References: <567ED6CA.2040504@sigaev.ru> <05838ca5-1c78-af81-34c1-19cae2516b61@postgrespro.ru> <919bfbcb-f812-758d-d687-71f89f0d9a68@postgrespro.ru> <7829312a-eb6b-b9ba-9719-71c9bc410884@yandex.ru> Content-Language: en-US From: Alena Rybakina In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk This is a multi-part message in MIME format. --------------LxcDHSbxmLntC0r7Zn4MURVr Content-Type: multipart/alternative; boundary="------------oNYeqemyuV04TsAGfuG3ny2o" --------------oNYeqemyuV04TsAGfuG3ny2o Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Hi! I'm sorry I didn't answer you right away, I was too busy with work. On 27.06.2023 22:50, Peter Geoghegan wrote: > On Tue, Jun 27, 2023 at 6:19 AM Alena Rybakina wrote: >> I learned something new from your letter, thank you very much for that! > Cool. The MDAM paper is also worth a read: > > https://vldb.org/conf/1995/P710.PDF > > Some of the techniques it describes are already in Postgres. With > varying degrees of maturity. > > The paper actually mentions OR optimization at one point, under > "Duplicate Elimination". The general idea is that ScalarArrayOpExpr > execution can "eliminate duplicates before the data is read". The > important underlying principle is that it can be really useful to give > the B-Tree code the context it requires to be clever about stuff like > that. We can do this by (say) using one ScalarArrayOpExpr, rather than > using two or more index scans that the B-Tree code will treat as > independent things. So a lot of the value in your patch comes from the > way that it can enable other optimizations (the immediate benefits are > also nice). > > In the past, OR optimizations have been prototyped that were later > withdrawn/rejected because the duplicate elimination aspect was...too > scary [1]. It's very easy to see that ScalarArrayOpExpr index scans > don't really have the same problem. "Giving the B-Tree code the > required context" helps here too. > Thank you for the explanation and the material provided) unfortunately, I am still only studying the article and at the moment I cannot write more. To be honest, I didn't think about the fact that my optimization can help eliminate duplicates before reading the data before. I am still only in the process of familiarizing myself with the thread [1] (reference from your letter), but I have already seen that there are problems related, for example, to when "or" expressions refer to the parent element. I think, I would face the similar problems if I complicate the current code, for example, so that not only or expressions standing on the same level are written in any, but also on different ones without violating the logic of the priority of executing operators. For example, this query works now: postgres=# EXPLAIN (analyze, COSTS OFF) SELECT oid,relname FROM pg_class WHERE   (oid = 13779 OR oid = 2) OR (oid = 4 OR oid = 5) OR   relname = 'pg_extension' ;                                                     QUERY PLAN ------------------------------------------------------------------------------------------------------------------  Seq Scan on pg_class (actual time=0.086..0.140 rows=1 loops=1)    Filter: ((oid = ANY ('{4,5}'::oid[])) OR (oid = ANY ('{13779,2}'::oid[])) OR (relname = 'pg_extension'::name))    Rows Removed by Filter: 412  Planning Time: 2.135 ms  Execution Time: 0.160 ms (5 rows) But I would like it works such as:                                       QUERY PLAN --------------------------------------------------------------------------------------  Seq Scan on pg_class (actual time=0.279..0.496 rows=1 loops=1)    Filter: ((oid = ANY ('{13779,2,4,5}'::oid[])) OR (relname = 'pg_extension'::name))    Rows Removed by Filter: 412  Planning Time: 0.266 ms  Execution Time: 0.536 ms (5 rows) >> I analyzed the buffer consumption when I ran control regression tests using my patch. diff shows me that there is no difference between the number of buffer block scans without and using my patch, as far as I have seen. (regression.diffs) > To be clear, I wasn't expecting that there'd be any regressions from > your patch. Intuitively, it seems like this optimization should make > the query plan do almost the same thing at execution time -- just > slightly more efficiently on average, and much more efficiently in > some individual cases. > > It would probably be very hard for the optimizer to model/predict how > much work it can save by using a ScalarArrayOpExpr instead of an > "equivalent" set of bitmap index scans, OR'd together. But it doesn't > necessarily matter -- the only truly critical detail is understanding > the worst case for the transformation optimization. Yes, I agree with you and I have yet to analyze this. > It cannot be too > bad (maybe it's ~zero added runtime overhead relative to not doing the > transformation, even?). I haven't seen a major performance degradation so far, but to be honest, I have not conducted a detailed analysis on other types of queries other than x=1 or x=2 or x=1 or y=2, etc. As soon as something is known, I will provide the data, it is very interesting to me. > At the same time, nbtree can be clever about > ScalarArrayOpExpr execution at runtime (once that's implemented), > without ever needing to make any kind of up-front commitment to > navigating through the index in any particular way. It's all dynamic, > and can be driven by the actual observed characteristics of the index > structure. > > In other words, we don't really need to gamble (in the planner, or at > execution time). We're just keeping our options open in more cases. > (My thinking on these topics was influenced by Goetz Graefe -- "choice > is confusion" [2]). Unfortunately, when I tried to make a transformation at the stage of index formation, I encountered too incorrect an assessment of the selectivity of relation, which affected the incorrect calculation of the cost and cardinality. I couldn't solve this problem. My diff (transform_or_v0.diff). I got this result: CREATE TABLE tenk1 (unique1int, unique2int, tenint, hundredint); insert into tenk1 SELECT x,x,x,x FROM generate_series(1,50000) as x; CREATE INDEX a_idx1 ON tenk1(unique1); CREATE INDEX a_idx2 ON tenk1(unique2); CREATE INDEX a_hundred ON tenk1(hundred); postgres=# explain analyze select * from tenk1 a join tenk1 b on a.unique2 = 3 or a.unique2 = 7 or a.unique1 = 1; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------- Nested Loop (cost=0.00..15627479.50 rows=1250050000 width=32) (actual time=0.040..75.531 rows=150000 loops=1) -> Seq Scan on tenk1 b (cost=0.00..771.00 rows=50000 width=16) (actual time=0.022..5.467 rows=50000 loops=1) -> Materialize (cost=0.00..1146.01 rows=25001 width=16) (actual time=0.000..0.001 rows=3 loops=50000) -> Seq Scan on tenk1 a (cost=0.00..1021.00 rows=25001 width=16) (actual time=0.011..22.789 rows=3 loops=1) Filter: ((unique2 = ANY (ARRAY[3, 7])) OR (unique1 = 1)) Rows Removed by Filter: 49997 Planning Time: 0.427 ms Execution Time: 80.027 ms (8 rows) The current patch's result: postgres=# set enable_bitmapscan ='off'; SET postgres=# explain analyze select * from tenk1 a join tenk1 b on a.unique2 = 3 or a.unique2 = 7 or a.unique1 = 1; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------- Nested Loop (cost=0.00..22247.02 rows=1350000 width=32) (actual time=0.094..373.627 rows=1350000 loops=1) -> Seq Scan on tenk1 b (cost=0.00..2311.00 rows=150000 width=16) (actual time=0.051..14.667 rows=150000 loops=1) -> Materialize (cost=0.00..3061.05 rows=9 width=16) (actual time=0.000..0.001 rows=9 loops=150000) -> Seq Scan on tenk1 a (cost=0.00..3061.00 rows=9 width=16) (actual time=0.026..42.389 rows=9 loops=1) Filter: ((unique2 = ANY ('{3,7}'::integer[])) OR (unique1 = 1)) Rows Removed by Filter: 149991 Planning Time: 0.414 ms Execution Time: 409.154 ms (8 rows) > [1]https://www.postgresql.org/message-id/flat/1397.1486598083%40sss.pgh.pa.us#310f974a8dc84478d6d3c70f336807bb > [2]https://sigmodrecord.org/publications/sigmodRecord/2009/pdfs/05_Profiles_Graefe.pdf Thank you again for the explanations and the material provided. I will carefully study everything as soon as possible and will write if there are any thoughts or if there are ideas about my patch. -- Regards, Alena Rybakina Postgres Professional --------------oNYeqemyuV04TsAGfuG3ny2o Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit

Hi! I'm sorry I didn't answer you right away, I was too busy with work.

On 27.06.2023 22:50, Peter Geoghegan wrote:
On Tue, Jun 27, 2023 at 6:19 AM Alena Rybakina <lena.ribackina@yandex.ru> wrote:
I learned something new from your letter, thank you very much for that!
Cool. The MDAM paper is also worth a read:

https://vldb.org/conf/1995/P710.PDF

Some of the techniques it describes are already in Postgres. With
varying degrees of maturity.

The paper actually mentions OR optimization at one point, under
"Duplicate Elimination". The general idea is that ScalarArrayOpExpr
execution can "eliminate duplicates before the data is read". The
important underlying principle is that it can be really useful to give
the B-Tree code the context it requires to be clever about stuff like
that. We can do this by (say) using one ScalarArrayOpExpr, rather than
using two or more index scans that the B-Tree code will treat as
independent things. So a lot of the value in your patch comes from the
way that it can enable other optimizations (the immediate benefits are
 also nice).

In the past, OR optimizations have been prototyped that were later
withdrawn/rejected because the duplicate elimination aspect was...too
scary [1]. It's very easy to see that ScalarArrayOpExpr index scans
don't really have the same problem. "Giving the B-Tree code the
required context" helps here too.

Thank you for the explanation and the material provided) unfortunately, I am still only studying the article and at the moment I cannot write more. To be honest, I didn't think about the fact that my optimization can help eliminate duplicates before reading the data before.

I am still only in the process of familiarizing myself with the thread [1] (reference from your letter), but I have already seen that there are problems related, for example, to when "or" expressions refer to the parent element.

I think, I would face the similar problems if I complicate the current code, for example, so that not only or expressions standing on the same level are written in any, but also on different ones without violating the logic of the priority of executing operators.

For example, this query works now:

postgres=# EXPLAIN (analyze, COSTS OFF)
SELECT oid,relname FROM pg_class
WHERE
  (oid = 13779 OR oid = 2) OR (oid = 4 OR oid = 5) OR
  relname = 'pg_extension'
;

                                                    QUERY PLAN                                                    
------------------------------------------------------------------------------------------------------------------
 Seq Scan on pg_class (actual time=0.086..0.140 rows=1 loops=1)
   Filter: ((oid = ANY ('{4,5}'::oid[])) OR (oid = ANY ('{13779,2}'::oid[])) OR (relname = 'pg_extension'::name))
   Rows Removed by Filter: 412
 Planning Time: 2.135 ms
 Execution Time: 0.160 ms
(5 rows)

But I would like it works such as:

                                      QUERY PLAN                                      
--------------------------------------------------------------------------------------
 Seq Scan on pg_class (actual time=0.279..0.496 rows=1 loops=1)
   Filter: ((oid = ANY ('{13779,2,4,5}'::oid[])) OR (relname = 'pg_extension'::name))
   Rows Removed by Filter: 412
 Planning Time: 0.266 ms
 Execution Time: 0.536 ms
(5 rows)

I analyzed the buffer consumption when I ran control regression tests using my patch. diff shows me that there is no difference between the number of buffer block scans without and using my patch, as far as I have seen. (regression.diffs)
To be clear, I wasn't expecting that there'd be any regressions from
your patch. Intuitively, it seems like this optimization should make
the query plan do almost the same thing at execution time -- just
slightly more efficiently on average, and much more efficiently in
some individual cases.

It would probably be very hard for the optimizer to model/predict how
much work it can save by using a ScalarArrayOpExpr instead of an
"equivalent" set of bitmap index scans, OR'd together. But it doesn't
necessarily matter -- the only truly critical detail is understanding
the worst case for the transformation optimization.
Yes, I agree with you and I have yet to analyze this.
 It cannot be too
bad (maybe it's ~zero added runtime overhead relative to not doing the
transformation, even?). 
I haven't seen a major performance degradation so far, but to be honest, I have not conducted a detailed analysis on other types of queries other than x=1 or x=2 or x=1 or y=2, etc. As soon as something is known, I will provide the data, it is very interesting to me.
At the same time, nbtree can be clever about
ScalarArrayOpExpr execution at runtime (once that's implemented),
without ever needing to make any kind of up-front commitment to
navigating through the index in any particular way. It's all dynamic,
and can be driven by the actual observed characteristics of the index
structure.

In other words, we don't really need to gamble (in the planner, or at
execution time). We're just keeping our options open in more cases.
(My thinking on these topics was influenced by Goetz Graefe -- "choice
is confusion" [2]).

Unfortunately, when I tried to make a transformation at the stage of index formation, I encountered too incorrect an assessment of the selectivity of relation, which affected the incorrect calculation of the cost and cardinality. I couldn't solve this problem.

My diff (transform_or_v0.diff). I got this result:

CREATE TABLE tenk1 (unique1 int, unique2 int, ten int, hundred int);
insert into tenk1 SELECT x,x,x,x FROM generate_series(1,50000) as x;
CREATE INDEX a_idx1 ON tenk1(unique1);
CREATE INDEX a_idx2 ON tenk1(unique2);
CREATE INDEX a_hundred ON tenk1(hundred);

postgres=# explain analyze
select * from tenk1 a join tenk1 b on
  a.unique2 = 3 or a.unique2 = 7 or a.unique1 = 1;
                                                      QUERY PLAN                                                      
----------------------------------------------------------------------------------------------------------------------
 Nested Loop  (cost=0.00..15627479.50 rows=1250050000 width=32) (actual time=0.040..75.531 rows=150000 loops=1)
   ->  Seq Scan on tenk1 b  (cost=0.00..771.00 rows=50000 width=16) (actual time=0.022..5.467 rows=50000 loops=1)
   ->  Materialize  (cost=0.00..1146.01 rows=25001 width=16) (actual time=0.000..0.001 rows=3 loops=50000)
         ->  Seq Scan on tenk1 a  (cost=0.00..1021.00 rows=25001 width=16) (actual time=0.011..22.789 rows=3 loops=1)
               Filter: ((unique2 = ANY (ARRAY[3, 7])) OR (unique1 = 1))
               Rows Removed by Filter: 49997
 Planning Time: 0.427 ms
 Execution Time: 80.027 ms
(8 rows)

The current patch's result:

postgres=# set enable_bitmapscan ='off';
SET
postgres=# explain analyze
select * from tenk1 a join tenk1 b on
  a.unique2 = 3 or a.unique2 = 7 or a.unique1 = 1;
                                                      QUERY PLAN                                                      
----------------------------------------------------------------------------------------------------------------------
 Nested Loop  (cost=0.00..22247.02 rows=1350000 width=32) (actual time=0.094..373.627 rows=1350000 loops=1)
   ->  Seq Scan on tenk1 b  (cost=0.00..2311.00 rows=150000 width=16) (actual time=0.051..14.667 rows=150000 loops=1)
   ->  Materialize  (cost=0.00..3061.05 rows=9 width=16) (actual time=0.000..0.001 rows=9 loops=150000)
         ->  Seq Scan on tenk1 a  (cost=0.00..3061.00 rows=9 width=16) (actual time=0.026..42.389 rows=9 loops=1)
               Filter: ((unique2 = ANY ('{3,7}'::integer[])) OR (unique1 = 1))
               Rows Removed by Filter: 149991
 Planning Time: 0.414 ms
 Execution Time: 409.154 ms
(8 rows)

[1] https://www.postgresql.org/message-id/flat/1397.1486598083%40sss.pgh.pa.us#310f974a8dc84478d6d3c70f336807bb
[2] https://sigmodrecord.org/publications/sigmodRecord/2009/pdfs/05_Profiles_Graefe.pdf
Thank you again for the explanations and the material provided. I will carefully study everything as soon as possible and will write if there are any thoughts or if there are ideas about my patch.

--

Regards,
Alena Rybakina
Postgres Professional
--------------oNYeqemyuV04TsAGfuG3ny2o-- --------------LxcDHSbxmLntC0r7Zn4MURVr Content-Type: text/x-patch; charset=UTF-8; name="transform_or_v0.diff" Content-Disposition: attachment; filename="transform_or_v0.diff" Content-Transfer-Encoding: base64 ZGlmZiAtLWdpdCBhL3NyYy9iYWNrZW5kL29wdGltaXplci9wYXRoL2luZHhwYXRoLmMgYi9z cmMvYmFja2VuZC9vcHRpbWl6ZXIvcGF0aC9pbmR4cGF0aC5jCmluZGV4IDAwNjVjODk5MmJk Li44ZWYzNDM4ZDc4YyAxMDA2NDQKLS0tIGEvc3JjL2JhY2tlbmQvb3B0aW1pemVyL3BhdGgv aW5keHBhdGguYworKysgYi9zcmMvYmFja2VuZC9vcHRpbWl6ZXIvcGF0aC9pbmR4cGF0aC5j CkBAIC0xOTMsNiArMTkzLDI3MyBAQCBzdGF0aWMgYm9vbCBlY19tZW1iZXJfbWF0Y2hlc19p bmRleGNvbChQbGFubmVySW5mbyAqcm9vdCwgUmVsT3B0SW5mbyAqcmVsLAogCQkJCQkJCQkJ ICAgRXF1aXZhbGVuY2VDbGFzcyAqZWMsIEVxdWl2YWxlbmNlTWVtYmVyICplbSwKIAkJCQkJ CQkJCSAgIHZvaWQgKmFyZyk7CiAKK3R5cGVkZWYgc3RydWN0IE9yQ2xhdXNlR3JvdXBFbnRy eQoreworCU5vZGUJCSAgICpub2RlOworCUxpc3QJCSAgICpjb25zdHM7CisJT2lkCQkJCWNv bGxhdGlvbjsKKwlPaWQJCQkJb3BubzsKKwlSZXN0cmljdEluZm8gICAqcmluZm87Cit9IE9y Q2xhdXNlR3JvdXBFbnRyeTsKKworLyoKKyAqIFBhc3MgdGhyb3VnaCBiYXNlcmVzdHJpY3Rp bmZvIGNsYXVzZXMgYW5kIHRyeSB0byBjb252ZXJ0IE9SIGNsYXVzZXMgaW50byBJTgorICog UmV0dXJuIGEgbW9kaWZpZWQgY2xhdXNlIGxpc3Qgb3IganVzdCB0aGUgc2FtZSBiYXNlcmVz dHJpY3RpbmZvLCBpZiBubworICogY2hhbmdlcyBoYXZlIG1hZGUuCisgKiBYWFg6IGRvIG5v dCBjaGFuZ2Ugc291cmNlIGxpc3Qgb2YgY2xhdXNlcyBhdCBhbGwuCisgKi8KK3N0YXRpYyBM aXN0ICoKK3RyYW5zZm9ybV9vcnMoUGxhbm5lckluZm8gKnJvb3QsIExpc3QgKmJhc2VyZXN0 cmljdGluZm8pCit7CisJTGlzdENlbGwgICAqbGM7CisJTGlzdENlbGwgICAqbGNfY3A7CisJ TGlzdAkgICAqbW9kaWZpZWRfcmluZm8gPSBOSUw7CisJYm9vbAkJc29tZXRoaW5nX2NoYW5n ZWQgPSBmYWxzZTsKKwlMaXN0CSAgICpiYXNlcmVzdHJpY3RpbmZvX29yaWdpbiA9IGxpc3Rf Y29weShiYXNlcmVzdHJpY3RpbmZvKTsKKworCS8qCisJICogQ29tcGxleGl0eSBvZiBhIGNs YXVzZSBjb3VsZCBiZSBhcmJpdHJhcmlseSBzb3BoaXN0aWNhdGVkLiBIZXJlLCB3ZSB3aWxs CisJICogbG9vayB1cCBvbmx5IG9uIHRoZSB0b3AgbGV2ZWwgb2YgY2xhdXNlIGxpc3QuCisJ ICogWFhYOiBJdCBpcyBzdWJzdGFudGlhdGVkPyBDb3VsZCB3ZSBjaGFuZ2Ugc29tZXRoaW5n IGhlcmU/CisJICovCisJZm9yYm90aCAobGMsIGJhc2VyZXN0cmljdGluZm8sIGxjX2NwLCBi YXNlcmVzdHJpY3RpbmZvX29yaWdpbikKKwl7CisJCVJlc3RyaWN0SW5mbyAgICpyaW5mbyA9 IGxmaXJzdF9ub2RlKFJlc3RyaWN0SW5mbywgbGMpOworCQlSZXN0cmljdEluZm8gICAqcmlu Zm9fYmFzZSA9IGxmaXJzdF9ub2RlKFJlc3RyaWN0SW5mbywgbGNfY3ApOworCQlMaXN0CQkg ICAqb3JfbGlzdCA9IE5JTDsKKwkJTGlzdENlbGwJICAgKmxjX2VhcmdzLAorCQkJCQkgICAq bGNfcmFyZ3MsCisJCQkJCSAgICpsY19hcmdzOworCQlMaXN0CQkgICAqZ3JvdXBzX2xpc3Qg PSBOSUw7CisJCWJvb2wJCQljaGFuZ2VfYXBwbHkgPSBmYWxzZTsKKworCQlpZiAoIXJlc3Ry aWN0aW9uX2lzX29yX2NsYXVzZShyaW5mbykpCisJCXsKKwkJCS8qIEFkZCBhIGNsYXVzZSB3 aXRob3V0IGNoYW5nZXMgKi8KKwkJCW1vZGlmaWVkX3JpbmZvID0gbGFwcGVuZChtb2RpZmll ZF9yaW5mbywgcmluZm8pOworCQkJY29udGludWU7CisJCX0KKworCQkvKgorCQkgKiBOT1RF OgorCQkgKiBJdCBpcyBhbiBPUi1jbGF1c2UuIFNvLCByaW5mby0+b3JjbGF1c2UgaXMgYSBC b29sRXhwciBub2RlLCBjb250YWlucworCQkgKiBhIGxpc3Qgb2Ygc3ViLXJlc3RyaWN0aW5m byBhcmdzLCBhbmQgcmluZm8tPmNsYXVzZSAtIHdoaWNoIGlzIHRoZQorCQkgKiBzYW1lIGV4 cHJlc3Npb24sIG1hZGUgZnJvbSBiYXJlIGNsYXVzZXMuIFRvIG5vdCBicmVhayBzZWxlY3Rp dml0eQorCQkgKiBjYWNoZXMgYW5kIG90aGVyIG9wdGltaXphdGlvbnMsIHVzZSBib3RoOgor CQkgKiAtIHVzZSByaW5mb3MgZnJvbSBvcmNsYXVzZSBpZiBubyB0cmFuc2Zvcm1hdGlvbiBu ZWVkZWQKKwkJICogLSB1c2UgIGJhcmUgcXVhbHMgZnJvbSByaW5mby0+Y2xhdXNlIGluIHRo ZSBjYXNlIG9mIHRyYW5zZm9ybWF0aW9uLAorCQkgKiB0byBjcmVhdGUgbmV3IFJlc3RyaWN0 SW5mbzogaW4gdGhpcyBjYXNlIHdlIGhhdmUgbm8gb3B0aW9ucyB0byBhdm9pZAorCQkgKiBz ZWxlY3Rpdml0eSBlc3RpbWF0aW9uIHByb2NlZHVyZS4KKwkJICovCisJCWZvcmJvdGgobGNf ZWFyZ3MsICgoQm9vbEV4cHIgKikgcmluZm8tPmNsYXVzZSktPmFyZ3MsCisJCQkJbGNfcmFy Z3MsICgoQm9vbEV4cHIgKikgcmluZm8tPm9yY2xhdXNlKS0+YXJncykKKwkJeworCQkJRXhw cgkJCSAgICpiYXJlX29yYXJnID0gKEV4cHIgKikgbGZpcnN0KGxjX2VhcmdzKTsKKwkJCVJl c3RyaWN0SW5mbwkgICAqc3ViX3JpbmZvOworCQkJTm9kZQkJCSAgICpjb25zdF9leHByOwor CQkJTm9kZQkJCSAgICpub25fY29uc3RfZXhwcjsKKwkJCUxpc3RDZWxsCQkgICAqbGNfZ3Jv dXBzOworCQkJT3JDbGF1c2VHcm91cEVudHJ5ICpnZW50cnk7CisJCQlPaWQJCQkJCW9wbm87 CisKKwkJCS8qIEl0IG1heSBiZSBvbmUgbW9yZSBib29sZWFuIGV4cHJlc3Npb24sIHNraXAg aXQgZm9yIG5vdyAqLworCQkJaWYgKCFJc0EobGZpcnN0KGxjX3JhcmdzKSwgUmVzdHJpY3RJ bmZvKSkKKwkJCXsKKwkJCQlvcl9saXN0ID0gbGFwcGVuZChvcl9saXN0LCAodm9pZCAqKSBi YXJlX29yYXJnKTsKKwkJCQljb250aW51ZTsKKwkJCX0KKworCQkJc3ViX3JpbmZvID0gbGZp cnN0X25vZGUoUmVzdHJpY3RJbmZvLCBsY19yYXJncyk7CisKKwkJCS8qIENoZWNrOiBpdCBp cyBhbiBleHByIG9mIHRoZSBmb3JtICdGKHgpIG9wZXIgQ29uc3RFeHByJyAqLworCQkJaWYg KCFJc0EoYmFyZV9vcmFyZywgT3BFeHByKSB8fAorCQkJCSEoYm1zX2lzX2VtcHR5KHN1Yl9y aW5mby0+bGVmdF9yZWxpZHMpIF4KKwkJCQlibXNfaXNfZW1wdHkoc3ViX3JpbmZvLT5yaWdo dF9yZWxpZHMpKSB8fAorCQkJCWNvbnRhaW5fdm9sYXRpbGVfZnVuY3Rpb25zKChOb2RlICop IGJhcmVfb3JhcmcpKQorCQkJeworCQkJCS8qIEFnYWluLCBpdCdzIG5vdCB0aGUgZXhwciB3 ZSBjYW4gdHJhbnNmb3JtICovCisJCQkJb3JfbGlzdCA9IGxhcHBlbmQob3JfbGlzdCwgKHZv aWQgKikgYmFyZV9vcmFyZyk7CisJCQkJY29udGludWU7CisJCQl9CisKKwkJCS8qIEdldCBw b2ludGVycyB0byBjb25zdGFudCBhbmQgZXhwcmVzc2lvbiBzaWRlcyBvZiB0aGUgY2xhdXNl ICovCisJCQljb25zdF9leHByID1ibXNfaXNfZW1wdHkoc3ViX3JpbmZvLT5sZWZ0X3JlbGlk cykgPworCQkJCQkJCQkJCQkJZ2V0X2xlZnRvcChzdWJfcmluZm8tPmNsYXVzZSkgOgorCQkJ CQkJCQkJCQkJZ2V0X3JpZ2h0b3Aoc3ViX3JpbmZvLT5jbGF1c2UpOworCQkJbm9uX2NvbnN0 X2V4cHIgPSBibXNfaXNfZW1wdHkoc3ViX3JpbmZvLT5sZWZ0X3JlbGlkcykgPworCQkJCQkJ CQkJCQkJZ2V0X3JpZ2h0b3Aoc3ViX3JpbmZvLT5jbGF1c2UpIDoKKwkJCQkJCQkJCQkJCWdl dF9sZWZ0b3Aoc3ViX3JpbmZvLT5jbGF1c2UpOworCisJCQlvcG5vID0gKChPcEV4cHIgKikg c3ViX3JpbmZvLT5jbGF1c2UpLT5vcG5vOworCQkJaWYgKCFvcF9tZXJnZWpvaW5hYmxlKG9w bm8sIGV4cHJUeXBlKG5vbl9jb25zdF9leHByKSkpCisJCQl7CisJCQkJLyogQW5kIGFnYWlu LCBmaWx0ZXIgb3V0IG5vbi1lcXVhbGl0eSBvcGVyYXRvcnMgKi8KKwkJCQlvcl9saXN0ID0g bGFwcGVuZChvcl9saXN0LCAodm9pZCAqKSBiYXJlX29yYXJnKTsKKwkJCQljb250aW51ZTsK KwkJCX0KKworCQkJLyoKKwkJCSAqIEF0IHRoaXMgcG9pbnQgd2UgZGVmaW5pdGVseSBoYXZl IGEgdHJhbnNmb3JtYWJsZSBjbGF1c2UuCisJCQkgKiBDbGFzc2lmeSBpdCBhbmQgYWRkIGlu dG8gc3BlY2lmaWMgZ3JvdXAgb2YgY2xhdXNlcywgb3IgY3JlYXRlIG5ldworCQkJICogZ3Jv dXAuCisJCQkgKiBUT0RPOiB0byBtYW5hZ2UgY29tcGxleGl0eSBpbiB0aGUgY2FzZSBvZiBt YW55IGRpZmZlcmVudCBjbGF1c2VzCisJCQkgKiAoWDE9QzEpIE9SIChYMj1DMiBPUikgLi4u IChYTiA9IENOKSB3ZSBjb3VsZCBpbnZlbnQgc29tZXRoaW5nCisJCQkgKiBsaWtlIGEgaGFz aCB0YWJsZSAoaHRhYiBrZXkgPz8/KS4KKwkJCSAqLworCQkJZm9yZWFjaChsY19ncm91cHMs IGdyb3Vwc19saXN0KQorCQkJeworCQkJCU9yQ2xhdXNlR3JvdXBFbnRyeSAqdiA9IChPckNs YXVzZUdyb3VwRW50cnkgKikgbGZpcnN0KGxjX2dyb3Vwcyk7CisKKwkJCQlBc3NlcnQodi0+ bm9kZSAhPSBOVUxMKTsKKworCQkJCWlmIChlcXVhbCh2LT5ub2RlLCBub25fY29uc3RfZXhw cikpCisJCQkJeworCQkJCQl2LT5jb25zdHMgPSBsYXBwZW5kKHYtPmNvbnN0cywgY29uc3Rf ZXhwcik7CisJCQkJCW5vbl9jb25zdF9leHByID0gTlVMTDsKKwkJCQkJYnJlYWs7CisJCQkJ fQorCQkJfQorCisJCQlpZiAobm9uX2NvbnN0X2V4cHIgPT0gTlVMTCkKKwkJCQkvKgorCQkJ CSAqIFRoZSBjbGF1c2UgY2xhc3NpZmllZCBzdWNjZXNzZnVsbHkgYW5kIGFkZGVkIGludG8g ZXhpc3RlZAorCQkJCSAqIGNsYXVzZSBncm91cC4KKwkJCQkgKi8KKwkJCQljb250aW51ZTsK KworCQkJLyogTmV3IGNsYXVzZSBncm91cCBuZWVkZWQgKi8KKwkJCWdlbnRyeSA9IHBhbGxv YyhzaXplb2YoT3JDbGF1c2VHcm91cEVudHJ5KSk7CisJCQlnZW50cnktPm5vZGUgPSBub25f Y29uc3RfZXhwcjsKKwkJCWdlbnRyeS0+Y29uc3RzID0gbGlzdF9tYWtlMShjb25zdF9leHBy KTsKKwkJCWdlbnRyeS0+Y29sbGF0aW9uID0gZXhwcklucHV0Q29sbGF0aW9uKChOb2RlICop c3ViX3JpbmZvLT5jbGF1c2UpOworCQkJZ2VudHJ5LT5vcG5vID0gb3BubzsKKwkJCWdlbnRy eS0+cmluZm8gPSBzdWJfcmluZm87CisJCQlncm91cHNfbGlzdCA9IGxhcHBlbmQoZ3JvdXBz X2xpc3QsICAodm9pZCAqKSBnZW50cnkpOworCQl9CisKKwkJaWYgKGdyb3Vwc19saXN0ID09 IE5JTCkKKwkJeworCQkJLyoKKwkJCSAqIE5vIGFueSB0cmFuc2Zvcm1hdGlvbnMgcG9zc2li bGUgd2l0aCB0aGlzIHJpbmZvLCBqdXN0IGFkZCBpdHNlbGYKKwkJCSAqIHRvIHRoZSBsaXN0 IGFuZCBnbyBmdXJ0aGVyLgorCQkJICovCisJCQltb2RpZmllZF9yaW5mbyA9IGxhcHBlbmQo bW9kaWZpZWRfcmluZm8sIHJpbmZvKTsKKwkJCWNvbnRpbnVlOworCQl9CisKKwkJLyogTGV0 J3MgY29udmVydCBlYWNoIGdyb3VwIG9mIGNsYXVzZXMgdG8gYW4gSU4gb3BlcmF0aW9uLiAq LworCisJCS8qCisJCSAqIEdvIHRocm91Z2ggdGhlIGxpc3Qgb2YgZ3JvdXBzIGFuZCBjb252 ZXJ0IGVhY2gsIHdoZXJlIG51bWJlciBvZgorCQkgKiBjb25zdHMgbW9yZSB0aGFuIDEuIHRy aXZpYWwgZ3JvdXBzIG1vdmUgdG8gT1ItbGlzdCBhZ2FpbgorCQkgKi8KKworCQlmb3JlYWNo KGxjX2FyZ3MsIGdyb3Vwc19saXN0KQorCQl7CisJCQlPckNsYXVzZUdyb3VwRW50cnkgKmdl bnRyeSA9IChPckNsYXVzZUdyb3VwRW50cnkgKikgbGZpcnN0KGxjX2FyZ3MpOworCQkJU2Nh bGFyQXJyYXlPcEV4cHIgICpzYW9wZXhwcjsKKwkJCUFycmF5RXhwcgkJICAgKm5ld2E7CisK KwkJCUFzc2VydChsaXN0X2xlbmd0aChnZW50cnktPmNvbnN0cykgPiAwKTsKKworCQkJaWYg KGxpc3RfbGVuZ3RoKGdlbnRyeS0+Y29uc3RzKSA9PSAxKQorCQkJeworCQkJCS8qCisJCQkJ ICogT25seSBvbmUgZWxlbWVudCBpbiB0aGUgY2xhc3MuIFJldHVybiByaW5mbyBpbnRvIHRo ZSBCb29sRXhwcgorCQkJCSAqIGFyZ3MgbGlzdCB1bmNoYW5nZWQuCisJCQkJICovCisJCQkJ bGlzdF9mcmVlKGdlbnRyeS0+Y29uc3RzKTsKKwkJCQlvcl9saXN0ID0gbGFwcGVuZChvcl9s aXN0LCAodm9pZCAqKSBnZW50cnktPnJpbmZvLT5jbGF1c2UpOworCQkJCWNvbnRpbnVlOwor CQkJfQorCisJCQkvKgorCQkJICogRG8gdGhlIHRyYW5zZm9ybWF0aW9uLiBJdCdzIGJlZW4g YSBsb25nIHdheSA7KQorCQkJICoKKwkJCSAqIEFzIGEgc291cmNlIG9mIGluc2lkZXMsIHVz ZSBtYWtlX3NjYWxhcl9hcnJheV9vcCgpCisJCQkgKi8KKworCQkJbmV3YSA9IG1ha2VOb2Rl KEFycmF5RXhwcik7CisJCQluZXdhLT5lbGVtZW50X3R5cGVpZCA9IGV4cHJUeXBlKGdlbnRy eS0+bm9kZSk7CisJCQluZXdhLT5hcnJheV90eXBlaWQgPSBuZXdhLT5lbGVtZW50X3R5cGVp ZDsgLyogZG9uJ3QgdXNlZCBpbiB0aGUgY2FzZSBvZiBvbmUgZGltZW5zaW9uLCBidXQgZXhw clR5cGUgcmV0dXJucyB0aGlzIHZhbHVlICovCisJCQluZXdhLT5tdWx0aWRpbXMgPSBmYWxz ZTsKKwkJCW5ld2EtPmVsZW1lbnRzID0gZ2VudHJ5LT5jb25zdHM7CisJCQluZXdhLT5sb2Nh dGlvbiA9IC0xOyAvKiBQb3NpdGlvbiBvZiB0aGUgbmV3IGNsYXVzZSBpcyB1bmRlZmluZWQg Ki8KKworCQkJc2FvcGV4cHIgPSBtYWtlTm9kZShTY2FsYXJBcnJheU9wRXhwcik7CisJCQlz YW9wZXhwci0+b3BubyA9IGdlbnRyeS0+b3BubzsKKwkJCXNhb3BleHByLT5vcGZ1bmNpZCA9 IGdldF9vcGNvZGUoZ2VudHJ5LT5vcG5vKTsKKwkJCXNhb3BleHByLT51c2VPciA9IHRydWU7 CisJCQlzYW9wZXhwci0+aW5wdXRjb2xsaWQgPSBnZW50cnktPmNvbGxhdGlvbjsKKwkJCXNh b3BleHByLT5hcmdzID0gbGlzdF9tYWtlMihnZW50cnktPm5vZGUsIG5ld2EpOworCQkJc2Fv cGV4cHItPmxvY2F0aW9uID0gLTE7CisKKwkJCS8qIFRPRE86IHN0dWR5IG9uIHRoZXNlIHBh cmFtZXRlcnMuICovCisJCQlzYW9wZXhwci0+aGFzaGZ1bmNpZCA9IEludmFsaWRPaWQ7CisJ CQlzYW9wZXhwci0+bmVnZnVuY2lkID0gSW52YWxpZE9pZDsKKworCQkJLyoKKwkJCSAqIFRP RE86IGhlcmUgd2UgY2FuIHRyeSB0byBjb2VyY2UgdGhlIGFycmF5IHRvIGEgQ29uc3QgYW5k IGZpbmQKKwkJCSAqIGhhc2ggZnVuYyBpbnN0ZWFkIG9mIGxpbmVhciBzZWFyY2ggKHNlZSA1 MGUxN2FkMjgxYikuCisJCQkgKiBjb252ZXJ0X3Nhb3BfdG9faGFzaGVkX3Nhb3AoKE5vZGUg Kikgc2FvcGV4cHIpOworCQkJICovCisKKwkJCW9yX2xpc3QgPSBsYXBwZW5kKG9yX2xpc3Qs ICh2b2lkICopIHNhb3BleHByKTsKKwkJCWNoYW5nZV9hcHBseSA9IHRydWU7CisJCX0KKwor CQlpZiAoIWNoYW5nZV9hcHBseSkKKwkJeworCQkJLyoKKwkJCSAqIEVhY2ggZ3JvdXAgY29u dGFpbnMgb25seSBvbmUgZWxlbWVudCAtIHVzZSByaW5mbyBhcyBpcy4KKwkJCSAqLworCQkJ bW9kaWZpZWRfcmluZm8gPSBsYXBwZW5kKG1vZGlmaWVkX3JpbmZvLCByaW5mbyk7CisJCQls aXN0X2ZyZWUob3JfbGlzdCk7CisJCQlsaXN0X2ZyZWVfZGVlcChncm91cHNfbGlzdCk7CisJ CQljb250aW51ZTsKKwkJfQorCisJCS8qCisJCSAqIE1ha2UgYSBuZXcgdmVyc2lvbiBvZiB0 aGUgcmVzdHJpY3Rpb24uIFJlbWVtYmVyIHNvdXJjZSByZXN0cmljdGlvbgorCQkgKiBjYW4g YmUgdXNlZCBpbiBhbm90aGVyIHBhdGggKFNlcVNjYW4sIGZvciBleGFtcGxlKS4KKwkJICov CisKKwkJLyogT25lIG1vcmUgdHJpY2s6IGFzc2VtYmxlIGNvcnJlY3QgY2xhdXNlICovCisJ CXJpbmZvID0gbWFrZV9yZXN0cmljdGluZm8ocm9vdCwKKwkJCQkgIGxpc3RfbGVuZ3RoKG9y X2xpc3QpID4gMSA/IG1ha2Vfb3JjbGF1c2Uob3JfbGlzdCkgOgorCQkJCQkJCQkJCQkgKEV4 cHIgKikgbGluaXRpYWwob3JfbGlzdCksCisJCQkJICByaW5mby0+aXNfcHVzaGVkX2Rvd24s CisJCQkJICByaW5mby0+aGFzX2Nsb25lLAorCQkJCSAgcmluZm8tPmlzX2Nsb25lLAorCQkJ CSAgcmluZm8tPnBzZXVkb2NvbnN0YW50LAorCQkJCSAgcmluZm8tPnNlY3VyaXR5X2xldmVs LAorCQkJCSAgcmluZm8tPnJlcXVpcmVkX3JlbGlkcywKKwkJCQkgIHJpbmZvLT5pbmNvbXBh dGlibGVfcmVsaWRzLAorCQkJCSAgcmluZm8tPm91dGVyX3JlbGlkcyk7CisJCXJpbmZvLT5l dmFsX2Nvc3Q9cmluZm9fYmFzZS0+ZXZhbF9jb3N0OworCQlyaW5mby0+bm9ybV9zZWxlYz1y aW5mb19iYXNlLT5ub3JtX3NlbGVjOworCQlyaW5mby0+b3V0ZXJfc2VsZWM9cmluZm9fYmFz ZS0+b3V0ZXJfc2VsZWM7CisJCXJpbmZvLT5sZWZ0X2J1Y2tldHNpemU9cmluZm9fYmFzZS0+ bGVmdF9idWNrZXRzaXplOworCQlyaW5mby0+cmlnaHRfYnVja2V0c2l6ZT1yaW5mb19iYXNl LT5yaWdodF9idWNrZXRzaXplOworCQlyaW5mby0+bGVmdF9tY3ZmcmVxPXJpbmZvX2Jhc2Ut PmxlZnRfbWN2ZnJlcTsKKwkJcmluZm8tPnJpZ2h0X21jdmZyZXE9cmluZm9fYmFzZS0+cmln aHRfbWN2ZnJlcTsKKwkJbW9kaWZpZWRfcmluZm8gPSBsYXBwZW5kKG1vZGlmaWVkX3JpbmZv LCByaW5mbyk7CisJCWxpc3RfZnJlZV9kZWVwKGdyb3Vwc19saXN0KTsKKwkJc29tZXRoaW5n X2NoYW5nZWQgPSB0cnVlOworCX0KKworCS8qCisJICogQ2hlY2sgaWYgdHJhbnNmb3JtYXRp b24gaGFzIG1hZGUuIElmIG5vdGhpbmcgY2hhbmdlZCAtIHJldHVybgorCSAqIGJhc2VyZXN0 cmljdGluZm8gYXMgaXMuCisJICovCisJaWYgKHNvbWV0aGluZ19jaGFuZ2VkKQorCXsKKwkJ cmV0dXJuIG1vZGlmaWVkX3JpbmZvOworCX0KKworCWxpc3RfZnJlZShtb2RpZmllZF9yaW5m byk7CisJcmV0dXJuIGJhc2VyZXN0cmljdGluZm87Cit9CiAKIC8qCiAgKiBjcmVhdGVfaW5k ZXhfcGF0aHMoKQpAQCAtMzMwOSwxMSArMzU3NiwxNiBAQCBjaGVja19pbmRleF9wcmVkaWNh dGVzKFBsYW5uZXJJbmZvICpyb290LCBSZWxPcHRJbmZvICpyZWwpCiAJICogbm90LCB0aGlz IGlzIGFsbCB3ZSBuZWVkIHRvIGRvLgogCSAqLwogCWhhdmVfcGFydGlhbCA9IGZhbHNlOwor CisJaWYgKHJlbC0+cmVsb3B0a2luZCA9PSBSRUxPUFRfQkFTRVJFTCkKKwkJcmVsLT5iYXNl cmVzdHJpY3RpbmZvID0gdHJhbnNmb3JtX29ycyhyb290LCByZWwtPmJhc2VyZXN0cmljdGlu Zm8pOworCiAJZm9yZWFjaChsYywgcmVsLT5pbmRleGxpc3QpCiAJewogCQlJbmRleE9wdElu Zm8gKmluZGV4ID0gKEluZGV4T3B0SW5mbyAqKSBsZmlyc3QobGMpOwogCiAJCWluZGV4LT5p bmRyZXN0cmljdGluZm8gPSByZWwtPmJhc2VyZXN0cmljdGluZm87CisKIAkJaWYgKGluZGV4 LT5pbmRwcmVkKQogCQkJaGF2ZV9wYXJ0aWFsID0gdHJ1ZTsKIAl9Cg== --------------LxcDHSbxmLntC0r7Zn4MURVr--