/*
   Copyright (C) 2003-2006 MySQL AB
    All rights reserved. Use is subject to license terms.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License, version 2.0,
   as published by the Free Software Foundation.

   This program is also distributed with certain software (including
   but not limited to OpenSSL) that is licensed under separate terms,
   as designated in a particular file or component or in included license
   documentation.  The authors of MySQL hereby grant you an additional
   permission to link the program and your derivative works with the
   separately licensed software that they have included with MySQL.

   This program 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, version 2.0, for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
*/


/* ***************************************************
       BASIC TEST 1
       Test basic functions and status of NDB

       Arguments:
        none 

       Returns:
        0 - Test passed
       -1 - Test failed
        1 - Invalid arguments
flexBench
 * *************************************************** */

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

#define MAXATTR 4
#define MAXTABLES 4
#define PAGESIZE 8192
#define OVERHEAD 0.02
#define NUMBEROFRECORDS 10
#define PKSIZE 1
#define ATTRNAMELEN 16


static void  createTable_IPACCT(Ndb*);
static void  createTable_RPACCT(Ndb*);
static void  createTable_SBMCALL(Ndb*);
static void  createTable_TODACCT(Ndb*);

static void  error_handler(const char*);
static bool  error_handler2(const char*, int) ;

static void  setAttrNames(void);
static void  setTableNames(void);
static void  create_table(Ndb*);
static void  insert_rows(Ndb*);
static void  update_rows(Ndb*);
static void  delete_rows(Ndb*);
static void  verify_deleted(Ndb*);
static void  read_and_verify_rows(Ndb*);

static void  insert_IPACCT(Ndb*, Uint32, Uint32, Uint32, Uint32, Uint32); //3 for Pk, and two data. just to test;

static void read_IPACCT(Ndb* , Uint32 , Uint32  , Uint32 );

static  int		        tAttributeSize;
static  int             bTestPassed;

static  char    		tableName[MAXTABLES][ATTRNAMELEN];static  char		    attrName[MAXATTR][ATTRNAMELEN];
static  int    		    attrValue[NUMBEROFRECORDS];
static  int                 pkValue[NUMBEROFRECORDS];
static int		    failed = 0 ;
#include <NdbOut.hpp>

NDB_COMMAND(celloDb, "celloDb", "celloDb", "celloDb", 65535)
{
  ndb_init();

  int                   tTableId;
  int                   i;
  Ndb	      		MyNdb( "CELLO-SESSION-DB" );

  MyNdb.init();

  // Assume test passed
  bTestPassed = 0;
  /*
  // Initialize global variables
  for (i = 0; i < NUMBEROFRECORDS; i ++)
     pkValue[i] = i; 
  
  for (i = 0; i < NUMBEROFRECORDS; i ++)
     attrValue[i] = i;
  */
  tAttributeSize = 1;

  // Wait for Ndb to become ready
  if (MyNdb.waitUntilReady() == 0) {
    ndbout << endl << "Cello session db - Starting " << endl;
    ndbout << "Test basic functions and status of NDB" << endl;
    

      
    createTable_SBMCALL (&MyNdb );
    createTable_RPACCT (&MyNdb );
    createTable_TODACCT (&MyNdb );
    createTable_IPACCT (&MyNdb );
    
    insert_IPACCT(&MyNdb, 1,2,1,2,2);
    read_IPACCT(&MyNdb, 1, 2 , 1);
    /*
      insert_rows(&MyNdb);

      read_and_verify_rows(&MyNdb);


      // Create some new values to use for update
      for (i = 0; i < NUMBEROFRECORDS; i++)
		  attrValue[i] = NUMBEROFRECORDS-i;

      update_rows(&MyNdb);

      read_and_verify_rows(&MyNdb);

      delete_rows(&MyNdb);

      verify_deleted(&MyNdb);
      */
    }
    else {
	bTestPassed = -1;
      }


  if (bTestPassed == 0)
    {
      // Test passed
      ndbout << "OK - Test passed" << endl;
    }
  else
    {
      // Test failed
      ndbout << "FAIL - Test failed" << endl;
      exit(-1);
    }
  return NULL;
}

static void 
error_handler(const char* errorText)
{
  // Test failed 
  ndbout << endl << "ErrorMessage: " << errorText << endl;
  bTestPassed = -1;
}

static void
createTable_SBMCALL ( Ndb* pMyNdb )
{
  /****************************************************************
   *	Create table and attributes. 	
   *
   *    create table SBMCALL(
   *      for attribs, see the REQ SPEC for cello session DB
   *     )
   *  
   ***************************************************************/ 

  const char* tname = "SBMCALL";
  Uint32 recordsize = 244; //including 12 byte overhead
  Uint32 pksize = 8; //size of total prim. key. in bytes. sum of entire composite PK.
  Uint32 tTableId = pMyNdb->getTable()->openTable(tname);
  
  if (tTableId == -1) {    
    Uint32              check; 
    Uint32              i;
    NdbSchemaCon      	*MySchemaTransaction;
    NdbSchemaOp	       	*MySchemaOp;
    
    ndbout << "Creating " << tname << "..." << endl;
    
    MySchemaTransaction = pMyNdb->startSchemaTransaction();
    if( ( MySchemaTransaction == NULL ) && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    
    MySchemaOp = MySchemaTransaction->getNdbSchemaOp();	
    if( ( MySchemaOp == NULL ) && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    
        
    // Createtable

    Uint32 tablesize=(recordsize*NUMBEROFRECORDS + OVERHEAD * NUMBEROFRECORDS)/1024;
    Uint32 noPages=(pksize*NUMBEROFRECORDS)/PAGESIZE;
    
    ndbout << "table size " << tablesize << "for table name " << tname << endl;
    
    check = MySchemaOp->createTable( tname,
        		             tablesize,		// Table Size
				     TupleKey,	// Key Type
				     noPages,		// Nr of Pages
				     All,
				     6,
				     78,
				     80,
				     1,
				     true
				     );
    
    if( check == -1 ) {
      error_handler(MySchemaTransaction->getNdbErrorString());
      exit(-1);
    }
    

    
    // Create first column, primary key 
    check = MySchemaOp->createAttribute( "SPBBOARDID",
					 TupleKey,
					 32,
					 PKSIZE,
					 UnSigned,
					 MMBased,
					 NotNullAttribute );

    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    

    // Create second column, primary key 
    check = MySchemaOp->createAttribute( "CALLID",
					 TupleKey,
					 32,
					 PKSIZE,
					 UnSigned,
					 MMBased,
					 NotNullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    

    // Creat thrid column, RP Session info, byte[16] represented as (String, 16)
    check = MySchemaOp->createAttribute( "RPSESS",
					 NoKey,
					 32,
					 16,
					 String,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    
// Creat fourth column, GRE Tunnel info, byte[16] represented as (String, 16)
    check = MySchemaOp->createAttribute( "GRETUNNEL",
					 NoKey,
					 32,
					 16,
					 String,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    
// Creat fifth column, PPP Session info, byte[24] represented as (String, 24)
    check = MySchemaOp->createAttribute( "PPPSESS",
					 NoKey,
					 32,
					 24,
					 String,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;

    
    if( (MySchemaTransaction->execute() == -1) && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    
    pMyNdb->closeSchemaTransaction(MySchemaTransaction);
    ndbout << "done" << endl;
    
    
  } //if 
  
  //else table already created , proceed
}



static void
createTable_RPACCT(Ndb*pMyNdb)
{
  
  /****************************************************************
   *	Create table and attributes. 	
   *
   *    create table RPACCT(
   *      for attribs, see the REQ SPEC for cello session DB
   *     )
   *  
   ***************************************************************/ 
 
 const char* tname = "RPACCT";
 Uint32 recordsize = 380; //including 12 byte overhead
 Uint32 pksize = 8; //size of total prim. key. in bytes.
 Uint32 tTableId = pMyNdb->getTable()->openTable(tname);
 
 if (tTableId == -1) {    
   Uint32              check; 
   Uint32              i;
   NdbSchemaCon      	*MySchemaTransaction;
   NdbSchemaOp	       	*MySchemaOp;
   
   ndbout << "Creating " << tname << "..." << endl;
   
   MySchemaTransaction = pMyNdb->startSchemaTransaction();
   if( MySchemaTransaction == NULL )
     error_handler(MySchemaTransaction->getNdbErrorString());
   
   MySchemaOp = MySchemaTransaction->getNdbSchemaOp();	
   if( MySchemaOp == NULL ) 
      error_handler(MySchemaTransaction->getNdbErrorString());
   
   // Createtable
   
   Uint32 tablesize=(recordsize*NUMBEROFRECORDS + OVERHEAD * NUMBEROFRECORDS)/1024;
   Uint32 noPages=(pksize*NUMBEROFRECORDS)/PAGESIZE;
   
   ndbout << "table size " << tablesize << "for table name " << tname << endl;
   
   check = MySchemaOp->createTable( tname,
				    tablesize,		// Table Size
				    TupleKey,	// Key Type
				     noPages		// Nr of Pages
				    );
   
   if( check == -1 ) 
     error_handler(MySchemaTransaction->getNdbErrorString());
   
   
   
   // Create first column, primary key 
   check = MySchemaOp->createAttribute( "SPBBOARDID",
					TupleKey,
					32,
					PKSIZE,
					 UnSigned,
					MMBased,
					NotNullAttribute );
   
   if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
     exit (-1) ;
   
   
   // Create second column, primary key 
   check = MySchemaOp->createAttribute( "CALLID",
					TupleKey,
					32,
					PKSIZE,
					 UnSigned,
					 MMBased,
					 NotNullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    

    // Creat thrid column MS ID, 4 byte unsigned
    check = MySchemaOp->createAttribute( "MSID",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    

    // Create PDSN FA Address, 4 byte unsigned
    check = MySchemaOp->createAttribute( "PDSN",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    

    // Create Serving PCF, 4 byte unsigned
    check = MySchemaOp->createAttribute( "SPCF",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    


    // Create BS ID, 12 byte char, represented as String,12
    check = MySchemaOp->createAttribute( "BSID",
					 NoKey,
					 32,
					 12,
					 String,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    




    // Create User Zone, 4 byte unsigned
    check = MySchemaOp->createAttribute( "UZ",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    

    // Create Forward Multiplex, 4 byte unsigned
    check = MySchemaOp->createAttribute( "FMO",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    

    // Create Reverse Multiplex, 4 byte unsigned
    check = MySchemaOp->createAttribute( "RMO",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;


    // Create Forward Fund rate, 4 byte unsigned
    check = MySchemaOp->createAttribute( "FFR",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;

    
 // Create Reverse Fund rate, 4 byte unsigned
    check = MySchemaOp->createAttribute( "RFR",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;


    
 // Create Service Option, 4 byte unsigned
    check = MySchemaOp->createAttribute( "SO",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;




 // Create Forward Traffic Type, 4 byte unsigned
    check = MySchemaOp->createAttribute( "FTT",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;



// Create Reverse Traffic Type, 4 byte unsigned
    check = MySchemaOp->createAttribute( "RTT",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;



// Create Fund Frame Size, 4 byte unsigned
    check = MySchemaOp->createAttribute( "FFS",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;



// Create Forware Fund RC, 4 byte unsigned
    check = MySchemaOp->createAttribute( "FFRC",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;



    // Create Reverse Fund RC, 4 byte unsigned
    check = MySchemaOp->createAttribute( "RFRC",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    

    // Create DCCH Frame Format, 4 byte unsigned
    check = MySchemaOp->createAttribute( "DCCH",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    
    
    // Create Airlink QOS, 4 byte unsigned
    check = MySchemaOp->createAttribute( "AQOS",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;



// Create Bad PPP Frame Count , 4 byte unsigned
    check = MySchemaOp->createAttribute( "BPPPFC",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;




// Create Active Time , 4 byte unsigned
    check = MySchemaOp->createAttribute( "AT",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;



// Create Nb Active Transitions , 4 byte unsigned
    check = MySchemaOp->createAttribute( "NBAT",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;


// Create SDB Octet Count In , 4 byte unsigned
    check = MySchemaOp->createAttribute( "SDBOCI",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;


    

// Create Nb SDB In, 4 byte unsigned
    check = MySchemaOp->createAttribute( "NBSDBI",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;




// Create Nb SDB Out, 4 byte unsigned
    check = MySchemaOp->createAttribute( "NBSDBO",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;




// Create HDLC Bytes received, 4 byte unsigned
    check = MySchemaOp->createAttribute( "HDLC",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    

    
    if( (MySchemaTransaction->execute() == -1) && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    
    pMyNdb->closeSchemaTransaction(MySchemaTransaction);
    ndbout << "done" << endl;
    
 } //if 
  
 //else table already created , proceed
  }
 

static void
createTable_IPACCT(Ndb* pMyNdb)
{


  /****************************************************************
   *	Create table and attributes. 	
   *
   *    create table IPACCT(
   *      for attribs, see the REQ SPEC for cello session DB
   *     )
   *  
   ***************************************************************/ 

  const char* tname = "IPACCT";
  Uint32 recordsize = 70; //including 12 byte overhead
  Uint32 pksize = 12; //size of total prim. key. in bytes.
  Uint32 tTableId = pMyNdb->getTable()->openTable(tname);
  
  if (tTableId == -1) {    
    Uint32              check; 
    Uint32              i;
    NdbSchemaCon      	*MySchemaTransaction;
    NdbSchemaOp	       	*MySchemaOp;
    
    ndbout << "Creating " << tname << "..." << endl;
    
    MySchemaTransaction = pMyNdb->startSchemaTransaction();
    if( MySchemaTransaction == NULL )
      error_handler(MySchemaTransaction->getNdbErrorString());
    
    MySchemaOp = MySchemaTransaction->getNdbSchemaOp();	
    if( MySchemaOp == NULL ) 
      error_handler(MySchemaTransaction->getNdbErrorString());
    
    // Createtable

    Uint32 tablesize=(recordsize*NUMBEROFRECORDS + OVERHEAD * NUMBEROFRECORDS)/1024;
    Uint32 noPages=(pksize*NUMBEROFRECORDS)/PAGESIZE;
    
    ndbout << "table size " << tablesize << "for table name " << tname << endl;
    
    check = MySchemaOp->createTable( tname,
        		             tablesize,		// Table Size
				     TupleKey,	// Key Type
				     noPages		// Nr of Pages
				     );
    
    if( check == -1 ) 
      error_handler(MySchemaTransaction->getNdbErrorString());
    


    // Create first column, primary key 
    check = MySchemaOp->createAttribute( "SPBBOARDID",
					 TupleKey,
					 32,
					 PKSIZE,
					 UnSigned,
					 MMBased,
					 NotNullAttribute );

    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    

    // Create second column, primary key 
    check = MySchemaOp->createAttribute( "CALLID",
					 TupleKey,
					 32,
					 PKSIZE,
					 UnSigned,
					 MMBased,
					 NotNullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;

   // Create third column, primary key 
    check = MySchemaOp->createAttribute( "IPADDR",
					 TupleKey,
					 32,
					 PKSIZE,
					 String,
					 MMBased,
					 NotNullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;


     

// Create Acct session id  4 byte unsigned
    check = MySchemaOp->createAttribute( "ASID",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;


// Create Correlation ID, 4 byte unsigned
    check = MySchemaOp->createAttribute( "CID",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;


// Create MIP HA Address, 4 byte unsigned
    check = MySchemaOp->createAttribute( "MIPHA",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;


    

    
// Create IP technology, 4 byte unsigned
    check = MySchemaOp->createAttribute( "IPT",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;



// Create Compuls Tunnel ID, 4 byte unsigned
    check = MySchemaOp->createAttribute( "CTID",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;

// Create IP QOS, 4 byte unsigned
    check = MySchemaOp->createAttribute( "IPQOS",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;

    
    // Create Data octet count in, 4 byte unsigned
    check = MySchemaOp->createAttribute( "DOCI",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;

    // Create Data octet count out, 4 byte unsigned
    check = MySchemaOp->createAttribute( "DOCO",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;

    // Create Event time, 4 byte unsigned
    check = MySchemaOp->createAttribute( "ET",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;

     // Create In mip sig count, 4 byte unsigned
    check = MySchemaOp->createAttribute( "IMSC",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;

// Create Out mip sig count, 4 byte unsigned
    check = MySchemaOp->createAttribute( "OMSC",
					 NoKey,
					 32,
					 1,
					 UnSigned,
					 MMBased,
					 NullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;

    
    if( (MySchemaTransaction->execute() == -1) && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    
    pMyNdb->closeSchemaTransaction(MySchemaTransaction);
    ndbout << "done" << endl;
    


  } //if 

  //else table already created , proceed
}


static void
createTable_TODACCT(Ndb* pMyNdb)
{


  /****************************************************************
   *	Create table and attributes. 	
   *
   *    create table TODACCT(
   *      for attribs, see the REQ SPEC for cello session DB
   *     )
   *  
   ***************************************************************/ 
  
  const char* tname = "TODACCT";
  Uint32 recordsize = 92; //including 12 byte overhead
  Uint32 pksize = 12; //size of total prim. key. in bytes.
  Uint32 tTableId = pMyNdb->getTable()->openTable(tname);
  
  if (tTableId == -1) {    
    Uint32              check; 
    Uint32              i;
    NdbSchemaCon      	*MySchemaTransaction;
    NdbSchemaOp	       	*MySchemaOp;
    
    ndbout << "Creating " << tname << "..." << endl;
    
    MySchemaTransaction = pMyNdb->startSchemaTransaction();
    if( MySchemaTransaction == NULL )
      error_handler(MySchemaTransaction->getNdbErrorString());
    
    MySchemaOp = MySchemaTransaction->getNdbSchemaOp();	
    if( MySchemaOp == NULL ) 
      error_handler(MySchemaTransaction->getNdbErrorString());
    
    // Createtable
    
    Uint32 tablesize=(recordsize*NUMBEROFRECORDS + OVERHEAD * NUMBEROFRECORDS)/1024;
    Uint32 noPages=(pksize*NUMBEROFRECORDS)/PAGESIZE;
    
    ndbout << "table size " << tablesize << "for table name " << tname << endl;
    
    check = MySchemaOp->createTable( tname,
        		             tablesize,		// Table Size
				     TupleKey,	// Key Type
				     noPages		// Nr of Pages
				     );
    
    if( check == -1 ) 
      error_handler(MySchemaTransaction->getNdbErrorString());
    


    // Create first column, primary key 
    check = MySchemaOp->createAttribute( "SPBBOARDID",
					 TupleKey,
					 32,
					 PKSIZE,
					 UnSigned,
					 MMBased,
					 NotNullAttribute );

    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;
    

    // Create second column, primary key 
    check = MySchemaOp->createAttribute( "CALLID",
					 TupleKey,
					 32,
					 PKSIZE,
					 UnSigned,
					 MMBased,
					 NotNullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;

   // Create third column, primary key 
    check = MySchemaOp->createAttribute( "IPADDR",
					 TupleKey,
					 32,
					 PKSIZE,
					 String,
					 MMBased,
					 NotNullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;



   // Create third column, primary key 
    check = MySchemaOp->createAttribute( "INDEX",
					 TupleKey,
					 32,
					 PKSIZE,
					 UnSigned,
					 MMBased,
					 NotNullAttribute );
    
    if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;


     

// Create Acct session id  4 byte unsigned
    check = MySchemaOp->createAttribute( "TOD",
					 NoKey,
					 32,
					 16,
					 String,
					 MMBased,
					 NullAttribute );


   if( (check == -1)  && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
      exit (-1) ;


     
   if( (MySchemaTransaction->execute() == -1) && (!error_handler2((const char*)MySchemaTransaction->getNdbErrorString(),  MySchemaTransaction->getNdbError())) )
     exit (-1) ;
   
   pMyNdb->closeSchemaTransaction(MySchemaTransaction);
   ndbout << "done" << endl;
   
  } //if 
  
 //else table already created , proceed
}






static void  read_IPACCT(Ndb* pMyNdb, Uint32 CALLID, Uint32 SPBBOARDID , Uint32 IPADDR)
{


  int                   check;
  int                   loop_count_ops;
  int					count;
  int                   count_attributes;
  char* value;
  NdbConnection			*MyTransaction;
  NdbOperation			*MyOperation;
  NdbRecAttr*           tTmp;
  
  
  
  MyTransaction = pMyNdb->startTransaction();
  if (MyTransaction == NULL)
    error_handler(pMyNdb->getNdbErrorString());
  
  MyOperation = MyTransaction->getNdbOperation("IPACCT");	
  if (MyOperation == NULL) 
    error_handler( MyTransaction->getNdbErrorString());
  
  check = MyOperation->readTuple();
  if( check == -1 ) 
    error_handler( MyTransaction->getNdbErrorString());
  
  check = MyOperation->equal( "SPBBOARDID",SPBBOARDID );
  if( check == -1 ) 
    error_handler( MyTransaction->getNdbErrorString());
  

  check = MyOperation->equal( "IPADDR","IPADDR" );
  if( check == -1 ) 
    error_handler( MyTransaction->getNdbErrorString());
  

  check = MyOperation->equal( "CALLID",CALLID );
  if( check == -1 ) 
    error_handler( MyTransaction->getNdbErrorString());




  tTmp = MyOperation->getValue("IPQOS", NULL );
  if( tTmp == NULL ) 
    error_handler( MyTransaction->getNdbErrorString());
  ndbout << " tTmp " << tTmp->isNULL() << endl;
  MyTransaction->execute(Commit);
  
  ndbout << " value read " << tTmp->int32_value() << endl;
  
}



static void  insert_IPACCT(Ndb* pMyNdb, Uint32 CALLID, Uint32 SPBBOARDID , Uint32 IPADDR, Uint32 ASID, Uint32 IPQOS)
{
  /****************************************************************
   *	Insert rows 	
   *
   ***************************************************************/

  int                   check;
  int                   loop_count_ops;
  int					count;
  int                   i;
  NdbConnection			*MyTransaction;
  NdbOperation			*MyOperation;
 
  ndbout << "Inserting records..."  << flush;
   
  MyTransaction = pMyNdb->startTransaction();
  if (MyTransaction == NULL)	  
    error_handler(pMyNdb->getNdbErrorString());
  
  MyOperation = MyTransaction->getNdbOperation("IPACCT");	
  if (MyOperation == NULL) 
    error_handler(MyTransaction->getNdbErrorString());
 

 
  check = MyOperation->insertTuple();
  if( check == -1 ) 
    error_handler(MyTransaction->getNdbErrorString());
  
  ndbout << "insertTuple"  << endl;  
  
  check = MyOperation->equal("CALLID",CALLID );
  if( check == -1 ) 
    error_handler(MyTransaction->getNdbErrorString());
  ndbout << "equal"  << endl;  
  

  check = MyOperation->equal("SPBBOARDID",SPBBOARDID );
  if( check == -1 ) 
    error_handler(MyTransaction->getNdbErrorString());
  ndbout << "equal"  << endl;  


  check = MyOperation->equal("IPADDR","IPADDR" );
  if( check == -1 ) 
    error_handler(MyTransaction->getNdbErrorString());
  ndbout << "equal"  << endl;  


  check = MyOperation->setValue( "IPQOS", IPQOS);
  if( check == -1 ) 
    error_handler(MyTransaction->getNdbErrorString());
  ndbout << "Set Value"  << endl;
  


  check = MyOperation->setValue( "ASID", ASID);
  if( check == -1 ) 
    error_handler(MyTransaction->getNdbErrorString());
  ndbout << "Set Value"  << endl;
  

  check = MyTransaction->execute( Commit ); 
  if(check == -1 ) {
    ndbout << "error at commit"  << endl;
    error_handler(MyTransaction->getNdbErrorString());
  }
  else
    ;//ndbout << ".";
  
  pMyNdb->closeTransaction(MyTransaction);
  
  
      
  ndbout << "OK" << endl;
  
  return;
}

static void  
update_rows(Ndb* pMyNdb){
 /****************************************************************
   *	Update rows in SimpleTable 	
   *
   ***************************************************************/

  int                   check;
  int                   loop_count_ops;
  int					count;
  int                   i;
  NdbConnection			*MyTransaction;
  NdbOperation			*MyOperation;

   ndbout << "Updating records..." << flush;
   
   loop_count_ops = NUMBEROFRECORDS;

   for (count=0 ; count < loop_count_ops ; count++)    {

      MyTransaction = pMyNdb->startTransaction();
      if (MyTransaction == NULL)
		  error_handler( pMyNdb->getNdbErrorString() );

      MyOperation = MyTransaction->getNdbOperation(tableName[0]);	
      if (MyOperation == NULL) 
        error_handler(MyTransaction->getNdbErrorString());

      check = MyOperation->updateTuple();
      if( check == -1 ) 
        error_handler(MyTransaction->getNdbErrorString());
	 
      check = MyOperation->equal( attrName[0], (char*)&pkValue[count] );
      if( check == -1 ) 
         error_handler(MyTransaction->getNdbErrorString());

      for (i = 1; i < MAXATTR; i++)
	{
          check = MyOperation->setValue( attrName[i], (char*)&attrValue[count]);
          if( check == -1 ) 
             error_handler(MyTransaction->getNdbErrorString());
	}

      if( MyTransaction->execute( Commit ) == -1 )
         error_handler(MyTransaction->getNdbErrorString());
      else
	;//ndbout << ".";
        
      pMyNdb->closeTransaction(MyTransaction);

    }

   ndbout << "OK" << endl;
  return;

};

static void  
delete_rows(Ndb* pMyNdb){

  /****************************************************************
   *	Delete rows from SimpleTable 	
   *
   ***************************************************************/

  int                   check;
  int                   loop_count_ops;
  int					count;
  NdbConnection			*MyTransaction;
  NdbOperation			*MyOperation;

   ndbout << "Deleting records..."<< flush;
   
   loop_count_ops = NUMBEROFRECORDS;

   for (count=0 ; count < loop_count_ops ; count++)    {

      MyTransaction = pMyNdb->startTransaction();
      if (MyTransaction == NULL)
		  error_handler( pMyNdb->getNdbErrorString() );

      MyOperation = MyTransaction->getNdbOperation(tableName[0]);	
      if (MyOperation == NULL) 
        error_handler(MyTransaction->getNdbErrorString());


      check = MyOperation->deleteTuple();
      if( check == -1 ) 
        error_handler(MyTransaction->getNdbErrorString());
	 
      check = MyOperation->equal( attrName[0], (char*)&pkValue[count] );
      if( check == -1 ) 
         error_handler(MyTransaction->getNdbErrorString());


      if( MyTransaction->execute( Commit ) == -1 )
         error_handler(MyTransaction->getNdbErrorString());
      else
	;// ndbout << ".";
        
      pMyNdb->closeTransaction(MyTransaction);

    }

   ndbout << "OK" << endl;
  return;

};

static void 
verify_deleted(Ndb* pMyNdb){
  int                   check;
  int                   loop_count_ops;
  int					count;
  NdbConnection			*MyTransaction;
  NdbOperation			*MyOperation;

  ndbout << "Verifying deleted records..."<< flush;
    
  loop_count_ops = NUMBEROFRECORDS;

  for (count=0 ; count < loop_count_ops ; count++)
  {
     MyTransaction = pMyNdb->startTransaction();
     if (MyTransaction == NULL)
        error_handler(pMyNdb->getNdbErrorString());

     MyOperation = MyTransaction->getNdbOperation(tableName[0]);	
     if (MyOperation == NULL) 
        error_handler( MyTransaction->getNdbErrorString());
       
     check = MyOperation->readTuple();
     if( check == -1 ) 
       error_handler( MyTransaction->getNdbErrorString());

     check = MyOperation->equal( attrName[0],(char*)&pkValue[count] );
     if( check == -1 ) 
        error_handler( MyTransaction->getNdbErrorString());

     // Exepect to receive an error
      if( MyTransaction->execute( Commit ) != -1 ) 
         error_handler(MyTransaction->getNdbErrorString());
      else
      {
        ;//ndbout << ".";
      }
     
      pMyNdb->closeTransaction(MyTransaction);

    }

   ndbout << "OK" << endl;
  return;
};

static void 
read_and_verify_rows(Ndb* pMyNdb)
{

  int                   check;
  int                   loop_count_ops;
  int					count;
  int                   count_attributes;

  NdbConnection			*MyTransaction;
  NdbOperation			*MyOperation;
  NdbRecAttr*           tTmp;

  int					readValue[MAXATTR];

  ndbout << "Verifying records..."<< flush;
    
  loop_count_ops = NUMBEROFRECORDS;

  for (count=0 ; count < loop_count_ops ; count++)
  {
     MyTransaction = pMyNdb->startTransaction();
     if (MyTransaction == NULL)
        error_handler(pMyNdb->getNdbErrorString());

     MyOperation = MyTransaction->getNdbOperation(tableName[0]);	
     if (MyOperation == NULL) 
        error_handler( MyTransaction->getNdbErrorString());
       
     check = MyOperation->readTuple();
     if( check == -1 ) 
        error_handler( MyTransaction->getNdbErrorString());

     check = MyOperation->equal( attrName[0],(char*)&pkValue[count] );
     if( check == -1 ) 
        error_handler( MyTransaction->getNdbErrorString());

     for (count_attributes = 1; count_attributes < MAXATTR; count_attributes++)
     {
        tTmp = MyOperation->getValue( (char*)attrName[count_attributes], (char*)&readValue[count_attributes] );
        if( tTmp == NULL ) 
           error_handler( MyTransaction->getNdbErrorString());
      }

      if( MyTransaction->execute( Commit ) == -1 ) 
         error_handler(MyTransaction->getNdbErrorString());
      else
      {
	// Check value in db against value in mem     

	//ndbout << readValue[1] << " == " << attrValue[count] << endl;
           
	   if ( readValue[1]!=attrValue[count] )
             error_handler("Verification error!");
           else
	   if ( readValue[2]!=attrValue[count] )
             error_handler("Verification error!");
           else
	   if ( readValue[3]!=attrValue[count] )
             error_handler("Verification error!");
           else
	   {
	     ;//ndbout << ".";
	   }
	}
        pMyNdb->closeTransaction(MyTransaction);

    }

   ndbout << "OK" << endl;
  return;

 

};


static void
setAttrNames()
{
  int i;

  for (i = 0; i < MAXATTR ; i++)
  {
    sprintf(&attrName[i][0], "Col%d", i);
  }
}

static void
setTableNames()
{
  int i;

  sprintf(&tableName[0][0], "SBMCALL", 0);
  sprintf(&tableName[1][0], "RPACCT", 0);
  sprintf(&tableName[2][0], "IPACCT", 0);
  sprintf(&tableName[3][0], "TODACCT", 0);

}


bool error_handler2(const char* error_string, int error_int) {
  failed++ ;
  ndbout << error_string << endl ;
  if ( 4008==error_int || 721==error_int || 266==error_int ){
    ndbout << endl << "Attempting to recover and continue now..." << endl ;
    return true ; // return true to retry
  }
  return false ; // return false to abort
}
