/* This file is part of TALER Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. TALER 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 General Public License for more details. You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, If not, see */ /** * @file mintdb/perf_taler_mintdb_interpreter.h * @brief Library for performance analysis of taler database * @author Nicolas Fournier */ #ifndef __PERF_TALER_MINTDB_INTERPRETER_H__ #define __PERF_TALER_MINTDB_INTERPRETER_H__ #include #include "taler_mintdb_plugin.h" /** * Marks the end of the command chain * @param _label */ #define PERF_TALER_MINTDB_INIT_CMD_END(_label) \ { \ .command = PERF_TALER_MINTDB_CMD_END, \ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_NONE \ } /** * */ #define PERF_TALER_MINTDB_INIT_CMD_DEBUG(_label) \ { \ .command = PERF_TALER_MINTDB_CMD_DEBUG, \ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_NONE \ } /** * The begining of a loop * @param _label the name of the loop * @param _iter the number of iteration of the loop */ #define PERF_TALER_MINTDB_INIT_CMD_LOOP(_label, _iter) \ { \ .command = PERF_TALER_MINTDB_CMD_LOOP , \ .label = _label , \ .exposed_type = PERF_TALER_MINTDB_NONE , \ .details.loop = { \ .max_iterations = _iter , \ .curr_iteration = 0 } \ } /** * Marks the end of the loop @_label_loop */ #define PERF_TALER_MINTDB_INIT_CMD_END_LOOP(_label, _label_loop) \ {\ .command = PERF_TALER_MINTDB_CMD_END_LOOP , \ .label = _label , \ .exposed_type = PERF_TALER_MINTDB_NONE , \ .details.end_loop.label_loop = _label_loop \ } /** * Saves the time of execution to use for logging with gauger */ #define PERF_TALER_MINTDB_INIT_CMD_GET_TIME(_label) \ { \ .command = PERF_TALER_MINTDB_CMD_GET_TIME, \ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_NONE, \ } /** * Commits the duration between @a _label_start and @a _label_stop * to Gauger with @a _description explaining */ #define PERF_TALER_MINTDB_INIT_CMD_GAUGER(_label, _label_start, _label_stop, _description, _divide) \ { \ .command = PERF_TALER_MINTDB_CMD_GAUGER, \ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_NONE, \ .details.gauger = { \ .label_start = _label_start, \ .label_stop = _label_stop, \ .description = _description, \ .divide = _divide, \ } \ } /** * Initiate a database transaction */ #define PERF_TALER_MINTDB_INIT_CMD_START_TRANSACTION(_label) \ { \ .command = PERF_TALER_MINTDB_CMD_START_TRANSACTION, \ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_NONE, \ } /** * Commits a database connection */ #define PERF_TALER_MINTDB_INIT_CMD_COMMIT_TRANSACTION(_label) \ { \ .command = PERF_TALER_MINTDB_CMD_COMMIT_TRANSACTION, \ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_NONE, \ } /** * Extracts @a _nb_saved items of type @a _save_type * from the command @a _label_save during the loop @a _label_loop */ #define PERF_TALER_MINTDB_INIT_CMD_SAVE_ARRAY(_label, _label_loop, _label_save, _nb_saved, _save_type) \ { \ .command = PERF_TALER_MINTDB_CMD_SAVE_ARRAY, \ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_NONE, \ .details.save_array = { \ .label_loop = _label_loop, \ .label_save = _label_save, \ .nb_saved = _nb_saved, \ .type_saved = _save_type \ } \ } /** * Loads @a _nb_saved previously sampled data of type @a _saved_type * from @a _label_save during the loop @a _label_loop */ #define PERF_TALER_MINTDB_INIT_CMD_LOAD_ARRAY(_label, _label_loop, _label_save) \ { \ .command = PERF_TALER_MINTDB_CMD_LOAD_ARRAY, \ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_NONE, \ .details.load_array = { \ .label_loop = _label_loop, \ .label_save = _label_save \ } \ } /** * Insert a deposit into the database */ #define PERF_TALER_MINTDB_INIT_CMD_INSERT_DEPOSIT(_label, _label_dki) \ { \ .command = PERF_TALER_MINTDB_CMD_INSERT_DEPOSIT,\ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_DEPOSIT, \ .details.insert_deposit.label_dki = _label_dki, \ } /** * Check if a deposit is in the database * @param _label_deposit Label of the deposit to use */ #define PERF_TALER_MINTDB_INIT_CMD_GET_DEPOSIT(_label, _label_deposit) \ { \ .command = PERF_TALER_MINTDB_CMD_GET_DEPOSIT, \ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_NONE, \ .details.get_deposit.label_source = _label_deposit \ } /** * Creates a new reserve in the database */ #define PERF_TALER_MINTDB_INIT_CMD_INSERT_RESERVE(_label) \ { \ .command = PERF_TALER_MINTDB_CMD_INSERT_RESERVE, \ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_RESERVE \ } /** * Polls the database for a secific reserve's details * @param _label_source Source for the reserve to poll */ #define PERF_TALER_MINTDB_INIT_CMD_GET_RESERVE(_label, _label_source) \ { \ .command = PERF_TALER_MINTDB_CMD_GET_RESERVE, \ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_NONE, \ .details.get_reserve.label_source = _label_source \ } /** * Inserts informations about a withdrawal in the database */ #define PERF_TALER_MINTDB_INIT_CMD_INSERT_WITHDRAW(_label, _label_dki, _label_reserve) \ { \ .command = PERF_TALER_MINTDB_CMD_INSERT_WITHDRAW, \ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_BLINDCOIN, \ .details.insert_withdraw = {\ .label_dki = _label_dki, \ .label.reserve = _label_reserve, \ } \ }\ /** * Polls the database about informations regarding a secific withdrawal */ #define PERF_TALER_MINTDB_INIT_CMD_GET_WITHDRAW(_label, _label_source) \ { \ .command = PERF_TALER_MINTDB_CMD_GET_WITHDRAW, \ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_NONE, \ .details.get_withdraw.label_source = _label_source, \ } /** * Inserts informations about a denomination key in the database */ #define PERF_TALER_MINTDB_INIT_CMD_INSERT_DENOMINATION(_label) \ { \ .command = PERF_TALER_MINTDB_CMD_INSERT_DENOMINATION, \ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_DENOMINATION_INFO, \ } /** * Polls the database about informations regarding a specific denomination key */ #define PERF_TALER_MINTDB_INIT_CMD_GET_DENOMINATION(_label, _label_source) \ { \ .command = PERF_TALER_MINTDB_CMD_GET_DENOMINATION, \ .label = _label, \ .exposed_type = PERF_TALER_MINTDB_NONE, \ .details.get_denomination.label_source = _label_source, \ } /** * The type of data stored * in a PERF_TALER_MINTDB_Type */ enum PERF_TALER_MINTDB_Type { PERF_TALER_MINTDB_NONE, PERF_TALER_MINTDB_TIME, PERF_TALER_MINTDB_DEPOSIT, PERF_TALER_MINTDB_BLINDCOIN, PERF_TALER_MINTDB_RESERVE, PERF_TALER_MINTDB_DENOMINATION_INFO, PERF_TALER_MINTDB_COIN_INFO, }; /** * Storage for a variety of data type */ union PERF_TALER_MINTDB_Data { struct timespec time; struct TALER_MINTDB_Deposit *deposit; struct TALER_MINTDB_CollectableBlindcoin *blindcoin; struct TALER_MINTDB_Reserve *reserve; struct TALER_MINTDB_DenominationKeyIssueInformation *dki; struct TALER_CoinPublicInfo *cpi; }; /** * Name of the command */ enum PERF_TALER_MINTDB_CMD_Name { // All comand chain must hace this as their last command PERF_TALER_MINTDB_CMD_END, // Prints it's label PERF_TALER_MINTDB_CMD_DEBUG, // Define the start of al command chain loop PERF_TALER_MINTDB_CMD_LOOP, // Define the end of a command chain loop PERF_TALER_MINTDB_CMD_END_LOOP, // Save the time at which the command was executed PERF_TALER_MINTDB_CMD_GET_TIME, // Upload performance to Gauger PERF_TALER_MINTDB_CMD_GAUGER, // Start a new session PERF_TALER_MINTDB_CMD_NEW_SESSION, // Start a database transaction PERF_TALER_MINTDB_CMD_START_TRANSACTION, // End a database transaction PERF_TALER_MINTDB_CMD_COMMIT_TRANSACTION, // Abort a transaction PERF_TALER_MINTDB_CMD_ABORT_TRANSACTION, // Saves random deposits from a loop PERF_TALER_MINTDB_CMD_SAVE_ARRAY, // Load deposits saved earlier PERF_TALER_MINTDB_CMD_LOAD_ARRAY, // Insert a deposit into the database PERF_TALER_MINTDB_CMD_INSERT_DEPOSIT, // Check if a deposit is in the database PERF_TALER_MINTDB_CMD_GET_DEPOSIT, // Insert currency in a reserve / Create a reserve PERF_TALER_MINTDB_CMD_INSERT_RESERVE, // Get Informations about a reserve PERF_TALER_MINTDB_CMD_GET_RESERVE, // Insert informations about a withdrawal in the database PERF_TALER_MINTDB_CMD_INSERT_WITHDRAW, // Pulls informations about a withdrawal from the database PERF_TALER_MINTDB_CMD_GET_WITHDRAW, // Insert informations about a denomination key in the database PERF_TALER_MINTDB_CMD_INSERT_DENOMINATION, // Polls the database for informations about a specific denomination key PERF_TALER_MINTDB_CMD_GET_DENOMINATION, // Refresh a coin PERF_TALER_MINTDB_CMD_REFRESH_COIN, }; /** * Extra data requiered for the LOOP command */ struct PERF_TALER_MINTDB_CMD_loop_details { // Maximum number of iteration in the loop const unsigned int max_iterations; unsigned int curr_iteration; }; /** * Extra data requiered by the LOOP_END command */ struct PERF_TALER_MINTDB_CMD_loop_end_details { /** * Label of the loop closed by the command */ const char *label_loop; }; /** * Details about the GAUGER command */ struct PERF_TALER_MINTDB_CMD_gauger_details { /** * Label of the starting timestamp */ const char *label_start; /** * Label of the ending timestamp */ const char *label_stop; /** * Description of the metric, used in GAUGER */ const char *description; /** * Constant the result needs to be divided by * to get the result per unit */ float divide; }; /** * Contains extra data requiered by the SAVE_ARRAY command */ struct PERF_TALER_MINTDB_CMD_save_array_details { /** * Number of items to save */ unsigned int nb_saved; /** * Number of items already saved */ unsigned int index; /** * Label of the loop it is attached to */ const char *label_loop; /** * Label of the command exposing the item */ const char *label_save; /** * Type of data saved */ enum PERF_TALER_MINTDB_Type type_saved; /** * Array of data saved */ union PERF_TALER_MINTDB_Data *data_saved; }; /** * Extra data required for the LOAD_ARRAY command */ struct PERF_TALER_MINTDB_CMD_load_array_details { /** * The loop in which the command is located */ const char *label_loop; /** * Label of the command where the items were saved */ const char *label_save; /** * A permutation array used to randomize the order the items are loaded in */ unsigned int *permutation; // A permutation array to randomize the order the deposits are loaded in }; /** * Data used by the command insert_deposit */ struct PERF_TALER_MINTDB_CMD_insert_deposit_details { /** * Label of the source where the reserve used to create the coin is */ const char *label_dki; }; /** * Extra data requiered for the GET_DEPOSIT command */ struct PERF_TALER_MINTDB_CMD_get_deposit_details { /** * The label of the source of the deposit to check */ const char *label_source; }; /** * Extra data requiered for the GET_DEPOSIT command */ struct PERF_TALER_MINTDB_CMD_get_reserve_details { /** * The label of the source of the reserve to check */ const char *label_source; }; struct PERF_TALER_MINTDB_CMD_get_denomination_details { /** * The label of the source of the denomination to check */ const char *label_source; }; /** * Extra data related to the get withdraw command */ struct PERF_TALER_MINTDB_CMD_insert_withdraw_details { /** * label of the denomination key used to sign the coin */ const char *label_dki; /** * label of the reserve the money to mint the coin comes from */ const char *label_reserve; }; /** * Extra data requiered for refreshing coins */ struct PERF_TALER_MINTDB_CMD_refresh_coin_details { /** * The label of the coin to refresh */ const char *label_source; }; /** * Contains extra data required for any command */ union PERF_TALER_MINTDB_CMD_Details { struct PERF_TALER_MINTDB_CMD_loop_details loop; struct PERF_TALER_MINTDB_CMD_loop_end_details end_loop; struct PERF_TALER_MINTDB_CMD_gauger_details gauger; struct PERF_TALER_MINTDB_CMD_save_array_details save_array; struct PERF_TALER_MINTDB_CMD_load_array_details load_array; struct PERF_TALER_MINTDB_CMD_insert_deposit_details insert_deposit; struct PERF_TALER_MINTDB_CMD_get_deposit_details get_deposit; struct PERF_TALER_MINTDB_CMD_get_reserve_details get_reserve; struct PERF_TALER_MINTDB_CMD_get_denomination_details get_denomination; struct PERF_TALER_MINTDB_CMD_refresh_coin_details refresh; struct PERF_TALER_MINTDB_CMD_insert_withdraw_details insert_withdraw; }; /** * Command to be interpreted. */ struct PERF_TALER_MINTDB_Cmd { /** * Type of the command */ enum PERF_TALER_MINTDB_CMD_Name command; /** * Label to refer to the command */ const char *label; /** * Command specific data */ union PERF_TALER_MINTDB_CMD_Details details; /** * Type of the data exposed */ enum PERF_TALER_MINTDB_Type exposed_type; /** * Data easily accessible */ union PERF_TALER_MINTDB_Data exposed; }; /** * Runs the command array @a cmd * using @a db_plugin to connect to the database */ int PERF_TALER_MINTDB_interpret( struct TALER_MINTDB_Plugin *db_plugin, struct PERF_TALER_MINTDB_Cmd cmd[]); #endif