/*
  This file is part of Anastasis
  Copyright (C) 2020-2022 Anastasis SARL

  Anastasis is free software; you can redistribute it and/or modify it under the
  terms of the GNU Affero General Public License as published by the Free Software
  Foundation; either version 3, or (at your option) any later version.

  Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.

  You should have received a copy of the GNU Affero General Public License along with
  Anastasis; see the file COPYING.GPL.  If not, see <http://www.gnu.org/licenses/>
*/
/**
 * @file stasis/anastasis-db_pg.h
 * @brief internal shared state for the Anastasis postgres database
 * @author Christian Grothoff
 */
#ifndef ANASTASIS_DB_PG_H
#define ANASTASIS_DB_PG_H

#include "platform.h"
#include "anastasis_util_lib.h"
#include "anastasis_database_lib.h"
#include <gnunet/gnunet_util_lib.h>
#include <gnunet/gnunet_db_lib.h>
#include <gnunet/gnunet_pq_lib.h>
#include <taler/taler_pq_lib.h>

/**
 * How long do we keep transient accounts open (those that have
 * not been paid at all, but are awaiting payment). This puts
 * a cap on how long users have to make a payment after a payment
 * request was generated.
 */
#define TRANSIENT_LIFETIME GNUNET_TIME_UNIT_WEEKS

/**
 * How often do we re-try if we run into a DB serialization error?
 */
#define MAX_RETRIES 3


/**
 * Shared database state for the Anastasis postgres backend.
 */
struct PostgresClosure
{

  /**
   * Postgres connection handle.
   */
  struct GNUNET_PQ_Context *conn;

  /**
   * Underlying configuration.
   */
  const struct GNUNET_CONFIGURATION_Handle *cfg;

  /**
   * Name of the currently active transaction, NULL if none is active.
   */
  const char *transaction_name;

  /**
   * Currency we accept payments in.
   */
  char *currency;

};


/**
 * Prepared statements have been initialized in this edition.
 */
extern uint64_t ANASTASIS_DB_prep_gen_;

/**
 * Global database state, initialized by ANASTASIS_DB_init().
 */
extern struct PostgresClosure *pg;

/**
 * Prepares SQL statement @a sql under @a name for
 * connection @a pg once.
 * Returns with #GNUNET_DB_STATUS_HARD_ERROR on failure.
 *
 * @param name name to prepare the statement under
 * @param sql actual SQL text
 */
#define PREPARE(name,sql)                               \
        do {                                            \
          static unsigned long long gen;                \
                                                  \
          if (gen < ANASTASIS_DB_prep_gen_)             \
          {                                             \
            struct GNUNET_PQ_PreparedStatement ps[] = { \
              GNUNET_PQ_make_prepare (name, sql),       \
              GNUNET_PQ_PREPARED_STATEMENT_END          \
            };                                          \
                                                  \
            if (GNUNET_OK !=                            \
                GNUNET_PQ_prepare_statements (pg->conn, \
                                              ps))      \
            {                                           \
              GNUNET_break (0);                         \
              return GNUNET_DB_STATUS_HARD_ERROR;       \
            }                                           \
            gen = ANASTASIS_DB_prep_gen_;               \
          }                                             \
        } while (0)


#endif
