diff options
Diffstat (limited to 'src/backend-lib/merchant_db.c')
-rw-r--r-- | src/backend-lib/merchant_db.c | 141 |
1 files changed, 137 insertions, 4 deletions
diff --git a/src/backend-lib/merchant_db.c b/src/backend-lib/merchant_db.c index 035a6646..415ff223 100644 --- a/src/backend-lib/merchant_db.c +++ b/src/backend-lib/merchant_db.c @@ -104,7 +104,12 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp) "contract_id INT8 REFERENCES contracts(contract_id)," "amount INT4 NOT NULL," "amount_fraction INT4 NOT NULL," - "coin_sig BYTEA NOT NULL);", + "coin_sig BYTEA NOT NULL);" + "CREATE %1$s TABLE IF NOT EXISTS deposits (" + "dep_perm TEXT NOT NULL," + "transaction_id INT8 PRIMARY KEY," + "pending INT4 NOT NULL," + "mint_url TEXT NOT NULL);", tmp_str); ret = GNUNET_POSTGRES_exec (conn, sql); (void) GNUNET_POSTGRES_exec (conn, @@ -165,6 +170,28 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp) EXITIF (NULL == (res = PQprepare (conn, + "store_deposit_permission", + "INSERT INTO deposits" + "(dep_perm, transaction_id, pending, mint_url) " + "VALUES ($1, $2, $3, $4);", 4, NULL))); + + EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus(res))); + PQclear (res); + + + EXITIF (NULL == (res = PQprepare + (conn, + "update_deposit_permission", + "UPDATE deposits " + "SET pending = $1 " + "WHERE transaction_id = $2", 2, NULL))); + + EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus(res))); + PQclear (res); + + + EXITIF (NULL == (res = PQprepare + (conn, "get_contract_product", "SELECT (" "product" @@ -218,6 +245,115 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp) return GNUNET_SYSERR; } +/** + * Update the pending column of a deposit permission + * @param conn handle to DB + * @param transaction_id identification number of the deposit to + * update + * @param pending true if still pending, false otherwise (i.e. the + * mint did respond something) + * @return GNUNET_OK if successful, GNUNET_SYSERR upon errors + */ +uint32_t +MERCHANT_DB_update_deposit_permission (PGconn *conn, + uint64_t transaction_id, + unsigned int pending) +{ + PGresult *res; + ExecStatusType status; + + struct TALER_PQ_QueryParam params[] = { + TALER_PQ_query_param_uint64 (&transaction_id), + TALER_PQ_query_param_uint32 (&pending), + }; + + res = TALER_PQ_exec_prepared (conn, "update_deposit_permission", params); + status = PQresultStatus (res); + + if (PGRES_COMMAND_OK != status) + { + + const char *sqlstate; + + sqlstate = PQresultErrorField (res, PG_DIAG_SQLSTATE); + if (NULL == sqlstate) + { + /* very unexpected... */ + GNUNET_break (0); + PQclear (res); + return GNUNET_SYSERR; + } + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Database commit failure: %s\n", + sqlstate); + PQclear (res); + return GNUNET_SYSERR; + } +} + +/** + * Store a deposit permission in DB. To be mainly used if /deposit should + * be retried; also, the merchant can benefit from this information in case + * he needs to later investigate about some transaction_id. + * @param conn DB handle + * @param transaction_id identification number of this payment (which is the + * same id of the related contract) + * @param pending if true, this payment got to a persistent state + * @param which mint is to get this deposit permission + * @return GNUNET_OK if successful, GNUNET_SYSERR upon errors + */ +uint32_t +MERCHANT_DB_store_deposit_permission (PGconn *conn, + const char *deposit_permission, + uint64_t transaction_id, + unsigned int pending, + const char *mint_url) +{ + PGresult *res; + ExecStatusType status; + + struct TALER_PQ_QueryParam params[] = { + TALER_PQ_query_param_fixed_size (deposit_permission, strlen (deposit_permission)), + TALER_PQ_query_param_uint64 (&transaction_id), + TALER_PQ_query_param_uint32 (&pending), + TALER_PQ_query_param_fixed_size (mint_url, strlen (mint_url)), + TALER_PQ_query_param_end + }; + res = TALER_PQ_exec_prepared (conn, "store_deposit_permission", params); + status = PQresultStatus (res); + + if (PGRES_COMMAND_OK != status) + { + const char *sqlstate; + + sqlstate = PQresultErrorField (res, PG_DIAG_SQLSTATE); + if (NULL == sqlstate) + { + /* very unexpected... */ + GNUNET_break (0); + PQclear (res); + return GNUNET_SYSERR; + } + /* 40P01: deadlock, 40001: serialization failure */ + if ( (0 == strcmp (sqlstate, + "23505"))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Inserting same transaction id twice\n"); + /* Primary key violation */ + PQclear (res); + return GNUNET_SYSERR; + } + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Database commit failure: %s\n", + sqlstate); + PQclear (res); + return GNUNET_SYSERR; + } + + PQclear (res); + return GNUNET_OK; +} /** * Insert a contract record into the database and if successfull @@ -314,9 +450,6 @@ MERCHANT_DB_contract_create (PGconn *conn, PQclear (res); return GNUNET_OK; - EXITIF_exit: - PQclear (res); - return GNUNET_SYSERR; } long long |