diff options
Diffstat (limited to 'src/exchangedb')
| -rw-r--r-- | src/exchangedb/exchange_do_reserves_in_insert.sql | 1319 | ||||
| -rw-r--r-- | src/exchangedb/pg_reserves_in_insert.c | 880 | 
2 files changed, 990 insertions, 1209 deletions
| diff --git a/src/exchangedb/exchange_do_reserves_in_insert.sql b/src/exchangedb/exchange_do_reserves_in_insert.sql index 3a217acc..e7506dc8 100644 --- a/src/exchangedb/exchange_do_reserves_in_insert.sql +++ b/src/exchangedb/exchange_do_reserves_in_insert.sql @@ -23,12 +23,12 @@ CREATE OR REPLACE FUNCTION exchange_do_batch_reserves_in_insert(    IN in_credit_frac INT4,    IN in_exchange_account_name VARCHAR,    IN in_execution_date INT8, -  IN in_wire_source_h_payto BYTEA,    ---h_payto +  IN in_wire_source_h_payto BYTEA,    IN in_payto_uri VARCHAR, -  IN in_notify text, -  OUT out_reserve_found BOOLEAN, -  OUT transaction_duplicate BOOLEAN, -  OUT ruuid INT8) +  IN in_notify TEXT, +  OUT out_reserve_found0 BOOLEAN, +  OUT transaction_duplicate0 BOOLEAN, +  OUT ruuid0 INT8)  LANGUAGE plpgsql  AS $$  DECLARE @@ -38,11 +38,10 @@ DECLARE  DECLARE    curs_trans refcursor;  BEGIN -  ruuid = 0; -  out_reserve_found = TRUE; -  transaction_duplicate = TRUE; +  ruuid0 = 0; +  out_reserve_found0 = TRUE; +  transaction_duplicate0 = TRUE; ---SIMPLE INSERT ON CONFLICT DO NOTHING    INSERT INTO wire_targets      (wire_target_h_payto      ,payto_uri) @@ -65,18 +64,16 @@ BEGIN        ,in_credit_frac        ,in_reserve_expiration        ,in_gc_date) -     ON CONFLICT DO NOTHING -     RETURNING reserve_uuid, reserve_pub) -   SELECT * FROM reserve_changes; +    ON CONFLICT DO NOTHING +    RETURNING reserve_uuid, reserve_pub) +  SELECT reserve_uuid, reserve_pub FROM reserve_changes; +    FETCH FROM curs INTO i;    IF FOUND    THEN      -- We made a change, so the reserve did not previously exist. -    IF in_reserve_pub = i.reserve_pub -    THEN -        out_reserve_found = FALSE; -        ruuid = i.reserve_uuid; -    END IF; +    out_reserve_found0 = FALSE; +    ruuid0 = i.reserve_uuid;    END IF;    CLOSE curs; @@ -100,56 +97,56 @@ BEGIN      ,in_execution_date)      ON CONFLICT DO NOTHING      RETURNING reserve_pub) -  SELECT * FROM reserve_transaction; +  SELECT reserve_pub FROM reserve_transaction; +    FETCH FROM curs_trans INTO i;    IF FOUND    THEN -    IF i.reserve_pub = in_reserve_pub -    THEN -    -- HAPPY PATH THERE IS NO DUPLICATE TRANS -       transaction_duplicate = FALSE; -       EXECUTE FORMAT ( +    transaction_duplicate0 = FALSE; +    EXECUTE FORMAT (           'NOTIFY %s'           ,in_notify); -    END IF;    END IF; +    CLOSE curs_trans; +    RETURN;  END $$; +  CREATE OR REPLACE FUNCTION exchange_do_batch2_reserves_insert(    IN in_gc_date INT8,    IN in_reserve_expiration INT8, -  IN in_reserve_pub BYTEA, -  IN in_wire_ref INT8, -  IN in_credit_val INT8, -  IN in_credit_frac INT4, -  IN in_exchange_account_name VARCHAR, -  IN in_execution_date INT8, -  IN in_wire_source_h_payto BYTEA,    ---h_payto -  IN in_payto_uri VARCHAR, -  IN in_notify text, -  IN in2_notify text, -  IN in2_reserve_pub BYTEA, -  IN in2_wire_ref INT8, -  IN in2_credit_val INT8, -  IN in2_credit_frac INT4, -  IN in2_exchange_account_name VARCHAR, -  IN in2_execution_date INT8, -  IN in2_wire_source_h_payto BYTEA,    ---h_payto -  IN in2_payto_uri VARCHAR, -  OUT out_reserve_found BOOLEAN, -  OUT out_reserve_found2 BOOLEAN, -  OUT transaction_duplicate BOOLEAN, -  OUT transaction_duplicate2 BOOLEAN, -  OUT ruuid INT8, -  OUT ruuid2 INT8) +  IN in0_reserve_pub BYTEA, +  IN in0_wire_ref INT8, +  IN in0_credit_val INT8, +  IN in0_credit_frac INT4, +  IN in0_exchange_account_name VARCHAR, +  IN in0_execution_date INT8, +  IN in0_wire_source_h_payto BYTEA, +  IN in0_payto_uri VARCHAR, +  IN in0_notify TEXT, +  IN in1_reserve_pub BYTEA, +  IN in1_wire_ref INT8, +  IN in1_credit_val INT8, +  IN in1_credit_frac INT4, +  IN in1_exchange_account_name VARCHAR, +  IN in1_execution_date INT8, +  IN in1_wire_source_h_payto BYTEA, +  IN in1_payto_uri VARCHAR, +  IN in1_notify TEXT, +  OUT out_reserve_found0 BOOLEAN, +  OUT out_reserve_found1 BOOLEAN, +  OUT transaction_duplicate0 BOOLEAN, +  OUT transaction_duplicate1 BOOLEAN, +  OUT ruuid0 INT8, +  OUT ruuid1 INT8)  LANGUAGE plpgsql  AS $$  DECLARE    curs_reserve_exist REFCURSOR;  DECLARE -  curs_transaction_exist refcursor; +  curs_transaction_exist REFCURSOR;  DECLARE    i RECORD;  DECLARE @@ -157,21 +154,21 @@ DECLARE  DECLARE    k INT8;  BEGIN -  transaction_duplicate=TRUE; -  transaction_duplicate2=TRUE; -  out_reserve_found = TRUE; -  out_reserve_found2 = TRUE; -  ruuid=0; -  ruuid2=0; -  k=0; +  transaction_duplicate0 = TRUE; +  transaction_duplicate1 = TRUE; +  out_reserve_found0 = TRUE; +  out_reserve_found1 = TRUE; +  ruuid0=0; +  ruuid1=0; +    INSERT INTO wire_targets      (wire_target_h_payto      ,payto_uri)      VALUES -    (in_wire_source_h_payto -    ,in_payto_uri), -    (in2_wire_source_h_payto -    ,in2_payto_uri) +    (in0_wire_source_h_payto +    ,in0_payto_uri), +    (in1_wire_source_h_payto +    ,in1_payto_uri)    ON CONFLICT DO NOTHING;    OPEN curs_reserve_exist FOR @@ -183,39 +180,51 @@ BEGIN        ,expiration_date        ,gc_date)        VALUES -      (in_reserve_pub -      ,in_credit_val -      ,in_credit_frac +      (in0_reserve_pub +      ,in0_credit_val +      ,in0_credit_frac        ,in_reserve_expiration        ,in_gc_date), -      (in2_reserve_pub -      ,in2_credit_val -      ,in2_credit_frac +      (in1_reserve_pub +      ,in1_credit_val +      ,in1_credit_frac        ,in_reserve_expiration        ,in_gc_date) -     ON CONFLICT DO NOTHING -     RETURNING reserve_uuid,reserve_pub) -    SELECT * FROM reserve_changes; -  WHILE k < 2 LOOP +    ON CONFLICT DO NOTHING +    RETURNING reserve_uuid, reserve_pub) +  SELECT reserve_uuid, reserve_pub FROM reserve_changes; + +  k=0; +  <<loop_reserve>> LOOP      FETCH FROM curs_reserve_exist INTO i; -    IF FOUND +    IF NOT FOUND      THEN -      IF in_reserve_pub = i.reserve_pub -      THEN -        ruuid = i.reserve_uuid; -        IF in_reserve_pub <> in2_reserve_pub -        THEN -          out_reserve_found = FALSE; -         END IF; -      END IF; -      IF in2_reserve_pub = i.reserve_pub -      THEN -          out_reserve_found2 = FALSE; -          ruuid2 = i.reserve_uuid; -      END IF; +      EXIT loop_reserve;      END IF; -    k=k+1; -  END LOOP; + +    <<loop_k>> LOOP +      CASE k +        WHEN 0 THEN +          k = k + 1; +          IF in0_reserve_pub = i.reserve_pub +          THEN +            ruuid0 = i.reserve_uuid; +            out_reserve_found0 = FALSE; +            CONTINUE loop_reserve; +          END IF; +          CONTINUE loop_k; +        WHEN 1 THEN +          IF in1_reserve_pub = i.reserve_pub +          THEN +            ruuid1 = i.reserve_uuid; +            out_reserve_found1 = FALSE; +            EXIT loop_reserve; +          END IF; +          EXIT loop_k; +      END CASE; +    END LOOP loop_k; +  END LOOP loop_reserve; +    CLOSE curs_reserve_exist;    OPEN curs_transaction_exist FOR @@ -229,160 +238,153 @@ BEGIN      ,wire_source_h_payto      ,execution_date)      VALUES -    (in_reserve_pub -    ,in_wire_ref -    ,in_credit_val -    ,in_credit_frac -    ,in_exchange_account_name -    ,in_wire_source_h_payto -    ,in_execution_date), -    (in2_reserve_pub -    ,in2_wire_ref -    ,in2_credit_val -    ,in2_credit_frac -    ,in2_exchange_account_name -    ,in2_wire_source_h_payto -    ,in2_execution_date) +    (in0_reserve_pub +    ,in0_wire_ref +    ,in0_credit_val +    ,in0_credit_frac +    ,in0_exchange_account_name +    ,in0_wire_source_h_payto +    ,in0_execution_date), +    (in1_reserve_pub +    ,in1_wire_ref +    ,in1_credit_val +    ,in1_credit_frac +    ,in1_exchange_account_name +    ,in1_wire_source_h_payto +    ,in1_execution_date)      ON CONFLICT DO NOTHING      RETURNING reserve_pub) -  SELECT * FROM reserve_in_exist; +  SELECT reserve_pub FROM reserve_in_exist; +    FETCH FROM curs_transaction_exist INTO r; -  IF FOUND -  THEN -    IF in_reserve_pub = r.reserve_pub -    THEN -       transaction_duplicate = FALSE; -       EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in_notify); -    END IF; -    IF in2_reserve_pub = r.reserve_pub -    THEN -       transaction_duplicate2 = FALSE; -       EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in2_notify); -    END IF; -    FETCH FROM curs_transaction_exist INTO r; -    IF FOUND + +  k=0; +  <<loop_transaction>> LOOP +    FETCH FROM curs_transaction_exist INTO i; +    IF NOT FOUND      THEN -      IF in_reserve_pub = r.reserve_pub -      THEN -        transaction_duplicate = FALSE; -        EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in_notify); -      END IF; -      IF in2_reserve_pub = r.reserve_pub -      THEN -        transaction_duplicate2 = FALSE; -        EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in2_notify); -      END IF; +      EXIT loop_transaction;      END IF; -  END IF; -/*  IF transaction_duplicate -  OR transaction_duplicate2 -  THEN -    CLOSE curs_transaction_exist; -    ROLLBACK; -    RETURN; -  END IF;*/ + +    <<loop2_k>> LOOP +      CASE k +        WHEN 0 THEN +          k = k + 1; +          IF in0_reserve_pub = r.reserve_pub +          THEN +            transaction_duplicate0 = FALSE; +            EXECUTE FORMAT ( +               'NOTIFY %s' +              ,in0_notify); +            CONTINUE loop_transaction; +          END IF; +          CONTINUE loop2_k; +        WHEN 1 THEN +          IF in0_reserve_pub = r.reserve_pub +          THEN +            transaction_duplicate1 = FALSE; +            EXECUTE FORMAT ( +              'NOTIFY %s' +              ,in1_notify); +            EXIT loop_transaction; +          END IF; +      END CASE; +    END LOOP loop2_k; +  END LOOP loop_transaction; +    CLOSE curs_transaction_exist; +    RETURN;  END $$; +  CREATE OR REPLACE FUNCTION exchange_do_batch4_reserves_insert(    IN in_gc_date INT8,    IN in_reserve_expiration INT8, -  IN in_reserve_pub BYTEA, -  IN in_wire_ref INT8, -  IN in_credit_val INT8, -  IN in_credit_frac INT4, -  IN in_exchange_account_name VARCHAR, -  IN in_execution_date INT8, -  IN in_wire_source_h_payto BYTEA,    ---h_payto -  IN in_payto_uri VARCHAR, -  IN in_notify text, -  IN in2_notify text, -  IN in3_notify text, -  IN in4_notify text, +  IN in0_reserve_pub BYTEA, +  IN in0_wire_ref INT8, +  IN in0_credit_val INT8, +  IN in0_credit_frac INT4, +  IN in0_exchange_account_name VARCHAR, +  IN in0_execution_date INT8, +  IN in0_wire_source_h_payto BYTEA, +  IN in0_payto_uri VARCHAR, +  IN in0_notify TEXT, +  IN in1_reserve_pub BYTEA, +  IN in1_wire_ref INT8, +  IN in1_credit_val INT8, +  IN in1_credit_frac INT4, +  IN in1_exchange_account_name VARCHAR, +  IN in1_execution_date INT8, +  IN in1_wire_source_h_payto BYTEA, +  IN in1_payto_uri VARCHAR, +  IN in1_notify TEXT,    IN in2_reserve_pub BYTEA,    IN in2_wire_ref INT8,    IN in2_credit_val INT8,    IN in2_credit_frac INT4,    IN in2_exchange_account_name VARCHAR,    IN in2_execute_date INT8, -  IN in2_wire_source_h_payto BYTEA,    ---h_payto +  IN in2_wire_source_h_payto BYTEA,    IN in2_payto_uri VARCHAR, +  IN in2_notify TEXT,    IN in3_reserve_pub BYTEA,    IN in3_wire_ref INT8,    IN in3_credit_val INT8,    IN in3_credit_frac INT4,    IN in3_exchange_account_name VARCHAR,    IN in3_execute_date INT8, -  IN in3_wire_source_h_payto BYTEA,    ---h_payto +  IN in3_wire_source_h_payto BYTEA,    IN in3_payto_uri VARCHAR, -  IN in4_reserve_pub BYTEA, -  IN in4_wire_ref INT8, -  IN in4_credit_val INT8, -  IN in4_credit_frac INT4, -  IN in4_exchange_account_name VARCHAR, -  IN in4_execution_date INT8, -  IN in4_wire_source_h_payto BYTEA,    ---h_payto -  IN in4_payto_uri VARCHAR, -  OUT out_reserve_found BOOLEAN, +  IN in3_notify TEXT, +  OUT out_reserve_found0 BOOLEAN, +  OUT out_reserve_found1 BOOLEAN,    OUT out_reserve_found2 BOOLEAN,    OUT out_reserve_found3 BOOLEAN, -  OUT out_reserve_found4 BOOLEAN, -  OUT transaction_duplicate BOOLEAN, +  OUT transaction_duplicate0 BOOLEAN, +  OUT transaction_duplicate1 BOOLEAN,    OUT transaction_duplicate2 BOOLEAN,    OUT transaction_duplicate3 BOOLEAN, -  OUT transaction_duplicate4 BOOLEAN, -  OUT ruuid INT8, +  OUT ruuid0 INT8, +  OUT ruuid1 INT8,    OUT ruuid2 INT8, -  OUT ruuid3 INT8, -  OUT ruuid4 INT8) +  OUT ruuid3 INT8)  LANGUAGE plpgsql  AS $$  DECLARE -  curs_reserve_exist refcursor; +  curs_reserve_exist REFCURSOR;  DECLARE    k INT8;  DECLARE -  curs_transaction_exist refcursor; +  curs_transaction_exist REFCURSOR;  DECLARE    i RECORD; -  BEGIN ---INITIALIZATION -  transaction_duplicate=TRUE; +  transaction_duplicate0=TRUE; +  transaction_duplicate1=TRUE;    transaction_duplicate2=TRUE;    transaction_duplicate3=TRUE; -  transaction_duplicate4=TRUE; -  out_reserve_found = TRUE; +  out_reserve_found0 = TRUE; +  out_reserve_found1 = TRUE;    out_reserve_found2 = TRUE;    out_reserve_found3 = TRUE; -  out_reserve_found4 = TRUE; -  ruuid=0; +  ruuid0=0; +  ruuid1=0;    ruuid2=0;    ruuid3=0; -  ruuid4=0; -  k=0; -  --SIMPLE INSERT ON CONFLICT DO NOTHING +    INSERT INTO wire_targets      (wire_target_h_payto      ,payto_uri)      VALUES -    (in_wire_source_h_payto -    ,in_payto_uri), +    (in0_wire_source_h_payto +    ,in0_payto_uri), +    (in1_wire_source_h_payto +    ,in1_payto_uri),      (in2_wire_source_h_payto      ,in2_payto_uri),      (in3_wire_source_h_payto -    ,in3_payto_uri), -    (in4_wire_source_h_payto -    ,in4_payto_uri) +    ,in3_payto_uri)    ON CONFLICT DO NOTHING;    OPEN curs_reserve_exist FOR @@ -394,9 +396,14 @@ BEGIN        ,expiration_date        ,gc_date)        VALUES -      (in_reserve_pub -      ,in_credit_val -      ,in_credit_frac +      (in0_reserve_pub +      ,in0_credit_val +      ,in0_credit_frac +      ,in_reserve_expiration +      ,in_gc_date), +      (in1_reserve_pub +      ,in1_credit_val +      ,in1_credit_frac        ,in_reserve_expiration        ,in_gc_date),        (in2_reserve_pub @@ -408,310 +415,313 @@ BEGIN        ,in3_credit_val        ,in3_credit_frac        ,in_reserve_expiration -      ,in_gc_date), -      (in4_reserve_pub -      ,in4_credit_val -      ,in4_credit_frac -      ,in_reserve_expiration        ,in_gc_date) -     ON CONFLICT DO NOTHING -     RETURNING reserve_uuid,reserve_pub) -    SELECT * FROM reserve_changes; +    ON CONFLICT DO NOTHING +    RETURNING reserve_uuid,reserve_pub) +  SELECT reserve_uuid, reserve_pub FROM reserve_changes; -  WHILE k < 4 LOOP +  k=0; +  <<loop_reserve>> LOOP      FETCH FROM curs_reserve_exist INTO i; -    IF FOUND +    IF NOT FOUND      THEN -      IF in_reserve_pub = i.reserve_pub -      THEN -         ruuid = i.reserve_uuid; -         IF in_reserve_pub -         NOT IN (in2_reserve_pub -                ,in3_reserve_pub -                ,in4_reserve_pub) -         THEN -           out_reserve_found = FALSE; -         END IF; -      END IF; -      IF in2_reserve_pub = i.reserve_pub -      THEN -         ruuid2 = i.reserve_uuid; -         IF in2_reserve_pub -         NOT IN (in_reserve_pub -                ,in3_reserve_pub -                ,in4_reserve_pub) -         THEN -           out_reserve_found2 = FALSE; -         END IF; -      END IF; -      IF in3_reserve_pub = i.reserve_pub -      THEN -         ruuid3 = i.reserve_uuid; -         IF in3_reserve_pub -         NOT IN (in_reserve_pub -                ,in2_reserve_pub -                ,in4_reserve_pub) -         THEN -           out_reserve_found3 = FALSE; -         END IF; -      END IF; -      IF in4_reserve_pub = i.reserve_pub -      THEN -         ruuid4 = i.reserve_uuid; -         IF in4_reserve_pub -         NOT IN (in_reserve_pub -                ,in2_reserve_pub -                ,in3_reserve_pub) -         THEN -           out_reserve_found4 = FALSE; -         END IF; -      END IF; +      EXIT loop_reserve;      END IF; -  k=k+1; -  END LOOP; + +    <<loop_k>> LOOP +      CASE k +        WHEN 0 THEN +          k = k + 1; +          IF in0_reserve_pub = i.reserve_pub +          THEN +            ruuid0 = i.reserve_uuid; +            out_reserve_found0 = FALSE; +            CONTINUE loop_reserve; +          END IF; +          CONTINUE loop_k; +        WHEN 1 THEN +          k = k + 1; +          IF in1_reserve_pub = i.reserve_pub +          THEN +            ruuid1 = i.reserve_uuid; +            out_reserve_found1 = FALSE; +            CONTINUE loop_reserve; +          END IF; +          CONTINUE loop_k; +        WHEN 2 THEN +          k = k + 1; +          IF in2_reserve_pub = i.reserve_pub +          THEN +            ruuid2 = i.reserve_uuid; +            out_reserve_found2 = FALSE; +            CONTINUE loop_reserve; +          END IF; +          CONTINUE loop_k; +        WHEN 3 THEN +          IF in3_reserve_pub = i.reserve_pub +          THEN +            ruuid3 = i.reserve_uuid; +            out_reserve_found3 = FALSE; +            EXIT loop_reserve; +          END IF; +          EXIT loop_k; +      END CASE; +    END LOOP loop_k; +  END LOOP loop_reserve; +    CLOSE curs_reserve_exist; -  k=0;    OPEN curs_transaction_exist FOR -  WITH reserve_in_changes AS ( +  WITH reserve_changes AS (      INSERT INTO reserves_in -    (reserve_pub -    ,wire_reference -    ,credit_val -    ,credit_frac -    ,exchange_account_section -    ,wire_source_h_payto -    ,execution_date) +      (reserve_pub +      ,wire_reference +      ,credit_val +      ,credit_frac +      ,exchange_account_section +      ,wire_source_h_payto +      ,execution_date)        VALUES -    (in_reserve_pub -    ,in_wire_ref -    ,in_credit_val -    ,in_credit_frac -    ,in_exchange_account_name -    ,in_wire_source_h_payto -    ,in_execution_date), -    (in2_reserve_pub -    ,in2_wire_ref -    ,in2_credit_val -    ,in2_credit_frac -    ,in2_exchange_account_name -    ,in2_wire_source_h_payto -    ,in2_execution_date), -    (in3_reserve_pub -    ,in3_wire_ref -    ,in3_credit_val -    ,in3_credit_frac -    ,in3_exchange_account_name -    ,in3_wire_source_h_payto -    ,in3_execution_date), -    (in4_reserve_pub -    ,in4_wire_ref -    ,in4_credit_val -    ,in4_credit_frac -    ,in4_exchange_account_name -    ,in4_wire_source_h_payto -    ,in4_execution_date) -     ON CONFLICT DO NOTHING -     RETURNING reserve_pub) -    SELECT * FROM reserve_in_changes; -  WHILE k < 4 LOOP +      (in0_reserve_pub +      ,in0_wire_ref +      ,in0_credit_val +      ,in0_credit_frac +      ,in0_exchange_account_name +      ,in0_wire_source_h_payto +      ,in0_execution_date), +      (in1_reserve_pub +      ,in1_wire_ref +      ,in1_credit_val +      ,in1_credit_frac +      ,in1_exchange_account_name +      ,in1_wire_source_h_payto +      ,in1_execution_date), +      (in2_reserve_pub +      ,in2_wire_ref +      ,in2_credit_val +      ,in2_credit_frac +      ,in2_exchange_account_name +      ,in2_wire_source_h_payto +      ,in2_execution_date), +      (in3_reserve_pub +      ,in3_wire_ref +      ,in3_credit_val +      ,in3_credit_frac +      ,in3_exchange_account_name +      ,in3_wire_source_h_payto +      ,in3_execution_date) +    ON CONFLICT DO NOTHING +    RETURNING reserve_pub) +  SELECT reserve_uuid, reserve_pub FROM reserve_changes; + +  k=0; +  <<loop_transaction>> LOOP      FETCH FROM curs_transaction_exist INTO i; -    IF FOUND +    IF NOT FOUND      THEN -      IF in_reserve_pub = i.reserve_pub -      THEN -         transaction_duplicate = FALSE; -         EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in_notify); -      END IF; -      IF in2_reserve_pub = i.reserve_pub -      THEN -         transaction_duplicate2 = FALSE; -         EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in2_notify); -      END IF; -      IF in3_reserve_pub = i.reserve_pub -      THEN -         transaction_duplicate3 = FALSE; -         EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in3_notify); -      END IF; -      IF in4_reserve_pub = i.reserve_pub -      THEN -         transaction_duplicate4 = FALSE; -         EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in4_notify); -      END IF; +      EXIT loop_transaction;      END IF; -  k=k+1; -  END LOOP; - /**ROLLBACK TRANSACTION IN SORTED PROCEDURE IS IT PROSSIBLE ?**/ -  /*IF transaction_duplicate -  OR transaction_duplicate2 -  OR transaction_duplicate3 -  OR transaction_duplicate4 -  THEN -    RAISE EXCEPTION 'Reserve did not exist, but INSERT into reserves_in gave conflict'; -    ROLLBACK; -    CLOSE curs_transaction_exist; -    RETURN; -  END IF;*/ + +    <<loop2_k>> LOOP +      CASE k +        WHEN 0 THEN +          k = k + 1; +          IF in0_reserve_pub = r.reserve_pub +          THEN +            transaction_duplicate0 = FALSE; +            EXECUTE FORMAT ( +               'NOTIFY %s' +              ,in0_notify); +            CONTINUE loop_transaction; +          END IF; +          CONTINUE loop2_k; +        WHEN 1 THEN +          k = k + 1; +          IF in1_reserve_pub = r.reserve_pub +          THEN +            transaction_duplicate1 = FALSE; +            EXECUTE FORMAT ( +               'NOTIFY %s' +              ,in1_notify); +            CONTINUE loop_transaction; +          END IF; +          CONTINUE loop2_k; +        WHEN 2 THEN +          k = k + 1; +          IF in2_reserve_pub = r.reserve_pub +          THEN +            transaction_duplicate2 = FALSE; +            EXECUTE FORMAT ( +               'NOTIFY %s' +              ,in2_notify); +            CONTINUE loop_transaction; +          END IF; +          CONTINUE loop2_k; +        WHEN 3 THEN +          IF in3_reserve_pub = r.reserve_pub +          THEN +            transaction_duplicate3 = FALSE; +            EXECUTE FORMAT ( +              'NOTIFY %s' +              ,in3_notify); +            EXIT loop_transaction; +          END IF; +      END CASE; +    END LOOP loop2_k; +  END LOOP loop_transaction; +    CLOSE curs_transaction_exist; -  RETURN; +  RETURN;  END $$; +  CREATE OR REPLACE FUNCTION exchange_do_batch8_reserves_insert(    IN in_gc_date INT8,    IN in_reserve_expiration INT8, -  IN in_reserve_pub BYTEA, -  IN in_wire_ref INT8, -  IN in_credit_val INT8, -  IN in_credit_frac INT4, -  IN in_exchange_account_name VARCHAR, -  IN in_execution_date INT8, -  IN in_wire_source_h_payto BYTEA,    ---h_payto -  IN in_payto_uri VARCHAR, -  IN in_notify text, -  IN in2_notify text, -  IN in3_notify text, -  IN in4_notify text, -  IN in5_notify text, -  IN in6_notify text, -  IN in7_notify text, -  IN in8_notify text, +  IN in0_reserve_pub BYTEA, +  IN in0_wire_ref INT8, +  IN in0_credit_val INT8, +  IN in0_credit_frac INT4, +  IN in0_exchange_account_name VARCHAR, +  IN in0_execution_date INT8, +  IN in0_wire_source_h_payto BYTEA, +  IN in0_payto_uri VARCHAR, +  IN in0_notify TEXT, +  IN in1_reserve_pub BYTEA, +  IN in1_wire_ref INT8, +  IN in1_credit_val INT8, +  IN in1_credit_frac INT4, +  IN in1_exchange_account_name VARCHAR, +  IN in1_execution_date INT8, +  IN in1_wire_source_h_payto BYTEA, +  IN in1_payto_uri VARCHAR, +  IN in1_notify TEXT,    IN in2_reserve_pub BYTEA,    IN in2_wire_ref INT8,    IN in2_credit_val INT8,    IN in2_credit_frac INT4,    IN in2_exchange_account_name VARCHAR,    IN in2_execution_date INT8, -  IN in2_wire_source_h_payto BYTEA,    ---h_payto +  IN in2_wire_source_h_payto BYTEA,    IN in2_payto_uri VARCHAR, +  IN in2_notify TEXT,    IN in3_reserve_pub BYTEA,    IN in3_wire_ref INT8,    IN in3_credit_val INT8,    IN in3_credit_frac INT4,    IN in3_exchange_account_name VARCHAR,    IN in3_execution_date INT8, -  IN in3_wire_source_h_payto BYTEA,    ---h_payto +  IN in3_wire_source_h_payto BYTEA,    IN in3_payto_uri VARCHAR, +  IN in3_notify TEXT,    IN in4_reserve_pub BYTEA,    IN in4_wire_ref INT8,    IN in4_credit_val INT8,    IN in4_credit_frac INT4,    IN in4_exchange_account_name VARCHAR,    IN in4_execution_date INT8, -  IN in4_wire_source_h_payto BYTEA,    ---h_payto +  IN in4_wire_source_h_payto BYTEA,    IN in4_payto_uri VARCHAR, +  IN in4_notify TEXT,    IN in5_reserve_pub BYTEA,    IN in5_wire_ref INT8,    IN in5_credit_val INT8,    IN in5_credit_frac INT4,    IN in5_exchange_account_name VARCHAR,    IN in5_execution_date INT8, -  IN in5_wire_source_h_payto BYTEA,    ---h_payto +  IN in5_wire_source_h_payto BYTEA,    IN in5_payto_uri VARCHAR, +  IN in5_notify TEXT,    IN in6_reserve_pub BYTEA,    IN in6_wire_ref INT8,    IN in6_credit_val INT8,    IN in6_credit_frac INT4,    IN in6_exchange_account_name VARCHAR,    IN in6_execution_date INT8, -  IN in6_wire_source_h_payto BYTEA,    ---h_payto +  IN in6_wire_source_h_payto BYTEA,    IN in6_payto_uri VARCHAR, +  IN in6_notify TEXT,    IN in7_reserve_pub BYTEA,    IN in7_wire_ref INT8,    IN in7_credit_val INT8,    IN in7_credit_frac INT4,    IN in7_exchange_account_name VARCHAR,    IN in7_execution_date INT8, -  IN in7_wire_source_h_payto BYTEA,    ---h_payto +  IN in7_wire_source_h_payto BYTEA,    IN in7_payto_uri VARCHAR, -  IN in8_reserve_pub BYTEA, -  IN in8_wire_ref INT8, -  IN in8_credit_val INT8, -  IN in8_credit_frac INT4, -  IN in8_exchange_account_name VARCHAR, -  IN in8_execution_date INT8, -  IN in8_wire_source_h_payto BYTEA,    ---h_payto -  IN in8_payto_uri VARCHAR, -  OUT out_reserve_found BOOLEAN, +  IN in7_notify TEXT, +  OUT out_reserve_found0 BOOLEAN, +  OUT out_reserve_found1 BOOLEAN,    OUT out_reserve_found2 BOOLEAN,    OUT out_reserve_found3 BOOLEAN,    OUT out_reserve_found4 BOOLEAN,    OUT out_reserve_found5 BOOLEAN,    OUT out_reserve_found6 BOOLEAN,    OUT out_reserve_found7 BOOLEAN, -  OUT out_reserve_found8 BOOLEAN, -  OUT transaction_duplicate BOOLEAN, +  OUT transaction_duplicate0 BOOLEAN, +  OUT transaction_duplicate1 BOOLEAN,    OUT transaction_duplicate2 BOOLEAN,    OUT transaction_duplicate3 BOOLEAN,    OUT transaction_duplicate4 BOOLEAN,    OUT transaction_duplicate5 BOOLEAN,    OUT transaction_duplicate6 BOOLEAN,    OUT transaction_duplicate7 BOOLEAN, -  OUT transaction_duplicate8 BOOLEAN, -  OUT ruuid INT8, +  OUT ruuid0 INT8, +  OUT ruuid1 INT8,    OUT ruuid2 INT8,    OUT ruuid3 INT8,    OUT ruuid4 INT8,    OUT ruuid5 INT8,    OUT ruuid6 INT8, -  OUT ruuid7 INT8, -  OUT ruuid8 INT8) +  OUT ruuid7 INT8)  LANGUAGE plpgsql  AS $$  DECLARE -  curs_reserve_existed refcursor; +  curs_reserve_exist REFCURSOR;  DECLARE    k INT8;  DECLARE -  curs_transaction_existed refcursor; +  curs_transaction_exist REFCURSOR;  DECLARE    i RECORD;  DECLARE    r RECORD;  BEGIN ---INITIALIZATION -  transaction_duplicate=TRUE; +  transaction_duplicate0=TRUE; +  transaction_duplicate1=TRUE;    transaction_duplicate2=TRUE;    transaction_duplicate3=TRUE;    transaction_duplicate4=TRUE;    transaction_duplicate5=TRUE;    transaction_duplicate6=TRUE;    transaction_duplicate7=TRUE; -  transaction_duplicate8=TRUE; -  out_reserve_found = TRUE; +  out_reserve_found0 = TRUE; +  out_reserve_found1 = TRUE;    out_reserve_found2 = TRUE;    out_reserve_found3 = TRUE;    out_reserve_found4 = TRUE;    out_reserve_found5 = TRUE;    out_reserve_found6 = TRUE;    out_reserve_found7 = TRUE; -  out_reserve_found8 = TRUE; -  ruuid=0; +  ruuid0=0; +  ruuid1=0;    ruuid2=0;    ruuid3=0;    ruuid4=0;    ruuid5=0;    ruuid6=0;    ruuid7=0; -  ruuid8=0; -  k=0; -  --SIMPLE INSERT ON CONFLICT DO NOTHING    INSERT INTO wire_targets      (wire_target_h_payto      ,payto_uri)      VALUES -    (in_wire_source_h_payto -    ,in_payto_uri), +    (in0_wire_source_h_payto +    ,in0_payto_uri), +    (in1_wire_source_h_payto +    ,in1_payto_uri),      (in2_wire_source_h_payto      ,in2_payto_uri),      (in3_wire_source_h_payto @@ -723,12 +733,10 @@ BEGIN      (in6_wire_source_h_payto      ,in6_payto_uri),      (in7_wire_source_h_payto -    ,in7_payto_uri), -    (in8_wire_source_h_payto -    ,in8_payto_uri) +    ,in7_payto_uri)    ON CONFLICT DO NOTHING; -  OPEN curs_reserve_existed FOR +  OPEN curs_reserve_exist FOR    WITH reserve_changes AS (      INSERT INTO reserves        (reserve_pub @@ -737,9 +745,14 @@ BEGIN        ,expiration_date        ,gc_date)        VALUES -      (in_reserve_pub -      ,in_credit_val -      ,in_credit_frac +      (in0_reserve_pub +      ,in0_credit_val +      ,in0_credit_frac +      ,in_reserve_expiration +      ,in_gc_date), +      (in1_reserve_pub +      ,in1_credit_val +      ,in1_credit_frac        ,in_reserve_expiration        ,in_gc_date),        (in2_reserve_pub @@ -771,295 +784,269 @@ BEGIN        ,in7_credit_val        ,in7_credit_frac        ,in_reserve_expiration -      ,in_gc_date), -      (in8_reserve_pub -      ,in8_credit_val -      ,in8_credit_frac -      ,in_reserve_expiration        ,in_gc_date) -     ON CONFLICT DO NOTHING -     RETURNING reserve_uuid,reserve_pub) -    SELECT * FROM reserve_changes; - -  WHILE k < 8 LOOP +    ON CONFLICT DO NOTHING +    RETURNING reserve_uuid,reserve_pub) +  SELECT reserve_uuid, reserve_pub FROM reserve_changes; -    FETCH FROM curs_reserve_existed INTO i; -    IF FOUND +  k=0; +  <<loop_reserve>> LOOP +    FETCH FROM curs_reserve_exist INTO i; +    IF NOT FOUND      THEN -      IF in_reserve_pub = i.reserve_pub -      THEN -         ruuid = i.reserve_uuid; -         IF in_reserve_pub -         NOT IN (in2_reserve_pub -                ,in3_reserve_pub -                ,in4_reserve_pub -                ,in5_reserve_pub -                ,in6_reserve_pub -                ,in7_reserve_pub -                ,in8_reserve_pub) -         THEN -           out_reserve_found = FALSE; -         END IF; -      END IF; -      IF in2_reserve_pub = i.reserve_pub -      THEN -         ruuid2 = i.reserve_uuid; -         IF in2_reserve_pub -         NOT IN (in_reserve_pub -                ,in3_reserve_pub -                ,in4_reserve_pub -                ,in5_reserve_pub -                ,in6_reserve_pub -                ,in7_reserve_pub -                ,in8_reserve_pub) -         THEN -           out_reserve_found2 = FALSE; -         END IF; -      END IF; -      IF in3_reserve_pub = i.reserve_pub -      THEN -         ruuid3 = i.reserve_uuid; -         IF in3_reserve_pub -         NOT IN (in_reserve_pub -                ,in2_reserve_pub -                ,in4_reserve_pub -                ,in5_reserve_pub -                ,in6_reserve_pub -                ,in7_reserve_pub -                ,in8_reserve_pub) -         THEN -           out_reserve_found3 = FALSE; -         END IF; -      END IF; -      IF in4_reserve_pub = i.reserve_pub -      THEN -         ruuid4 = i.reserve_uuid; -         IF in4_reserve_pub -         NOT IN (in_reserve_pub -                ,in2_reserve_pub -                ,in3_reserve_pub -                ,in5_reserve_pub -                ,in6_reserve_pub -                ,in7_reserve_pub -                ,in8_reserve_pub) -         THEN -           out_reserve_found4 = FALSE; -         END IF; -      END IF; -      IF in5_reserve_pub = i.reserve_pub -      THEN -         ruuid5 = i.reserve_uuid; -         IF in5_reserve_pub -         NOT IN (in_reserve_pub -                ,in2_reserve_pub -                ,in3_reserve_pub -                ,in4_reserve_pub -                ,in6_reserve_pub -                ,in7_reserve_pub -                ,in8_reserve_pub) -         THEN -           out_reserve_found5 = FALSE; -         END IF; -      END IF; -      IF in6_reserve_pub = i.reserve_pub -      THEN -         ruuid6 = i.reserve_uuid; -         IF in6_reserve_pub -         NOT IN (in_reserve_pub -                ,in2_reserve_pub -                ,in3_reserve_pub -                ,in4_reserve_pub -                ,in5_reserve_pub -                ,in7_reserve_pub -                ,in8_reserve_pub) -         THEN -           out_reserve_found6 = FALSE; -         END IF; -      END IF; -      IF in7_reserve_pub = i.reserve_pub -      THEN -         ruuid7 = i.reserve_uuid; -         IF in7_reserve_pub -         NOT IN (in_reserve_pub -                ,in2_reserve_pub -                ,in3_reserve_pub -                ,in4_reserve_pub -                ,in5_reserve_pub -                ,in6_reserve_pub -                ,in8_reserve_pub) -         THEN -           out_reserve_found7 = FALSE; -         END IF; -      END IF; -      IF in8_reserve_pub = i.reserve_pub -      THEN -         ruuid8 = i.reserve_uuid; -         IF in8_reserve_pub -         NOT IN (in_reserve_pub -                ,in2_reserve_pub -                ,in3_reserve_pub -                ,in4_reserve_pub -                ,in5_reserve_pub -                ,in6_reserve_pub -                ,in7_reserve_pub) -         THEN -           out_reserve_found8 = FALSE; -         END IF; -      END IF; +      EXIT loop_reserve;      END IF; -  k=k+1; -  END LOOP; -  CLOSE curs_reserve_existed; +    <<loop_k>> LOOP +      CASE k +        WHEN 0 THEN +          k = k + 1; +          IF in0_reserve_pub = i.reserve_pub +          THEN +            ruuid0 = i.reserve_uuid; +            out_reserve_found0 = FALSE; +            CONTINUE loop_reserve; +          END IF; +          CONTINUE loop_k; +        WHEN 1 THEN +          k = k + 1; +          IF in1_reserve_pub = i.reserve_pub +          THEN +            ruuid1 = i.reserve_uuid; +            out_reserve_found1 = FALSE; +            CONTINUE loop_reserve; +          END IF; +          CONTINUE loop_k; +        WHEN 2 THEN +          k = k + 1; +          IF in2_reserve_pub = i.reserve_pub +          THEN +            ruuid2 = i.reserve_uuid; +            out_reserve_found2 = FALSE; +            CONTINUE loop_reserve; +          END IF; +          CONTINUE loop_k; +        WHEN 3 THEN +          k = k + 1; +          IF in3_reserve_pub = i.reserve_pub +          THEN +            ruuid3 = i.reserve_uuid; +            out_reserve_found3 = FALSE; +            CONTINUE loop_reserve; +          END IF; +          CONTINUE loop_k; +        WHEN 4 THEN +          k = k + 1; +          IF in4_reserve_pub = i.reserve_pub +          THEN +            ruuid4 = i.reserve_uuid; +            out_reserve_found4 = FALSE; +            CONTINUE loop_reserve; +          END IF; +          CONTINUE loop_k; +        WHEN 5 THEN +          k = k + 1; +          IF in5_reserve_pub = i.reserve_pub +          THEN +            ruuid5 = i.reserve_uuid; +            out_reserve_found5 = FALSE; +            CONTINUE loop_reserve; +          END IF; +          CONTINUE loop_k; +        WHEN 6 THEN +          k = k + 1; +          IF in6_reserve_pub = i.reserve_pub +          THEN +            ruuid6 = i.reserve_uuid; +            out_reserve_found6 = FALSE; +            CONTINUE loop_reserve; +          END IF; +          CONTINUE loop_k; +        WHEN 7 THEN +          IF in7_reserve_pub = i.reserve_pub +          THEN +            ruuid7 = i.reserve_uuid; +            out_reserve_found7 = FALSE; +            EXIT loop_reserve; +          END IF; +          EXIT loop_k; +      END CASE; +    END LOOP loop_k; +  END LOOP loop_reserve; -  k=0; -  OPEN curs_transaction_existed FOR -  WITH reserve_in_changes AS ( +  CLOSE curs_reserve_exist; + +  OPEN curs_transaction_exist FOR +  WITH reserve_changes AS (      INSERT INTO reserves_in -    (reserve_pub -    ,wire_reference -    ,credit_val -    ,credit_frac -    ,exchange_account_section -    ,wire_source_h_payto -    ,execution_date) +      (reserve_pub +      ,wire_reference +      ,credit_val +      ,credit_frac +      ,exchange_account_section +      ,wire_source_h_payto +      ,execution_date)        VALUES -    (in_reserve_pub -    ,in_wire_ref -    ,in_credit_val -    ,in_credit_frac -    ,in_exchange_account_name -    ,in_wire_source_h_payto -    ,in_execution_date), -    (in2_reserve_pub -    ,in2_wire_ref -    ,in2_credit_val -    ,in2_credit_frac -    ,in2_exchange_account_name -    ,in2_wire_source_h_payto -    ,in2_execution_date), -    (in3_reserve_pub -    ,in3_wire_ref -    ,in3_credit_val -    ,in3_credit_frac -    ,in3_exchange_account_name -    ,in3_wire_source_h_payto -    ,in3_execution_date), -    (in4_reserve_pub -    ,in4_wire_ref -    ,in4_credit_val -    ,in4_credit_frac -    ,in4_exchange_account_name -    ,in4_wire_source_h_payto -    ,in4_execution_date), -    (in5_reserve_pub -    ,in5_wire_ref -    ,in5_credit_val -    ,in5_credit_frac -    ,in5_exchange_account_name -    ,in5_wire_source_h_payto -    ,in5_execution_date), -    (in6_reserve_pub -    ,in6_wire_ref -    ,in6_credit_val -    ,in6_credit_frac -    ,in6_exchange_account_name -    ,in6_wire_source_h_payto -    ,in6_execution_date), -    (in7_reserve_pub -    ,in7_wire_ref -    ,in7_credit_val -    ,in7_credit_frac -    ,in7_exchange_account_name -    ,in7_wire_source_h_payto -    ,in7_execution_date), -    (in8_reserve_pub -    ,in8_wire_ref -    ,in8_credit_val -    ,in8_credit_frac -    ,in8_exchange_account_name -    ,in8_wire_source_h_payto -    ,in8_execution_date) -     ON CONFLICT DO NOTHING -     RETURNING reserve_pub) -    SELECT * FROM reserve_in_changes; +      (in0_reserve_pub +      ,in0_wire_ref +      ,in0_credit_val +      ,in0_credit_frac +      ,in0_exchange_account_name +      ,in0_wire_source_h_payto +      ,in0_execution_date), +      (in1_reserve_pub +      ,in1_wire_ref +      ,in1_credit_val +      ,in1_credit_frac +      ,in1_exchange_account_name +      ,in1_wire_source_h_payto +      ,in1_execution_date), +      (in2_reserve_pub +      ,in2_wire_ref +      ,in2_credit_val +      ,in2_credit_frac +      ,in2_exchange_account_name +      ,in2_wire_source_h_payto +      ,in2_execution_date), +      (in3_reserve_pub +      ,in3_wire_ref +      ,in3_credit_val +      ,in3_credit_frac +      ,in3_exchange_account_name +      ,in3_wire_source_h_payto +      ,in3_execution_date), +      (in4_reserve_pub +      ,in4_wire_ref +      ,in4_credit_val +      ,in4_credit_frac +      ,in4_exchange_account_name +      ,in4_wire_source_h_payto +      ,in4_execution_date), +      (in5_reserve_pub +      ,in5_wire_ref +      ,in5_credit_val +      ,in5_credit_frac +      ,in5_exchange_account_name +      ,in5_wire_source_h_payto +      ,in5_execution_date), +      (in6_reserve_pub +      ,in6_wire_ref +      ,in6_credit_val +      ,in6_credit_frac +      ,in6_exchange_account_name +      ,in6_wire_source_h_payto +      ,in6_execution_date), +      (in7_reserve_pub +      ,in7_wire_ref +      ,in7_credit_val +      ,in7_credit_frac +      ,in7_exchange_account_name +      ,in7_wire_source_h_payto +      ,in7_execution_date) +    ON CONFLICT DO NOTHING +    RETURNING reserve_pub) +  SELECT reserve_pub FROM reserve_changes; -  WHILE k < 8 LOOP -    FETCH FROM curs_transaction_existed INTO r; -    IF FOUND +  k=0; +  <<loop_transaction>> LOOP +    FETCH FROM curs_transaction_exist INTO i; +    IF NOT FOUND      THEN -      IF in_reserve_pub = r.reserve_pub -      THEN -         transaction_duplicate = FALSE; -         EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in_notify); -      END IF; -      IF in2_reserve_pub = r.reserve_pub -      THEN -         transaction_duplicate2 = FALSE; -         EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in2_notify); -      END IF; -      IF in3_reserve_pub = r.reserve_pub -      THEN -         transaction_duplicate3 = FALSE; -         EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in3_notify); -      END IF; -      IF in4_reserve_pub = r.reserve_pub -      THEN -         transaction_duplicate4 = FALSE; -         EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in4_notify); -      END IF; -      IF in5_reserve_pub = r.reserve_pub -      THEN -         transaction_duplicate5 = FALSE; -         EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in5_notify); -      END IF; -      IF in6_reserve_pub = r.reserve_pub -      THEN -         transaction_duplicate6 = FALSE; -         EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in6_notify); -      END IF; -      IF in7_reserve_pub = r.reserve_pub -      THEN -         transaction_duplicate7 = FALSE; -         EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in7_notify); -      END IF; -      IF in8_reserve_pub = r.reserve_pub -      THEN -         transaction_duplicate8 = FALSE; -         EXECUTE FORMAT ( -         'NOTIFY %s' -         ,in8_notify); -      END IF; +      EXIT loop_transaction;      END IF; -  k=k+1; -  END LOOP; - /* IF transaction_duplicate -  OR transaction_duplicate2 -  OR transaction_duplicate3 -  OR transaction_duplicate4 -  OR transaction_duplicate5 -  OR transaction_duplicate6 -  OR transaction_duplicate7 -  OR transaction_duplicate8 -  THEN -    CLOSE curs_transaction_existed; -    ROLLBACK; -    RETURN; -  END IF;*/ -  CLOSE curs_transaction_existed; + +    <<loop2_k>> LOOP +      CASE k +        WHEN 0 THEN +          k = k + 1; +          IF in0_reserve_pub = r.reserve_pub +          THEN +            transaction_duplicate0 = FALSE; +            EXECUTE FORMAT ( +               'NOTIFY %s' +              ,in0_notify); +            CONTINUE loop_transaction; +          END IF; +          CONTINUE loop2_k; +        WHEN 1 THEN +          k = k + 1; +          IF in1_reserve_pub = r.reserve_pub +          THEN +            transaction_duplicate1 = FALSE; +            EXECUTE FORMAT ( +               'NOTIFY %s' +              ,in1_notify); +            CONTINUE loop_transaction; +          END IF; +          CONTINUE loop2_k; +        WHEN 2 THEN +          k = k + 1; +          IF in2_reserve_pub = r.reserve_pub +          THEN +            transaction_duplicate2 = FALSE; +            EXECUTE FORMAT ( +               'NOTIFY %s' +              ,in2_notify); +            CONTINUE loop_transaction; +          END IF; +          CONTINUE loop2_k; +        WHEN 3 THEN +          k = k + 1; +          IF in3_reserve_pub = r.reserve_pub +          THEN +            transaction_duplicate3 = FALSE; +            EXECUTE FORMAT ( +               'NOTIFY %s' +              ,in3_notify); +            CONTINUE loop_transaction; +          END IF; +          CONTINUE loop2_k; +        WHEN 4 THEN +          k = k + 1; +          IF in4_reserve_pub = r.reserve_pub +          THEN +            transaction_duplicate4 = FALSE; +            EXECUTE FORMAT ( +               'NOTIFY %s' +              ,in4_notify); +            CONTINUE loop_transaction; +          END IF; +          CONTINUE loop2_k; +        WHEN 5 THEN +          k = k + 1; +          IF in5_reserve_pub = r.reserve_pub +          THEN +            transaction_duplicate2 = FALSE; +            EXECUTE FORMAT ( +               'NOTIFY %s' +              ,in5_notify); +            CONTINUE loop_transaction; +          END IF; +          CONTINUE loop2_k; +        WHEN 6 THEN +          k = k + 1; +          IF in6_reserve_pub = r.reserve_pub +          THEN +            transaction_duplicate6 = FALSE; +            EXECUTE FORMAT ( +               'NOTIFY %s' +              ,in6_notify); +            CONTINUE loop_transaction; +          END IF; +          CONTINUE loop2_k; +        WHEN 7 THEN +          IF in7_reserve_pub = r.reserve_pub +          THEN +            transaction_duplicate7 = FALSE; +            EXECUTE FORMAT ( +              'NOTIFY %s' +              ,in7_notify); +            EXIT loop_transaction; +          END IF; +      END CASE; +    END LOOP loop2_k; +  END LOOP loop_transaction; + +  CLOSE curs_transaction_exist;    RETURN;  END $$; diff --git a/src/exchangedb/pg_reserves_in_insert.c b/src/exchangedb/pg_reserves_in_insert.c index 876774de..2e29a185 100644 --- a/src/exchangedb/pg_reserves_in_insert.c +++ b/src/exchangedb/pg_reserves_in_insert.c @@ -55,53 +55,107 @@ compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub)  } +/** + * Record we keep per reserve to process. + */ +struct ReserveRecord +{ +  /** +   * Details about reserve to insert (input). +   */ +  const struct TALER_EXCHANGEDB_ReserveInInfo *reserve; + +  /** +   * Hash of the payto URI in @e reserve. +   */ +  struct TALER_PaytoHashP h_payto; + +  /** +   * Notification to trigger on the reserve (input). +   */ +  char *notify_s; + +  /** +   * Set to UUID of the reserve (output); +   */ +  uint64_t reserve_uuid; + +  /** +   * Set to true if the transaction was an exact duplicate (output). +   */ +  bool transaction_duplicate; + +  /** +   * Set to true if the transaction conflicted with an existing reserve (output) +   * and needs to be re-done with an UPDATE. +   */ +  bool conflicts; +}; + + +/** + * Generate the SQL parameters to insert the record @a rr at + * index @a index + */ +#define RR_QUERY_PARAM(rr,index) \ +  GNUNET_PQ_query_param_auto_from_type (rr[index].reserve->reserve_pub),    \ +  GNUNET_PQ_query_param_uint64 (&rr[index].reserve->wire_reference),        \ +  TALER_PQ_query_param_amount (rr[index].reserve->balance),                 \ +  GNUNET_PQ_query_param_string (rr[index].reserve->exchange_account_name),  \ +  GNUNET_PQ_query_param_timestamp (&rr[index].reserve->execution_time),     \ +  GNUNET_PQ_query_param_auto_from_type (&rr[index].h_payto),                \ +  GNUNET_PQ_query_param_string (rr[index].reserve->sender_account_details), \ +  GNUNET_PQ_query_param_string (rr[index].notify_s) + + +/** + * Generate the SQL parameters to obtain results for record @a rr at + * index @a index + */ +#define RR_RESULT_PARAM(rr,index) \ +  GNUNET_PQ_result_spec_bool ("conflicted" TALER_S (index),            \ +                              &rr[index].conflicts),                   \ +  GNUNET_PQ_result_spec_bool ("transaction_duplicate" TALER_S (index), \ +                              &rr[index].transaction_duplicate),       \ +  GNUNET_PQ_result_spec_uint64 ("reserve_uuid" TALER_S (index),        \ +                                &rr[index].reserve_uuid) + + +/** + * Insert 1 reserve record @a rr into the database. + * + * @param pg database context + * @param gc gc timestamp to use + * @param reserve_expiration expiration time to use + * @param[in,out] rr array of reserve details to use and update + * @return database transaction status + */  static enum GNUNET_DB_QueryStatus  insert1 (struct PostgresClosure *pg, -         const struct TALER_EXCHANGEDB_ReserveInInfo reserves[1],           struct GNUNET_TIME_Timestamp gc, -         char *const *notify_s,           struct GNUNET_TIME_Timestamp reserve_expiration, -         bool *transaction_duplicate, -         bool *conflict, -         uint64_t *reserve_uuid) +         struct ReserveRecord *rr)  {    enum GNUNET_DB_QueryStatus qs; -  struct TALER_PaytoHashP h_payto0;    struct GNUNET_PQ_QueryParam params[] = {      GNUNET_PQ_query_param_timestamp (&gc),      GNUNET_PQ_query_param_timestamp (&reserve_expiration), - -    GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), -    GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), -    TALER_PQ_query_param_amount (reserves[0].balance), -    GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), -    GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), -    GNUNET_PQ_query_param_auto_from_type (&h_payto0), -    GNUNET_PQ_query_param_string (reserves[0].sender_account_details), - -    GNUNET_PQ_query_param_string (notify_s[0]), +    RR_QUERY_PARAM (rr, 0),      GNUNET_PQ_query_param_end    };    struct GNUNET_PQ_ResultSpec rs[] = { -    GNUNET_PQ_result_spec_bool ("conflicted", -                                &conflict[0]), -    GNUNET_PQ_result_spec_bool ("transaction_duplicate", -                                &transaction_duplicate[0]), -    GNUNET_PQ_result_spec_uint64 ("reserve_uuid", -                                  &reserve_uuid[0]), +    RR_RESULT_PARAM (rr, 0),      GNUNET_PQ_result_spec_end    };    PREPARE (pg,             "batch1_reserve_create",             "SELECT " -           " out_reserve_found AS conflicted" -           ",transaction_duplicate" -           ",ruuid AS reserve_uuid" +           " out_reserve_found0 AS conflicted0" +           ",transaction_duplicate0 AS transaction_duplicate0" +           ",ruuid0 AS reserve_uuid0"             " FROM exchange_do_batch_reserves_in_insert"             " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);"); -  TALER_payto_hash (reserves[0].sender_account_details, -                    &h_payto0);    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,                                                   "batch1_reserve_create",                                                   params, @@ -114,7 +168,7 @@ insert1 (struct PostgresClosure *pg,      return qs;    }    GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs); -  if ((! conflict[0]) && transaction_duplicate[0]) +  if ((! rr[0].conflicts) && rr[0].transaction_duplicate)    {      GNUNET_break (0);      TEH_PG_rollback (pg); @@ -124,463 +178,257 @@ insert1 (struct PostgresClosure *pg,  } +/** + * Insert 2 reserve records @a rr into the database. + * + * @param pg database context + * @param gc gc timestamp to use + * @param reserve_expiration expiration time to use + * @param[in,out] rr array of reserve details to use and update + * @return database transaction status + */  static enum GNUNET_DB_QueryStatus  insert2 (struct PostgresClosure *pg, -         const struct TALER_EXCHANGEDB_ReserveInInfo reserves[2],           struct GNUNET_TIME_Timestamp gc, -         char *const*notify_s,           struct GNUNET_TIME_Timestamp reserve_expiration, -         bool *transaction_duplicate, -         bool *conflict, -         uint64_t *reserve_uuid) +         struct ReserveRecord *rr)  { -  enum GNUNET_DB_QueryStatus qs1; -  struct TALER_PaytoHashP h_payto[2]; +  enum GNUNET_DB_QueryStatus qs;    struct GNUNET_PQ_QueryParam params[] = {      GNUNET_PQ_query_param_timestamp (&gc),      GNUNET_PQ_query_param_timestamp (&reserve_expiration), - -    GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), -    GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), -    TALER_PQ_query_param_amount (reserves[0].balance), -    GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), -    GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), -    GNUNET_PQ_query_param_auto_from_type (&h_payto[0]), -    GNUNET_PQ_query_param_string (reserves[0].sender_account_details), - -    GNUNET_PQ_query_param_string (notify_s[0]), -    GNUNET_PQ_query_param_string (notify_s[1]), - -    GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub), -    GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference), -    TALER_PQ_query_param_amount (reserves[1].balance), -    GNUNET_PQ_query_param_string (reserves[1].exchange_account_name), -    GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time), -    GNUNET_PQ_query_param_auto_from_type (&h_payto[1]), -    GNUNET_PQ_query_param_string (reserves[1].sender_account_details), +    RR_QUERY_PARAM (rr, 0), +    RR_QUERY_PARAM (rr, 1),      GNUNET_PQ_query_param_end    };    struct GNUNET_PQ_ResultSpec rs[] = { -    GNUNET_PQ_result_spec_bool ("conflicted", -                                &conflict[0]), -    GNUNET_PQ_result_spec_bool ("conflicted2", -                                &conflict[1]), -    GNUNET_PQ_result_spec_bool ("transaction_duplicate", -                                &transaction_duplicate[0]), -    GNUNET_PQ_result_spec_bool ("transaction_duplicate2", -                                &transaction_duplicate[1]), -    GNUNET_PQ_result_spec_uint64 ("reserve_uuid", -                                  &reserve_uuid[0]), -    GNUNET_PQ_result_spec_uint64 ("reserve_uuid2", -                                  &reserve_uuid[1]), +    RR_RESULT_PARAM (rr, 0), +    RR_RESULT_PARAM (rr, 1),      GNUNET_PQ_result_spec_end    };    PREPARE (pg,             "batch2_reserve_create", -           "SELECT " -           "out_reserve_found AS conflicted" -           ",out_reserve_found2 AS conflicted2" -           ",transaction_duplicate" -           ",transaction_duplicate2" -           ",ruuid AS reserve_uuid" -           ",ruuid2 AS reserve_uuid2" +           "SELECT" +           " out_reserve_found0 AS conflicted0" +           ",out_reserve_found1 AS conflicted1" +           ",transaction_duplicate0" +           ",transaction_duplicate1" +           ",ruuid0 AS reserve_uuid0" +           ",ruuid1 AS reserve_uuid1"             " FROM exchange_do_batch2_reserves_insert"             " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20);"); -  TALER_payto_hash (reserves[0].sender_account_details, -                    &h_payto[0]); -  TALER_payto_hash (reserves[1].sender_account_details, -                    &h_payto[1]); -  qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, -                                                  "batch2_reserve_create", -                                                  params, -                                                  rs); -  if (qs1 < 0) +  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, +                                                 "batch2_reserve_create", +                                                 params, +                                                 rs); +  if (qs < 0)    {      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,                  "Failed to create reserves 2(%d)\n", -                qs1); -    return qs1; +                qs); +    return qs;    } - -  GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1); -  if ( ((! conflict[0]) && (transaction_duplicate[0])) || -       ((! conflict[1]) && (transaction_duplicate[1])) ) +  GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs); +  for (unsigned int i = 0; i<2; i++)    { -    GNUNET_break (0); -    TEH_PG_rollback (pg); -    return GNUNET_DB_STATUS_HARD_ERROR; +    if ((! rr[i].conflicts) && (rr[i].transaction_duplicate)) +    { +      GNUNET_break (0); +      TEH_PG_rollback (pg); +      return GNUNET_DB_STATUS_HARD_ERROR; +    }    } -  return qs1; +  return qs;  } +/** + * Insert 4 reserve records @a rr into the database. + * + * @param pg database context + * @param gc gc timestamp to use + * @param reserve_expiration expiration time to use + * @param[in,out] rr array of reserve details to use and update + * @return database transaction status + */  static enum GNUNET_DB_QueryStatus  insert4 (struct PostgresClosure *pg, -         const struct TALER_EXCHANGEDB_ReserveInInfo reserves[4],           struct GNUNET_TIME_Timestamp gc, -         char *const*notify_s,           struct GNUNET_TIME_Timestamp reserve_expiration, -         bool *transaction_duplicate, -         bool *conflict, -         uint64_t *reserve_uuid) +         struct ReserveRecord *rr)  { -  enum GNUNET_DB_QueryStatus qs3; -  struct TALER_PaytoHashP h_payto[4]; +  enum GNUNET_DB_QueryStatus qs;    struct GNUNET_PQ_QueryParam params[] = {      GNUNET_PQ_query_param_timestamp (&gc),      GNUNET_PQ_query_param_timestamp (&reserve_expiration), - -    GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), -    GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), -    TALER_PQ_query_param_amount (reserves[0].balance), -    GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), -    GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), -    GNUNET_PQ_query_param_auto_from_type (&h_payto[0]), -    GNUNET_PQ_query_param_string (reserves[0].sender_account_details), - -    GNUNET_PQ_query_param_string (notify_s[0]), -    GNUNET_PQ_query_param_string (notify_s[1]), -    GNUNET_PQ_query_param_string (notify_s[2]), -    GNUNET_PQ_query_param_string (notify_s[3]), - -    GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub), -    GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference), -    TALER_PQ_query_param_amount (reserves[1].balance), -    GNUNET_PQ_query_param_string (reserves[1].exchange_account_name), -    GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time), -    GNUNET_PQ_query_param_auto_from_type (&h_payto[1]), -    GNUNET_PQ_query_param_string (reserves[1].sender_account_details), - -    GNUNET_PQ_query_param_auto_from_type (reserves[2].reserve_pub), -    GNUNET_PQ_query_param_uint64 (&reserves[2].wire_reference), -    TALER_PQ_query_param_amount (reserves[2].balance), -    GNUNET_PQ_query_param_string (reserves[2].exchange_account_name), -    GNUNET_PQ_query_param_timestamp (&reserves[2].execution_time), -    GNUNET_PQ_query_param_auto_from_type (&h_payto[2]), -    GNUNET_PQ_query_param_string (reserves[2].sender_account_details), - -    GNUNET_PQ_query_param_auto_from_type (reserves[3].reserve_pub), -    GNUNET_PQ_query_param_uint64 (&reserves[3].wire_reference), -    TALER_PQ_query_param_amount (reserves[3].balance), -    GNUNET_PQ_query_param_string (reserves[3].exchange_account_name), -    GNUNET_PQ_query_param_timestamp (&reserves[3].execution_time), -    GNUNET_PQ_query_param_auto_from_type (&h_payto[3]), -    GNUNET_PQ_query_param_string (reserves[3].sender_account_details), - +    RR_QUERY_PARAM (rr, 0), +    RR_QUERY_PARAM (rr, 1), +    RR_QUERY_PARAM (rr, 2), +    RR_QUERY_PARAM (rr, 3),      GNUNET_PQ_query_param_end    }; -    struct GNUNET_PQ_ResultSpec rs[] = { -    GNUNET_PQ_result_spec_bool ("conflicted", -                                &conflict[0]), -    GNUNET_PQ_result_spec_bool ("conflicted2", -                                &conflict[1]), -    GNUNET_PQ_result_spec_bool ("conflicted3", -                                &conflict[2]), -    GNUNET_PQ_result_spec_bool ("conflicted4", -                                &conflict[3]), -    GNUNET_PQ_result_spec_bool ("transaction_duplicate", -                                &transaction_duplicate[0]), -    GNUNET_PQ_result_spec_bool ("transaction_duplicate2", -                                &transaction_duplicate[1]), -    GNUNET_PQ_result_spec_bool ("transaction_duplicate3", -                                &transaction_duplicate[2]), -    GNUNET_PQ_result_spec_bool ("transaction_duplicate4", -                                &transaction_duplicate[3]), -    GNUNET_PQ_result_spec_uint64 ("reserve_uuid", -                                  &reserve_uuid[0]), -    GNUNET_PQ_result_spec_uint64 ("reserve_uuid2", -                                  &reserve_uuid[1]), -    GNUNET_PQ_result_spec_uint64 ("reserve_uuid3", -                                  &reserve_uuid[2]), -    GNUNET_PQ_result_spec_uint64 ("reserve_uuid4", -                                  &reserve_uuid[3]), +    RR_RESULT_PARAM (rr, 0), +    RR_RESULT_PARAM (rr, 1), +    RR_RESULT_PARAM (rr, 2), +    RR_RESULT_PARAM (rr, 3),      GNUNET_PQ_result_spec_end    };    PREPARE (pg,             "batch4_reserve_create", -           "SELECT " -           "out_reserve_found AS conflicted" +           "SELECT" +           " out_reserve_found0 AS conflicted0" +           ",out_reserve_found1 AS conflicted1"             ",out_reserve_found2 AS conflicted2"             ",out_reserve_found3 AS conflicted3" -           ",out_reserve_found4 AS conflicted4" -           ",transaction_duplicate" +           ",transaction_duplicate0" +           ",transaction_duplicate1"             ",transaction_duplicate2"             ",transaction_duplicate3" -           ",transaction_duplicate4" -           ",ruuid AS reserve_uuid" +           ",ruuid0 AS reserve_uuid0" +           ",ruuid1 AS reserve_uuid1"             ",ruuid2 AS reserve_uuid2"             ",ruuid3 AS reserve_uuid3" -           ",ruuid4 AS reserve_uuid4"             " FROM exchange_do_batch4_reserves_insert"             " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38);"); - -  for (unsigned int i = 0; i<4; i++) -    TALER_payto_hash (reserves[i].sender_account_details, -                      &h_payto[i]); -  qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, -                                                  "batch4_reserve_create", -                                                  params, -                                                  rs); -  if (qs3 < 0) +  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, +                                                 "batch4_reserve_create", +                                                 params, +                                                 rs); +  if (qs < 0)    {      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,                  "Failed to create reserves4 (%d)\n", -                qs3); -    return qs3; +                qs); +    return qs;    } -  GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs3); - -  if ( -    ((! conflict[0]) && (transaction_duplicate[0])) -    || ((! conflict[1]) && (transaction_duplicate[1])) -    || ((! conflict[2]) && (transaction_duplicate[2])) -    || ((! conflict[3]) && (transaction_duplicate[3])) -    ) +  GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs); +  for (unsigned int i = 0; i<4; i++)    { -    GNUNET_break (0); -    TEH_PG_rollback (pg); -    return GNUNET_DB_STATUS_HARD_ERROR; +    if ((! rr[i].conflicts) && (rr[i].transaction_duplicate)) +    { +      GNUNET_break (0); +      TEH_PG_rollback (pg); +      return GNUNET_DB_STATUS_HARD_ERROR; +    }    } -  return qs3; +  return qs;  } +/** + * Insert 8 reserve records @a rr into the database. + * + * @param pg database context + * @param gc gc timestamp to use + * @param reserve_expiration expiration time to use + * @param[in,out] rr array of reserve details to use and update + * @return database transaction status + */  static enum GNUNET_DB_QueryStatus  insert8 (struct PostgresClosure *pg, -         const struct TALER_EXCHANGEDB_ReserveInInfo reserves[8],           struct GNUNET_TIME_Timestamp gc, -         char *const*notify_s,           struct GNUNET_TIME_Timestamp reserve_expiration, -         bool *transaction_duplicate, -         bool *conflict, -         uint64_t *reserve_uuid) +         struct ReserveRecord *rr)  { -  enum GNUNET_DB_QueryStatus qs3; -  struct TALER_PaytoHashP h_payto[8]; +  enum GNUNET_DB_QueryStatus qs;    struct GNUNET_PQ_QueryParam params[] = {      GNUNET_PQ_query_param_timestamp (&gc),      GNUNET_PQ_query_param_timestamp (&reserve_expiration), - -    GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub), -    GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference), -    TALER_PQ_query_param_amount (reserves[0].balance), -    GNUNET_PQ_query_param_string (reserves[0].exchange_account_name), -    GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time), -    GNUNET_PQ_query_param_auto_from_type (&h_payto[0]), -    GNUNET_PQ_query_param_string (reserves[0].sender_account_details), - -    GNUNET_PQ_query_param_string (notify_s[0]), -    GNUNET_PQ_query_param_string (notify_s[1]), -    GNUNET_PQ_query_param_string (notify_s[2]), -    GNUNET_PQ_query_param_string (notify_s[3]), -    GNUNET_PQ_query_param_string (notify_s[4]), -    GNUNET_PQ_query_param_string (notify_s[5]), -    GNUNET_PQ_query_param_string (notify_s[6]), -    GNUNET_PQ_query_param_string (notify_s[7]), - -    GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub), -    GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference), -    TALER_PQ_query_param_amount (reserves[1].balance), -    GNUNET_PQ_query_param_string (reserves[1].exchange_account_name), -    GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time), -    GNUNET_PQ_query_param_auto_from_type (&h_payto[1]), -    GNUNET_PQ_query_param_string (reserves[1].sender_account_details), - -    GNUNET_PQ_query_param_auto_from_type (reserves[2].reserve_pub), -    GNUNET_PQ_query_param_uint64 (&reserves[2].wire_reference), -    TALER_PQ_query_param_amount (reserves[2].balance), -    GNUNET_PQ_query_param_string (reserves[2].exchange_account_name), -    GNUNET_PQ_query_param_timestamp (&reserves[2].execution_time), -    GNUNET_PQ_query_param_auto_from_type (&h_payto[2]), -    GNUNET_PQ_query_param_string (reserves[2].sender_account_details), - -    GNUNET_PQ_query_param_auto_from_type (reserves[3].reserve_pub), -    GNUNET_PQ_query_param_uint64 (&reserves[3].wire_reference), -    TALER_PQ_query_param_amount (reserves[3].balance), -    GNUNET_PQ_query_param_string (reserves[3].exchange_account_name), -    GNUNET_PQ_query_param_timestamp (&reserves[3].execution_time), -    GNUNET_PQ_query_param_auto_from_type (&h_payto[3]), -    GNUNET_PQ_query_param_string (reserves[3].sender_account_details), - -    GNUNET_PQ_query_param_auto_from_type (reserves[4].reserve_pub), -    GNUNET_PQ_query_param_uint64 (&reserves[4].wire_reference), -    TALER_PQ_query_param_amount (reserves[4].balance), -    GNUNET_PQ_query_param_string (reserves[4].exchange_account_name), -    GNUNET_PQ_query_param_timestamp (&reserves[4].execution_time), -    GNUNET_PQ_query_param_auto_from_type (&h_payto[4]), -    GNUNET_PQ_query_param_string (reserves[4].sender_account_details), -    GNUNET_PQ_query_param_timestamp (&reserve_expiration), - -    GNUNET_PQ_query_param_auto_from_type (reserves[5].reserve_pub), -    GNUNET_PQ_query_param_uint64 (&reserves[5].wire_reference), -    TALER_PQ_query_param_amount (reserves[5].balance), -    GNUNET_PQ_query_param_string (reserves[5].exchange_account_name), -    GNUNET_PQ_query_param_timestamp (&reserves[5].execution_time), -    GNUNET_PQ_query_param_auto_from_type (&h_payto[5]), -    GNUNET_PQ_query_param_string (reserves[5].sender_account_details), - -    GNUNET_PQ_query_param_auto_from_type (reserves[6].reserve_pub), -    GNUNET_PQ_query_param_uint64 (&reserves[6].wire_reference), -    TALER_PQ_query_param_amount (reserves[6].balance), -    GNUNET_PQ_query_param_string (reserves[6].exchange_account_name), -    GNUNET_PQ_query_param_timestamp (&reserves[6].execution_time), -    GNUNET_PQ_query_param_auto_from_type (&h_payto[6]), -    GNUNET_PQ_query_param_string (reserves[6].sender_account_details), - -    GNUNET_PQ_query_param_auto_from_type (reserves[7].reserve_pub), -    GNUNET_PQ_query_param_uint64 (&reserves[7].wire_reference), -    TALER_PQ_query_param_amount (reserves[7].balance), -    GNUNET_PQ_query_param_string (reserves[7].exchange_account_name), -    GNUNET_PQ_query_param_timestamp (&reserves[7].execution_time), -    GNUNET_PQ_query_param_auto_from_type (&h_payto[7]), -    GNUNET_PQ_query_param_string (reserves[7].sender_account_details), - +    RR_QUERY_PARAM (rr, 0), +    RR_QUERY_PARAM (rr, 1), +    RR_QUERY_PARAM (rr, 2), +    RR_QUERY_PARAM (rr, 3), +    RR_QUERY_PARAM (rr, 4), +    RR_QUERY_PARAM (rr, 5), +    RR_QUERY_PARAM (rr, 6), +    RR_QUERY_PARAM (rr, 7),      GNUNET_PQ_query_param_end    }; -    struct GNUNET_PQ_ResultSpec rs[] = { -    GNUNET_PQ_result_spec_bool ("conflicted", -                                &conflict[0]), -    GNUNET_PQ_result_spec_bool ("conflicted2", -                                &conflict[1]), -    GNUNET_PQ_result_spec_bool ("conflicted3", -                                &conflict[2]), -    GNUNET_PQ_result_spec_bool ("conflicted4", -                                &conflict[3]), -    GNUNET_PQ_result_spec_bool ("conflicted5", -                                &conflict[4]), -    GNUNET_PQ_result_spec_bool ("conflicted6", -                                &conflict[5]), -    GNUNET_PQ_result_spec_bool ("conflicted7", -                                &conflict[6]), -    GNUNET_PQ_result_spec_bool ("conflicted8", -                                &conflict[7]), -    GNUNET_PQ_result_spec_bool ("transaction_duplicate", -                                &transaction_duplicate[0]), -    GNUNET_PQ_result_spec_bool ("transaction_duplicate2", -                                &transaction_duplicate[1]), -    GNUNET_PQ_result_spec_bool ("transaction_duplicate3", -                                &transaction_duplicate[2]), -    GNUNET_PQ_result_spec_bool ("transaction_duplicate4", -                                &transaction_duplicate[3]), -    GNUNET_PQ_result_spec_bool ("transaction_duplicate5", -                                &transaction_duplicate[4]), -    GNUNET_PQ_result_spec_bool ("transaction_duplicate6", -                                &transaction_duplicate[5]), -    GNUNET_PQ_result_spec_bool ("transaction_duplicate7", -                                &transaction_duplicate[6]), -    GNUNET_PQ_result_spec_bool ("transaction_duplicate8", -                                &transaction_duplicate[7]), -    GNUNET_PQ_result_spec_uint64 ("reserve_uuid", -                                  &reserve_uuid[0]), -    GNUNET_PQ_result_spec_uint64 ("reserve_uuid2", -                                  &reserve_uuid[1]), -    GNUNET_PQ_result_spec_uint64 ("reserve_uuid3", -                                  &reserve_uuid[2]), -    GNUNET_PQ_result_spec_uint64 ("reserve_uuid4", -                                  &reserve_uuid[3]), -    GNUNET_PQ_result_spec_uint64 ("reserve_uuid5", -                                  &reserve_uuid[4]), -    GNUNET_PQ_result_spec_uint64 ("reserve_uuid6", -                                  &reserve_uuid[5]), -    GNUNET_PQ_result_spec_uint64 ("reserve_uuid7", -                                  &reserve_uuid[6]), -    GNUNET_PQ_result_spec_uint64 ("reserve_uuid8", -                                  &reserve_uuid[7]), +    RR_RESULT_PARAM (rr, 0), +    RR_RESULT_PARAM (rr, 1), +    RR_RESULT_PARAM (rr, 2), +    RR_RESULT_PARAM (rr, 3), +    RR_RESULT_PARAM (rr, 4), +    RR_RESULT_PARAM (rr, 5), +    RR_RESULT_PARAM (rr, 6), +    RR_RESULT_PARAM (rr, 7),      GNUNET_PQ_result_spec_end    };    PREPARE (pg,             "batch8_reserve_create",             "SELECT" -           " out_reserve_found AS conflicted" +           " out_reserve_found0 AS conflicted0" +           ",out_reserve_found1 AS conflicted1"             ",out_reserve_found2 AS conflicted2"             ",out_reserve_found3 AS conflicted3"             ",out_reserve_found4 AS conflicted4"             ",out_reserve_found5 AS conflicted5"             ",out_reserve_found6 AS conflicted6"             ",out_reserve_found7 AS conflicted7" -           ",out_reserve_found8 AS conflicted8" -           ",transaction_duplicate" +           ",transaction_duplicate0" +           ",transaction_duplicate1"             ",transaction_duplicate2"             ",transaction_duplicate3"             ",transaction_duplicate4"             ",transaction_duplicate5"             ",transaction_duplicate6"             ",transaction_duplicate7" -           ",transaction_duplicate8" -           ",ruuid AS reserve_uuid" +           ",ruuid0 AS reserve_uuid0" +           ",ruuid1 AS reserve_uuid1"             ",ruuid2 AS reserve_uuid2"             ",ruuid3 AS reserve_uuid3"             ",ruuid4 AS reserve_uuid4"             ",ruuid5 AS reserve_uuid5"             ",ruuid6 AS reserve_uuid6"             ",ruuid7 AS reserve_uuid7" -           ",ruuid8 AS reserve_uuid8"             " FROM exchange_do_batch8_reserves_insert"             " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39, $40, $41,$42,$43,$44,$45,$46,$47,$48,$49,$50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$70,$71,$72,$73,$74);"); -  for (unsigned int i = 0; i<8; i++) -    TALER_payto_hash (reserves[i].sender_account_details, -                      &h_payto[i]); -  qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, -                                                  "batch8_reserve_create", -                                                  params, -                                                  rs); -  if (qs3 < 0) +  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, +                                                 "batch8_reserve_create", +                                                 params, +                                                 rs); +  if (qs < 0)    {      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,                  "Failed to create reserves8 (%d)\n", -                qs3); -    return qs3; +                qs); +    return qs;    } -  GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs3); -  if ( -    ((! conflict[0]) && (transaction_duplicate[0])) -    || ((! conflict[1]) && (transaction_duplicate[1])) -    || ((! conflict[2]) && (transaction_duplicate[2])) -    || ((! conflict[3]) && (transaction_duplicate[3])) -    || ((! conflict[4]) && (transaction_duplicate[4])) -    || ((! conflict[5]) && (transaction_duplicate[5])) -    || ((! conflict[6]) && (transaction_duplicate[6])) -    || ((! conflict[7]) && (transaction_duplicate[7])) -    ) +  GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs); +  for (unsigned int i = 0; i<8; i++)    { -    GNUNET_break (0); -    TEH_PG_rollback (pg); -    return GNUNET_DB_STATUS_HARD_ERROR; +    if ((! rr[i].conflicts) && (rr[i].transaction_duplicate)) +    { +      GNUNET_break (0); +      TEH_PG_rollback (pg); +      return GNUNET_DB_STATUS_HARD_ERROR; +    }    } -  return qs3; +  return qs;  } -enum GNUNET_DB_QueryStatus -TEH_PG_reserves_in_insert ( -  void *cls, -  const struct TALER_EXCHANGEDB_ReserveInInfo *reserves, +static enum GNUNET_DB_QueryStatus +transact ( +  struct PostgresClosure *pg, +  struct ReserveRecord *rr,    unsigned int reserves_length,    unsigned int batch_size,    enum GNUNET_DB_QueryStatus *results)  { -  struct PostgresClosure *pg = cls; -  enum GNUNET_DB_QueryStatus qs1; -  enum GNUNET_DB_QueryStatus qs2; -  enum GNUNET_DB_QueryStatus qs4; -  enum GNUNET_DB_QueryStatus qs5; -  uint64_t reserve_uuid[reserves_length]; -  bool transaction_duplicate[reserves_length]; -  bool need_update = false;    struct GNUNET_TIME_Timestamp reserve_expiration      = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);    struct GNUNET_TIME_Timestamp gc      = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time); -  bool conflicts[reserves_length]; -  char *notify_s[reserves_length]; +  bool need_update = false;    if (GNUNET_OK !=        TEH_PG_preflight (pg)) @@ -589,13 +437,6 @@ TEH_PG_reserves_in_insert (      return GNUNET_DB_STATUS_HARD_ERROR;    } -  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, -              "Creating reserve %s with expiration in %s\n", -              TALER_B2S (&(reserves->reserve_pub)), -              GNUNET_STRINGS_relative_time_to_string ( -                pg->idle_reserve_expiration_time, -                GNUNET_NO)); -    if (GNUNET_OK !=        TEH_PG_start_read_committed (pg,                                     "READ_COMMITED")) @@ -604,144 +445,74 @@ TEH_PG_reserves_in_insert (      return GNUNET_DB_STATUS_HARD_ERROR;    } -  /* Optimistically assume this is a new reserve, create balance for the first -     time; we do this before adding the actual transaction to "reserves_in", -     as for a new reserve it can't be a duplicate 'add' operation, and as -     the 'add' operation needs the reserve entry as a foreign key. */ -  for (unsigned int i = 0; i<reserves_length; i++)    { -    const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i]; +    unsigned int i = 0; -    notify_s[i] = compute_notify_on_reserve (reserve->reserve_pub); -  } - -  unsigned int i = 0; - -  while (i < reserves_length) -  { -    unsigned int bs = GNUNET_MIN (batch_size, -                                  reserves_length - i); -    if (bs >= 8) +    while (i < reserves_length)      { -      qs1 = insert8 (pg, -                     &reserves[i], -                     gc, -                     ¬ify_s[i], -                     reserve_expiration, -                     &transaction_duplicate[i], -                     &conflicts[i], -                     &reserve_uuid[i]); - -      if (qs1<0) +      enum GNUNET_DB_QueryStatus qs; +      enum GNUNET_DB_QueryStatus +      (*fun)(struct PostgresClosure *pg, +             struct GNUNET_TIME_Timestamp gc, +             struct GNUNET_TIME_Timestamp reserve_expiration, +             struct ReserveRecord *rr); +      unsigned int lim; +      unsigned int bs; + +      bs = GNUNET_MIN (batch_size, +                       reserves_length - i); +      switch (bs)        { -        GNUNET_log (GNUNET_ERROR_TYPE_WARNING, -                    "Failed to create reserve batch_8 (%d)\n", -                    qs1); -        results[i] = qs1; -        return qs1; +      case 7: +      case 6: +      case 5: +      case 4: +        fun = &insert4; +        lim = 4; +        break; +      case 3: +      case 2: +        fun = &insert2; +        lim = 2; +        break; +      case 1: +        fun = &insert1; +        lim = 1; +        break; +      case 0: +        GNUNET_assert (0); +        break; +      default: +        fun = insert8; +        lim = 8; +        break;        } -      need_update |= conflicts[i]; -      need_update |= conflicts[i + 1]; -      need_update |= conflicts[i + 2]; -      need_update |= conflicts[i + 3]; -      need_update |= conflicts[i + 4]; -      need_update |= conflicts[i + 5]; -      need_update |= conflicts[i + 6]; -      need_update |= conflicts[i + 7]; -      for (unsigned int j = 0; j<8; j++) -        results[i + j] = transaction_duplicate[i + j] -          ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS -          : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; -      i += 8; -      continue; -    } -    switch (bs) -    { -    case 7: -    case 6: -    case 5: -    case 4: -      qs4 = insert4 (pg, -                     &reserves[i], -                     gc, -                     ¬ify_s[i], -                     reserve_expiration, -                     &transaction_duplicate[i], -                     &conflicts[i], -                     &reserve_uuid[i]); -      if (qs4<0) + +      qs = fun (pg, +                gc, +                reserve_expiration, +                &rr[i]); +      if (qs < 0)        {          GNUNET_log (GNUNET_ERROR_TYPE_WARNING, -                    "Failed to create reserve batch_4 (%d)\n", -                    qs4); -        results[i] = qs4; -        return qs4; +                    "Failed to create reserve batch_%u (%d)\n", +                    lim, +                    qs); +        results[i] = qs; +        return qs;        } -      need_update |= conflicts[i]; -      need_update |= conflicts[i + 1]; -      need_update |= conflicts[i + 2]; -      need_update |= conflicts[i + 3]; -      for (unsigned int j = 0; j<4; j++) -        results[i + j] = transaction_duplicate[i + j] -          ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS -          : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; -      i += 4; -      break; -    case 3: -    case 2: -      qs5 = insert2 (pg, -                     &reserves[i], -                     gc, -                     ¬ify_s[i], -                     reserve_expiration, -                     &transaction_duplicate[i], -                     &conflicts[i], -                     &reserve_uuid[i]); -      if (qs5<0) +      for (unsigned int j = 0; j<lim; j++)        { -        GNUNET_log (GNUNET_ERROR_TYPE_WARNING, -                    "Failed to create reserve batch_2 (%d)\n", -                    qs5); -        results[i] = qs5; -        return qs5; -      } -      need_update |= conflicts[i]; -      need_update |= conflicts[i + 1]; -      for (unsigned int j = 0; j<2; j++) -        results[i + j] = transaction_duplicate[i + j] +        need_update |= rr[i + j].conflicts; +        results[i + j] = rr[i + j].transaction_duplicate            ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS            : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; -      i += 2; -      break; -    case 1: -      qs2 = insert1 (pg, -                     &reserves[i], -                     gc, -                     ¬ify_s[i], -                     reserve_expiration, -                     &transaction_duplicate[i], -                     &conflicts[i], -                     &reserve_uuid[i]); -      if (qs2<0) -      { -        GNUNET_log (GNUNET_ERROR_TYPE_WARNING, -                    "Failed to create reserve batch_1 (%d)\n)", -                    qs2); -        results[i] = qs2; -        return qs2;        } -      need_update |= conflicts[i]; -      results[i] = (transaction_duplicate[i]) -        ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS -        : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; -      i += 1; -      break; -    case 0: -      GNUNET_assert (0); -      break; -    } -  } /* end while */ -  // commit +      i += lim; +      continue; +    } /* end while */ +  } /* end scope i */ +    {      enum GNUNET_DB_QueryStatus cs; @@ -753,19 +524,16 @@ TEH_PG_reserves_in_insert (        return cs;      }    } +    if (! need_update) +    return reserves_length; + +  if (GNUNET_OK != +      TEH_PG_start (pg, +                    "reserve-insert-continued"))    { -    goto exit; -  } -  // begin serializable -  { -    if (GNUNET_OK != -        TEH_PG_start (pg, -                      "reserve-insert-continued")) -    { -      GNUNET_break (0); -      return GNUNET_DB_STATUS_HARD_ERROR; -    } +    GNUNET_break (0); +    return GNUNET_DB_STATUS_HARD_ERROR;    }    PREPARE (pg, @@ -776,19 +544,18 @@ TEH_PG_reserves_in_insert (             " ($1,$2,$3,$4,$5,$6,$7,$8);");    for (unsigned int i = 0; i<reserves_length; i++)    { -    if (! conflicts[i]) +    if (! rr[i].conflicts)        continue;      {        bool duplicate; -      struct TALER_PaytoHashP h_payto;        struct GNUNET_PQ_QueryParam params[] = { -        GNUNET_PQ_query_param_auto_from_type (reserves[i].reserve_pub), +        GNUNET_PQ_query_param_auto_from_type (rr[i].reserve->reserve_pub),          GNUNET_PQ_query_param_timestamp (&reserve_expiration), -        GNUNET_PQ_query_param_uint64 (&reserves[i].wire_reference), -        TALER_PQ_query_param_amount (reserves[i].balance), -        GNUNET_PQ_query_param_string (reserves[i].exchange_account_name), -        GNUNET_PQ_query_param_auto_from_type (&h_payto), -        GNUNET_PQ_query_param_string (notify_s[i]), +        GNUNET_PQ_query_param_uint64 (&rr[i].reserve->wire_reference), +        TALER_PQ_query_param_amount (rr[i].reserve->balance), +        GNUNET_PQ_query_param_string (rr[i].reserve->exchange_account_name), +        GNUNET_PQ_query_param_auto_from_type (&rr[i].h_payto), +        GNUNET_PQ_query_param_string (rr[i].notify_s),          GNUNET_PQ_query_param_end        };        struct GNUNET_PQ_ResultSpec rs[] = { @@ -796,21 +563,19 @@ TEH_PG_reserves_in_insert (                                      &duplicate),          GNUNET_PQ_result_spec_end        }; -      enum GNUNET_DB_QueryStatus qs3; - -      TALER_payto_hash (reserves[i].sender_account_details, -                        &h_payto); -      qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, -                                                      "reserves_update", -                                                      params, -                                                      rs); -      if (qs3<0) +      enum GNUNET_DB_QueryStatus qs; + +      qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, +                                                     "reserves_update", +                                                     params, +                                                     rs); +      if (qs < 0)        {          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,                      "Failed to update reserves (%d)\n", -                    qs3); -        results[i] = qs3; -        return qs3; +                    qs); +        results[i] = qs; +        return qs;        }        results[i] = duplicate            ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS @@ -819,20 +584,49 @@ TEH_PG_reserves_in_insert (    }    { -    enum GNUNET_DB_QueryStatus cs; +    enum GNUNET_DB_QueryStatus cs = TEH_PG_commit (pg); -    cs = TEH_PG_commit (pg); -    if (cs < 0) -    { -      for (unsigned int i = 0; i<reserves_length; i++) -        GNUNET_free (notify_s[i]); +    if (0 > cs)        return cs; -    }    } +  return reserves_length; +} -exit: -  for (unsigned int i = 0; i<reserves_length; i++) -    GNUNET_free (notify_s[i]); -  return reserves_length; +enum GNUNET_DB_QueryStatus +TEH_PG_reserves_in_insert ( +  void *cls, +  const struct TALER_EXCHANGEDB_ReserveInInfo *reserves, +  unsigned int reserves_length, +  unsigned int batch_size, +  enum GNUNET_DB_QueryStatus *results) +{ +  struct PostgresClosure *pg = cls; +  struct ReserveRecord rrs[reserves_length]; +  enum GNUNET_DB_QueryStatus qs; + +  for (unsigned int i = 0; i<reserves_length; i++) +  { +    const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i]; +    struct ReserveRecord *rr = &rrs[i]; + +    rr->reserve = reserve; +    TALER_payto_hash (reserves->sender_account_details, +                      &rr->h_payto); +    rr->notify_s = compute_notify_on_reserve (reserve->reserve_pub); +    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                "Creating reserve %s with expiration in %s\n", +                TALER_B2S (&reserve->reserve_pub), +                GNUNET_STRINGS_relative_time_to_string ( +                  pg->idle_reserve_expiration_time, +                  false)); +  } +  qs = transact (pg, +                 rrs, +                 reserves_length, +                 batch_size, +                 results); +  for (unsigned int i = 0; i<reserves_length; i++) +    GNUNET_free (rrs[i].notify_s); +  return qs;  } | 
