#include <NdbApi.hpp>
#include <stdio.h>
#include <iostream>

namespace std {} using namespace std;

#define PRINT_ERROR(code,msg) \
    cout << "Error in " << __FILE__ << ", line: " << __LINE__ \
         << ", code: " << code \
         << ", msg: " << msg << "." << endl
#define APIERROR(error) { \
    PRINT_ERROR(error.code,error.message); \
    exit(-1); }

static void usage()
{
    fprintf(stderr, "This tool allows to alter a table into a \"diskless\" mode\n"
            "Usage: ndb_alter_table <database_name> <table_name>\n");
}

static void run_application(Ndb_cluster_connection &cluster_connection, const char* db_name, const char* table_name);

int main(int argc, char* argv[])
{
    if (argc != 3)
    {
        usage();
        exit(1);
    }
    const char* db_name = argv[1];
    const char* table_name = argv[2];
    // ndb_init must be called first
    ndb_init();
    printf("NDB library initialized\n");
    // connect to mysql server and cluster and run application
    {
        // Object representing the cluster
        const char* connect_string = getenv("NDB_CONNECT_STRING");
        if (connect_string == NULL)
        {
            printf("Environmental variable NDB_CONNECT_STRING is not defined. "
                   "Using default connect-string \"localhost:1186\"\n");
            connect_string = "localhost:1186";
        }
        Ndb_cluster_connection cluster_connection(connect_string);

        // Connect to cluster management server (ndb_mgmd)
        if (cluster_connection.connect(4 /* retries               */,
                                       5 /* delay between retries */,
                                       1 /* verbose               */))
        {
            cout << "Cluster management server was not ready within 30 secs.\n";
            exit(1);
        }
        printf("Connected to the management server\n");

        // Optionally connect and wait for the storage nodes (ndbd's)
        if (cluster_connection.wait_until_ready(30, 0) < 0)
        {
            cout << "Cluster was not ready within 30 secs.\n";
            exit(1);
        }
        printf("Cluster is ready\n");
        run_application(cluster_connection, db_name, table_name);
    }
    ndb_end(0);
    return 0;
}

static void do_alter(Ndb &myNdb, const char* table_name);

static void run_application(Ndb_cluster_connection &cluster_connection, const char* db_name, const char* table_name)
{
    // Connect to database via NdbApi

    // Object representing the database
    Ndb myNdb( &cluster_connection, db_name );
    if (myNdb.init())
    {
        APIERROR(myNdb.getNdbError());
    }
    printf("Connected to the %s database\n", db_name);
    do_alter(myNdb, table_name);
}

static void do_alter(Ndb &myNdb, const char* table_name)
{
    NdbDictionary::Dictionary* myDict = myNdb.getDictionary();
    const NdbDictionary::Table *myTable = myDict->getTable(table_name);

    if (myTable == NULL) 
        APIERROR(myDict->getNdbError());

    printf("Turning logging off for the table %s\n", table_name);
    NdbDictionary::Table alteredTable = *myTable;
    alteredTable.setLogging(false);
    if (myDict->alterTable(alteredTable) != 0)
    {
        APIERROR(myDict->getNdbError());
    }
    printf("Table %s altered successfully\n", table_name);
}
