
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#include <unistd.h>

#include <NdbApi.hpp>
#include <mysql.h>

#define CONNECTSTR "ndbsup-priv-2:1406"

#define PRINT_MSG(msg) \
  std::cout << "MSG: " << msg << std::endl

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

Ndb_cluster_connection *cluster_conn_init()
{
	Ndb_cluster_connection *conn;

	if (ndb_init()) {
		exit(EXIT_FAILURE);
	}

	conn = new Ndb_cluster_connection(CONNECTSTR);

	if (conn->connect(4, 5, 1)) {
		fprintf(stderr, "Unable to connect to cluster within 30 secs.");
		exit(EXIT_FAILURE);
	}
	
	if (conn->wait_until_ready(30,0) < 0) {
		fprintf(stderr, "Cluster was not ready within 30 secs.\n");
		exit(EXIT_FAILURE);
	}

	return conn; 
}

void cluster_conn_end(Ndb_cluster_connection *conn)
{
	delete conn;
	PRINT_MSG("Deleted conn");
	ndb_end(0);
	PRINT_MSG("ndb_end");
	exit(0);
}

void do_gettable(Ndb &myNdb)
{
	const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
	const NdbDictionary::Table *myTable= myDict->getTable("Country");

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

	std::cout << "Table " << myTable->getName() << " opened " << std::endl;
}

void do_scan(Ndb &myNdb)
{
	int i;
	NdbTransaction *myTrans;
	NdbScanOperation *myScanOp;
	NdbRecAttr *myRecAttr[1];

	const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
	const NdbDictionary::Table *myTable= myDict->getTable("Country");

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

	/* Setup a transaction */
	myTrans = myNdb.startTransaction();
	if (myTrans == NULL) {
		APIERROR(myNdb.getNdbError());
	}
	PRINT_MSG("Transaction started.");

	/* Setup a Scan operation */
	myScanOp = myTrans->getNdbScanOperation(myTable);
	if (myScanOp == NULL) {
		APIERROR(myTrans->getNdbError());
	}
	PRINT_MSG("Scan operation set up.");

	if (myScanOp->readTuples(NdbOperation::LM_CommittedRead) ==  -1) {
		APIERROR(myTrans->getNdbError());
	}

	myRecAttr[0] = myScanOp->getValue("Name");
	if (myRecAttr[0] == NULL) {
		APIERROR(myTrans->getNdbError());
	}

	if (myTrans->execute(NdbTransaction::NoCommit) != 0) {
		APIERROR(myTrans->getNdbError());
	}
	PRINT_MSG("Transaction executed");

	for (i=0; i < 10; i++) {
		if (myScanOp->nextResult(true) == 0) {
			std::cout << myRecAttr[0]->aRef() << std::endl;
			sleep(60);
		} else {
			APIERROR(myTrans->getNdbError());
		}
	}

	myNdb.closeTransaction(myTrans);
}

int main() 
{
	ndb_init();
	Ndb_cluster_connection *conn;
	conn = cluster_conn_init();

	printf("Connected to MySQL Cluster..\n");

	Ndb myNdb( conn, "world" );
	if (myNdb.init()) APIERROR(myNdb.getNdbError());

	//do_gettable(myNdb);
	do_scan(myNdb);

	//sleep(3600);

	cluster_conn_end(conn);

	return EXIT_SUCCESS;
}

