1 /*
2    Copyright (c) 2003, 2021, Oracle and/or its affiliates.
3     All rights reserved. Use is subject to license terms.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License, version 2.0,
7    as published by the Free Software Foundation.
8 
9    This program is also distributed with certain software (including
10    but not limited to OpenSSL) that is licensed under separate terms,
11    as designated in a particular file or component or in included license
12    documentation.  The authors of MySQL hereby grant you an additional
13    permission to link the program and your derivative works with the
14    separately licensed software that they have included with MySQL.
15 
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License, version 2.0, for more details.
20 
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24 */
25 
26 /* **************************************************************** */
27 /*                                                                  */
28 /*  S E R V . T C P                                                 */
29 /*  * This is an example program that demonstrates the use of       */
30 /*    stream sockets as an IPC mechanism. This contains the server, */
31 /*    and is intended to operate in conjunction with the client     */
32 /*    program found in client.tcp. Together, these two programs     */
33 /*    demonstrate many of the features of sockets, as well as good  */
34 /*    conventions for using these features.                         */
35 /*  * This program provides a service called "example". In order for*/
36 /*    it to function, an entry for it needs to exist in the         */
37 /*    ./etc/services file. The port address for this service can be */
38 /*    any port number that is likely to be unused, such as 22375,   */
39 /*    for example. The host on which the client will be running     */
40 /*    must also have the same entry (same port number) in its       */
41 /*    ./etc/services file.                                          */
42 /* **************************************************************** */
43 
44 #include <ndb_global.h>
45 
46 /******** NDB INCLUDE ******/
47 #include <NdbApi.hpp>
48 /***************************/
49 /*#include <sys/shm.h>*/
50 #include <pthread.h>
51 #include <sys/sem.h>
52 #include <sys/shm.h>
53 #include <netinet/in.h>
54 #include <signal.h>
55 #include <netdb.h>
56 #include <time.h>
57 #include <synch.h>
58 #include <sched.h>
59 
60 extern "C" {
61 #include "utv.h"
62 #include "vcdrfunc.h"
63 #include "bcd.h"
64 }
65 
66 #ifndef TESTLEV
67 #define TESTLEV
68 #endif
69 //#define DEBUG
70 //#define MYDEBUG
71 //#define SETDBG
72 
73 //#define ops_before_exe 64
74 #define MAXOPSEXEC 1024
75 
76 /* Used in nanosleep */
77 /**** NDB ********/
78 static  int bTestPassed;
79 void create_table(Ndb* pMyNdb);
80 void error_handler(const char* errorText);
81 /*****************/
82 static struct timespec tmspec1;
83 static int server(long int);
84 
85 /* Function for initiating the cdr-area and make it clean for ongoing calls */
86 
87 static int s;                          /* connected socket descriptor */
88 static int ls;                         /* listen socket descriptor */
89 
90 static struct hostent *hp;             /* pointer to host info for remote host */
91 static struct servent *sp;             /* pointer to service information */
92 
93 struct linger linger;           /* allow a lingering, graceful close; */
94                                 /* used when setting SO_LINGER */
95 
96 static struct sockaddr_in myaddr_in;   /* for local socket address */
97 static struct sockaddr_in peeraddr_in; /* for peer socket address */
98 
99 static FILE *fi;                       /* Log output */
100 static char temp[600]="";
101 
102 static int ops_before_exe = 1;  /* Number of operations per execute, default is 1,
103 				   but it can be changed with the -o parameter. */
104 
105 /*----------------------------------------------------------------------
106 
107      M A I N
108      * This routine starts the server. It forks, leaving the child
109      to do all the work, so it does not have to be run in the
110      background. It sets up the listen socket, and for each incoming
111      connection, it forks a child process to process the data. It
112      will loop forever, until killed by a signal.
113 
114   ----------------------------------------------------------------------*/
115 
116 /****** NDB *******/
117 static char *tableName = "VWTABLE";
118 /******************/
119 
120 #include <iostream>
121 using namespace std;
122 
main(int argc,const char ** argv)123 int main(int argc, const char** argv)
124 {
125   ndb_init();
126         /******** NDB ***********/
127 	/*
128         Ndb                   MyNdb( "TEST_DB" );
129         int                   tTableId;
130 	*/
131         /************************/
132 	char 	tmpbuf[400];
133 	/* Loop and status variables */
134 	int 		i,j,found;
135 
136 	/* Used by the server */
137         int 		addrlen;
138 
139 	/* return code used with functions */
140 	int 		rc;
141 
142   i = 1;
143   while (argc > 1)
144   {
145     if (strcmp(argv[i], "-o") == 0)
146     {
147       ops_before_exe = atoi(argv[i+1]);
148       if ((ops_before_exe < 1) || (ops_before_exe > MAXOPSEXEC))
149       {
150 	cout << "Number of operations per execute must be at least 1, and at most " << MAXOPSEXEC << endl;
151 	exit(1);
152       }
153 
154     }
155     else
156     {
157       cout << "Invalid parameter!" << endl << "Look in cdrserver.C for more info." << endl;
158       exit(1);
159     }
160 
161     argc -= 2;
162     i = i + 2;
163   }
164 
165 
166         /* Setup log handling */
167         logname(temp,"Cdrserver","Mother","");
168 	puts(temp);
169         fi=fopen(temp,"w");
170 	if (fi == NULL)
171 	{
172 		perror(argv[0]);
173 		exit(EXIT_FAILURE);
174 	}
175         m2log(fi,"Initiation of program");
176 
177         /***** NDB ******/
178 	/*
179         MyNdb.init();
180         if (MyNdb.waitUntilReady(30) != 0)
181         {
182                 puts("Not ready");
183                 exit(-1);
184         }
185         tTableId = MyNdb.getTable()->openTable(tableName);
186         if (tTableId == -1)
187         {
188                 printf("%d: Creating table",getpid());
189                 create_table(&MyNdb);
190         }
191 	else printf("%d: Table already create",getpid());
192 	*/
193 
194         /****************/
195 
196         /* clear out address structures */
197         memset ((char *)&myaddr_in, 0, sizeof(struct sockaddr_in));
198         memset ((char *)&peeraddr_in, 0, sizeof(struct sockaddr_in));
199 
200         m2log(fi,"Socket setup starting");
201 
202         /* Set up address structure for the listen socket. */
203         myaddr_in.sin_family = AF_INET;
204 
205         /* The server should listen on the wildcard address,            */
206         /*   rather than its own internet address. This is              */
207         /*   generally good practice for servers, because on            */
208         /*   systems which are connected to more than one               */
209         /*   network at once will be able to have one server            */
210         /*   listening on all networks at once. Even when the           */
211         /*   host is connected to only one network, this is good        */
212         /*   practice, because it makes the server program more         */
213         /*   portable.                                                  */
214 
215         myaddr_in.sin_addr.s_addr = INADDR_ANY;
216         /* Find the information for the "cdrserver" server              */
217         /*   in order to get the needed port number.                    */
218 
219         sp = getservbyname ("cdrserver", "tcp");
220         if (sp == NULL) {
221                 m2log(fi,"Service cdrserver not found in /etc/services");
222                 m2log(fi,"Terminating.");
223                 exit(EXIT_FAILURE);
224         }
225 
226         myaddr_in.sin_port = sp->s_port;
227 
228         /* Create the listen socket.i                                   */
229 
230         ls = socket (AF_INET, SOCK_STREAM, 0);
231         if (ls == -1) {
232                 m2log(fi,"Unable to create socket");
233                 m2log(fi,"Terminating.");
234                 exit(EXIT_FAILURE);
235         }
236         printf("Socket created\n");
237         printf("Wait..........\n");
238         /* Bind the listen address to the socket.                       */
239         if (bind(ls,(struct sockaddr*)&myaddr_in, sizeof(struct sockaddr_in)) == -1) {
240                 m2log(fi,"Unable to bind address");
241                 m2log(fi,"Terminating.");
242                 exit(EXIT_FAILURE);
243         }
244 
245         /* Initiate the listen on the socket so remote users            */
246         /*   can connect. The listen backlog is set to 5, which         */
247         /*   is the largest currently supported.                        */
248 
249         if (listen(ls, 5) == -1) {
250                 m2log(fi,"Unable to listen on socket");
251                 m2log(fi,"Terminating.");
252                 exit(EXIT_FAILURE);
253         }
254 
255         /* Now, all the initialization of the server is                 */
256         /*   complete, and any user errors will have already            */
257         /*   been detected. Now we can fork the daemon and              */
258         /*   return to the user. We need to do a setpgrp                */
259         /*   so that the daemon will no longer be associated            */
260         /*   with the user's control terminal. This is done             */
261         /*   before the fork, so that the child will not be             */
262         /*   a process group leader. Otherwise, if the child            */
263         /*   were to open a terminal, it would become associated        */
264         /*   with that terminal as its control terminal. It is          */
265         /*   always best for the parent to do the setpgrp.              */
266 
267         m2log(fi,"Socket setup completed");
268         m2log(fi,"Start server");
269 
270         setpgrp();
271 
272 	/* Initiate the tmspec struct for use with nanosleep() */
273         tmspec1.tv_sec = 0;
274         tmspec1.tv_nsec = 1;
275 
276 	printf("Waiting for client to connect.........\n");
277 	printf("Done\n");
278         switch (fork()) {
279            case -1: /* Unable to fork, for some reason. */
280                 m2log(fi,"Failed to start server");
281                 m2log(fi,"Terminating.");
282                 fclose(fi);
283                 perror(argv[0]);
284                 fprintf(stderr, "%s: unable to fork daemon\n", argv[0]);
285                 exit(EXIT_FAILURE);
286 
287 	   break;
288            case 0: /* The child process (daemon) comes here.            */
289                 m2log(fi,"Server started");
290 
291                /* Close stdin and stderr so that they will not          */
292                /*   be kept open. Stdout is assumed to have been        */
293                /*   redirected to some logging file, or /dev/null.      */
294                /*   From now on, the daemon will not report any         */
295                /*   error messages. This daemon will loop forever,      */
296                /*   waiting for connections and forking a child         */
297                /*   server to handle each one.                          */
298 
299                close((int)stdin);
300                close((int)stderr);
301                /* Set SIGCLD to SIG_IGN, in order to prevent            */
302                /*   the accumulation of zombies as each child           */
303                /*   terminates. This means the daemon does not          */
304                /*   have to make wait calls to clean them up.           */
305 
306                signal(SIGCLD, SIG_IGN);
307                for(EVER) {
308 			if ((checkchangelog(fi,temp))==0)
309                           m2log(fi,"Waiting for connection");
310                        /* Note that addrlen is passed as a pointer      */
311                        /*  so that the accept call can return the       */
312                        /*  size of the returned address.                */
313 
314                        addrlen = sizeof(struct sockaddr_in);
315 
316                        /* This call will block until a new              */
317                        /*   connection arrives. Then, it will           */
318                        /*   return the address of the connecting        */
319                        /*   peer, and a new socket descriptor, s,       */
320                        /*   for that connection.                        */
321 
322                         s = accept(ls,(struct sockaddr*) &peeraddr_in, &addrlen);
323 		       #ifdef MYDEBUG
324 			   puts("accepted");
325 		       #endif
326 			if ((checkchangelog(fi,temp))==0)
327                           m2log(fi,"Connection attempt from a client");
328 			if ((checkchangelog(fi,temp))==0)
329                           m2log(fi,"Start communication server");
330 
331                         if ( s == -1) exit(EXIT_FAILURE);
332                         switch (fork()) {
333                            case -1: /* Can't fork, just exit. */
334 				if ((checkchangelog(fi,temp))==0)
335                                   m2log(fi,"Start communication server failed.");
336                                 exit(EXIT_FAILURE);
337 			   break;
338                            case 0: /* Child process comes here. */
339 
340 				/* Get clients adress and save it in the info area */
341 				/* Keep track of how many times the client connects to the server */
342 				printf("Connect attempt from client %u\n",peeraddr_in.sin_addr.s_addr);
343                                 server(peeraddr_in.sin_addr.s_addr);
344                                 exit(EXIT_FAILURE);
345 			   break;
346                            default: /* Daemon process comes here. */
347                                 /* The daemon needs to remember         */
348                                 /*     to close the new accept socket   */
349                                 /*     after forking the child. This    */
350                                 /*     prevents the daemon from running */
351                                 /*     out of file descriptor space. It */
352                                 /*     also means that when the server  */
353                                 /*     closes the socket, that it will  */
354                                 /*     allow the socket to be destroyed */
355                                 /*     since it will be the last close. */
356                                 close(s);
357 			   break;
358                         }
359                }
360            default: /* Parent process comes here. */
361                exit(EXIT_FAILURE);
362        }
363   return EXIT_SUCCESS;
364 }
365 
366 /*----------------------------------------------------------------------
367 
368     S E R V E R
369     * This is the actual server routine that the daemon forks to
370       handle each individual connection. Its purpose is to receive
371       the request packets from the remote client, process them,
372       and return the results to the client. It will also write some
373       logging information to stdout.
374 
375   ----------------------------------------------------------------------*/
376 
server(long int servernum)377 server(long int servernum)
378 {
379 	/******** NDB ***********/
380   	Ndb                   MyNdb( "TEST_DB" );
381   	int                   tTableId;
382 	NdbConnection		*MyTransaction;
383 	NdbOperation		*MyOperation;
384 	int			check;
385 	int			c1 = 0;
386 	int			c2 = 0;
387 	int			c3 = 0;
388 	int			c4 = 0;
389 	int			act_index = 0;
390 	/************************/
391         register unsigned int   reqcnt;         /* keeps count of number of requests */
392         register unsigned int   i;          	/* Loop counters */
393 	register int		x;
394         register short          done;           /* Loop variable */
395 	short int		found;
396 
397 	/* The server index number */
398 	int 			thisServer;
399 
400 	/* Variables used to keep track of some statistics */
401 	time_t			ourtime;
402 	time_t			tmptime;
403 	int 			tmpvalue;
404 	long int		tmptransfer;
405 	long int		transfer;
406 	int			ops = 0;
407 
408 	/* Variables used by the server */
409         char    		buf[400];       /* This example uses 10 byte messages. */
410         char    		*inet_ntoa();
411         char    		*hostname;      /* points to the remote host's name string */
412         int     		len;
413         int     		rcvbuf_size;
414 
415 	long			ctid;
416 
417         unsigned char 		uc;
418 
419 	/* Variables used by the logging facilitiy */
420         char    		msg[600];
421         char    		crap[600];
422         char    		lognamn[600];
423 
424         FILE    		*log;
425 
426 	/* scheduling parameter for pthread */
427 	struct sched_param 	param1,param2,param3;
428 
429         /* Header information */
430 	/* cdrtype not used */
431         /*short           	cdrtype;   */   /* 1 CDR Typ                                            */
432         short           	cdrlen;         /* 2 CDR recored length in bytes excluding CDR type     */
433         short           	cdrsubtype;     /* 1 CDR subtype                                        */
434         unsigned int    	cdrid;          /* 8 CDR unique number of each call                     */
435         unsigned int    	cdrtime;        /* 4 CDR Time in seconds                                */
436         short           	cdrmillisec;    /* 2 CDR Milliseconds                                   */
437         short           	cdrstatus;      /* 1 CDR For future use                                 */
438         short           	cdrequipeid;    /* 1 CDR Equipment id                                   */
439         int             	cdrreserved1;   /* 4 CDR For future use                                 */
440 
441         /* Defined or calculated for each record */
442         int             	cdrrestlen;     /*   Unprocessed data left in record in bytes   */
443 
444         /* Gemensamma datatyper */
445         unsigned short  	parmtype_prev;  /* 1 Parameter type                                     */
446         unsigned short  	parmtype;       /* 1 Parameter type                                     */
447         unsigned short  	parmlen;        /* 1 Parameter type                                     */
448 
449 	int			rc;		/* return code for functions */
450 
451 	/* Attribute object used with threads */
452 	pthread_attr_t 		attr1;
453 	pthread_attr_t 		attr2;
454 	pthread_attr_t 		attr3;
455 	struct cdr_record	*tmpcdrptr,*ftest;
456 	void			*dat;
457 
458 	int			error_from_client = 0;
459 
460         /* Konstanter           */
461         const int       	headerlen = 24;         /*   Length of header record                    */
462 
463         parmtype_prev = 99;
464 	reqcnt = 0;
465 
466         /* Close the listen socket inherited from the daemon. */
467         close(ls);
468 
469 	printf("Use the readinfo program to get information about server status\n\n");
470 
471 	if((checkchangelog(fi,temp))==0)
472           c2log(fi,"Communication server started");
473 
474         /* Look up the host information for the remote host     */
475         /* that we have connected with. Its internet address    */
476         /* was returned by the accept call, in the main         */
477         /* daemon loop above.                                   */
478 
479         hp=gethostbyaddr((char *) &peeraddr_in.sin_addr,sizeof(struct in_addr),peeraddr_in.sin_family);
480 
481         if (hp == NULL) {
482                 /* The information is unavailable for the remote        */
483                 /* host. Just format its internet address to be         */
484                 /* printed out in the logging information. The          */
485                 /* address will be shown in "internet dot format".      */
486 
487 		/*
488                 hostname = inet_ntoa(peeraddr_in.sin_addr);
489 		*/
490 		sprintf(hostname,"Test");
491                 logname(lognamn,"Cdrserver","Child",hostname);
492         }
493         else {
494                 hostname = hp->h_name; /* point to host's name */
495                 logname(lognamn,"Cdrserver","Child",hostname);
496         }
497 
498         log=fopen(lognamn,"w");
499 	if (log == NULL)
500 	{
501 		perror(hostname);
502 		exit(EXIT_FAILURE);
503 	}
504         n2log(log,"Setup in progress");
505         /* Log a startup message. */
506 
507         /* The port number must be converted first to host byte */
508         /* order before printing. On most hosts, this is not    */
509         /* necessary, but the ntohs() call is included here so  */
510         /* that this program could easily be ported to a host   */
511         /* that does require it.                                */
512 
513         BaseString::snprintf(msg,sizeof(msg),"Startup from %s port %u",hostname,ntohs(peeraddr_in.sin_port));
514 	if ((checkchangelog(fi,temp))==0)
515           c2log(fi,msg);
516         n2log(log,msg);
517         BaseString::snprintf(msg,sizeof(msg),"For further information, see log(%s)",lognamn);
518 	if ((checkchangelog(fi,temp))==0)
519           c2log(fi,msg);
520 
521         /* Set the socket for a lingering, graceful close.              */
522         /* This will cause a final close of this socket to wait until   */
523         /* all * data sent on it has been received by the remote host.  */
524 
525         linger.l_onoff  =1;
526         linger.l_linger =0;
527         if (setsockopt(s, SOL_SOCKET, SO_LINGER,(const char*)&linger,sizeof(linger)) == -1) {
528                 BaseString::snprintf(msg,sizeof(msg),"Setting SO_LINGER, l_onoff=%d, l_linger=%d",linger.l_onoff,linger.l_linger);
529 		if ((checkchangelog(log,lognamn))==0)
530           		n2log(log,msg);
531                 goto errout;
532         }
533 
534         /* Set the socket for a lingering, graceful close.                              */
535         /* This will cause a final close of this socket to wait until all * data sent   */
536         /* on it has been received by the remote host.                                  */
537 
538         rcvbuf_size=64*1024;
539 
540         if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,(const char*) &rcvbuf_size,sizeof(rcvbuf_size)) == -1) {
541                 BaseString::snprintf(msg,sizeof(msg),"Setting SO_RCVBUF = %d",rcvbuf_size);
542 		if ((checkchangelog(log,lognamn))==0)
543           		n2log(log,msg);
544                 goto errout;
545         }
546 
547         /* Set nodelay on socket */
548         n2log(log,"Port setup complete");
549 
550         /* Go into a loop, receiving requests from the remote           */
551         /* client. After the client has sent the last request,          */
552         /* it will do a shutdown for sending, which will cause          */
553         /* an end-of-file condition to appear on this end of the        */
554         /* connection. After all of the client's requests have          */
555         /* been received, the next recv call will return zero           */
556         /* bytes, signalling an end-of-file condition. This is          */
557         /* how the server will know that no more requests will          */
558         /* follow, and the loop will be exited.                         */
559 
560         n2log(log,"Setup completed");
561 
562 	/* Fetch the process id for the server */
563 
564 	/* Inititate the variables used for counting transfer rates and rec/sec */
565 	tmpvalue    = 0;
566 	tmptime     = 0;
567 	tmptransfer = 0;
568 	transfer = 0;
569 
570 	printf("Client %s connected\nStarting to process the data\n\n",hostname);
571 
572 	tmpcdrptr = (struct cdr_record*)malloc(sizeof(struct cdr_record));
573 
574 	/***** NDB ******/
575 	MyNdb.init();
576 	if (MyNdb.waitUntilReady(30) != 0)
577 	{
578 		puts("Not ready");
579 		exit(-1);
580 	}
581 	tTableId = MyNdb.getTable()->openTable(tableName);
582       	if (tTableId == -1)
583 	{
584 		printf("%d: Creating table",getpid());
585         	create_table(&MyNdb);
586 	}
587 	else printf("%d: Table already created",getpid());
588 
589 	/****************/
590 
591         while (len = recv(s,buf,headerlen,MSG_WAITALL)) {
592                 if (len == -1) {
593         		snprintf(msg,sizeof(msg),"Error from recv");
594 			if ((checkchangelog(log,lognamn))==0)
595           			n2log(log,msg);
596                         goto errout; /* error from recv */
597                 }
598 
599                 /* The reason this while loop exists is that there              */
600                 /* is a remote possibility of the above recv returning          */
601                 /* less than 10 bytes. This is because a recv returns           */
602                 /* as soon as there is some data, and will not wait for         */
603                 /* all of the requested data to arrive. Since 10 bytes          */
604                 /* is relatively small compared to the allowed TCP              */
605                 /* packet sizes, a partial receive is unlikely. If              */
606                 /* this example had used 2048 bytes requests instead,           */
607                 /* a partial receive would be far more likely.                  */
608                 /* This loop will keep receiving until all 10 bytes             */
609                 /* have been received, thus guaranteeing that the               */
610                 /* next recv at the top of the loop will start at               */
611                 /* the begining of the next request.                            */
612 
613                 for (;len < headerlen;) {
614                         x = recv(s,buf,(headerlen-len),0);
615                         if (x == -1) {
616         			snprintf(msg,sizeof(msg),"Error from recv");
617 				if ((checkchangelog(log,lognamn))==0)
618           				n2log(log,msg);
619                                 goto errout; /* error from recv */
620                         }
621                         len=len+x;
622                 }
623 
624                 if (ops == 0) {
625             	  MyTransaction = MyNdb.startTransaction();
626         	  if (MyTransaction == NULL)
627         		error_handler(MyNdb.getNdbErrorString());
628                 }//if
629 
630       		MyOperation = MyTransaction->getNdbOperation(tableName);
631       		if (MyOperation == NULL)
632         		error_handler(MyTransaction->getNdbErrorString());
633                 /*------------------------------------------------------*/
634                 /* Parse header of CDR records                          */
635                 /*------------------------------------------------------*/
636 
637                 /*------------------------------------------------------*/
638                 /* 1. Type of cdr                                       */
639                 /*------------------------------------------------------*/
640 		/* Not used for the moment
641                 cdrtype=(char)buf[0];
642 		*/
643                 /*------------------------------------------------------*/
644                 /* 2. Total length of CDR                               */
645                 /*------------------------------------------------------*/
646                 swab(buf+1,buf+1,2);
647                 memcpy(&cdrlen,buf+1,2);
648                 /*------------------------------------------------------*/
649                 /* 3. Partial type of CDR                               */
650                 /*------------------------------------------------------*/
651                 cdrsubtype=(char)buf[3];
652 		switch (cdrsubtype)
653 		{
654 			case 0:
655 			c1++;
656 			tmpcdrptr->CallAttemptState = 1;
657 			check = MyOperation->insertTuple();
658 			break;
659 			case 1:
660 			c2++;
661 			tmpcdrptr->CallAttemptState = 2;
662 			check = MyOperation->updateTuple();
663 			break;
664 			case 2:
665 			c3++;
666 			tmpcdrptr->CallAttemptState = 3;
667 			check = MyOperation->deleteTuple();
668 			break;
669 			case 3:
670 			c4++;
671 			tmpcdrptr->CallAttemptState = 4;
672 			check = MyOperation->deleteTuple();
673 			break;
674 			if (check == -1)
675 				error_handler(MyTransaction->getNdbErrorString());
676 		}
677                 /*cdrsubtype=(cdrsubtype << 24) >> 24;*/
678                 /*------------------------------------------------------*/
679                 /* 4. ID number                                         */
680                 /*------------------------------------------------------*/
681                 /*swab(buf+4,buf+4,4);*/ /* ABCD -> BADC */
682 		/*
683                 swab(buf+4,buf+4,4);
684                 swab(buf+5,buf+5,2);
685                 swab(buf+6,buf+6,2);
686                 swab(buf+4,buf+4,2);
687                 swab(buf+5,buf+5,2);
688 		*/
689                 memcpy(&cdrid,buf+4,4);
690 		tmpcdrptr->CallIdentificationNumber = cdrid;
691 		#ifdef SETDBG
692 			puts("CIN");
693 		#endif
694 		check = MyOperation->equal("CIN",(char*)&cdrid);
695 		if (check == -1)
696 			error_handler(MyTransaction->getNdbErrorString());
697 		#ifdef SETDBG
698 			puts("CAS");
699 		#endif
700 
701 		if (cdrsubtype < 2)
702 		{
703 			check = MyOperation->setValue("CAS",(char*)&cdrsubtype);
704 			if (check == -1)
705 				error_handler(MyTransaction->getNdbErrorString());
706 		}
707                 /*------------------------------------------------------*/
708                 /* 5. Time stamp                                        */
709                 /*------------------------------------------------------*/
710                 swab(buf+12,buf+12,4);
711                 swab(buf+13,buf+13,2);
712                 swab(buf+14,buf+14,2);
713                 swab(buf+12,buf+12,2);
714                 swab(buf+13,buf+13,2);
715                 memcpy(&cdrtime,buf+12,4);
716 		switch (cdrsubtype)
717 		{
718 			case 0:
719 			#ifdef SETDBG
720 				puts("START_TIME");
721 			#endif
722 			check = MyOperation->setValue("START_TIME",(char*)&cdrtime);
723 			break;
724 			case 1:
725 			#ifdef SETDBG
726 				puts("Start1");
727 			#endif
728 			check = MyOperation->setValue("StartOfCharge",(char*)&cdrtime);
729 			break;
730 			case 2:
731 			#ifdef SETDBG
732 				puts("Start2");
733 			#endif
734 			/*
735 			check = MyOperation->setValue("StopOfCharge",(char*)&cdrtime);
736 			*/
737 			check = 0;
738 			break;
739 			if (check == -1)
740 				error_handler(MyTransaction->getNdbErrorString());
741 		}
742                 /*------------------------------------------------------*/
743                 /* 6. Milliseconds                                      */
744                 /*------------------------------------------------------*/
745 		/* Not used by application
746                 swab(buf+16,buf+16,2);
747                 memcpy(&cdrmillisec,buf+16,2);
748 		*/
749                 /*------------------------------------------------------*/
750                 /* 7. CDR status reserverd for future use               */
751                 /*------------------------------------------------------*/
752 		/* Not used by application
753                 memcpy(&cdrstatus,buf+18,1);
754 		*/
755                 /*------------------------------------------------------*/
756                 /* 8. CDR equipe id, number of sending equipement       */
757                 /*------------------------------------------------------*/
758 		/* Not used by application
759                 memcpy(&cdrequipeid,buf+19,1);
760 		*/
761                 /*cdrequipeid=(cdrequipeid << 24) >> 24;*/
762                 /*------------------------------------------------------*/
763                 /* 9. CDR reserverd for furter use                      */
764                 /*------------------------------------------------------*/
765 		/* Not used by applikation
766                 swab(buf+20,buf+20,4);
767                 swab(buf+21,buf+21,2);
768                 swab(buf+22,buf+22,2);
769                 swab(buf+20,buf+20,2);
770                 swab(buf+21,buf+21,2);
771                 memcpy(&cdrreserved1,buf+20,4);
772 		*/
773                 /*------------------------------------------------------*/
774                 /* calculate length of datapart in record               */
775                 /* Formula recordlength-headerlen-1                     */
776                 /*------------------------------------------------------*/
777                 cdrrestlen=cdrlen-(headerlen-1);
778                 /*------------------------------------------------------*/
779                 /* Finished with header                                 */
780                 /*------------------------------------------------------*/
781                 /* Read remaining cdr data into buffer for furter       */
782                 /* handling.                                            */
783                 /*------------------------------------------------------*/
784                 len = recv(s,buf,cdrrestlen,MSG_WAITALL);
785                 if (len == -1) {
786         		snprintf(msg,sizeof(msg),"Error from recv");
787 			if ((checkchangelog(log,lognamn))==0)
788           			n2log(log,msg);
789                         goto errout; /* error from recv */
790                 }
791                 for (;len<cdrrestlen;) {
792                         x = recv(s,buf,len-cdrrestlen,0);
793                         if (x == -1) {
794         			snprintf(msg,sizeof(msg),"Error from recv");
795 				if ((checkchangelog(log,lognamn))==0)
796           				n2log(log,msg);
797                                 goto errout; /* error from recv */
798                         }
799                         len=len+x;
800                 }
801                 done=FALSE;
802 
803 		/* Count the transfer/sec */
804 		tmptransfer += cdrlen;
805 		if (cdrsubtype > 1)
806 		{
807 				#ifdef SETDBG
808 					puts("Going to execute");
809 				#endif
810                                 ops++;
811                                 if (ops == ops_before_exe) {
812                                   ops = 0;
813                 		  check = MyTransaction->execute(Commit, CommitAsMuchAsPossible);
814                 		  if ((check == -1) && (MyTransaction->getNdbError() != 0))
815                         		error_handler(MyTransaction->getNdbErrorString());
816                 		  MyNdb.closeTransaction(MyTransaction);
817 				  #ifdef SETDBG
818 					puts("Transaction closed");
819 				  #endif
820                                 }//if
821 			reqcnt++;
822 			continue;
823 		}
824                 for (x=0;x<=cdrrestlen && !done && cdrrestlen > 1;) {
825                         uc=buf[x];
826                         parmtype=uc;
827                         /*parmtype=(parmtype << 24) >> 24;*/ /* Modified in sun worked in hp */
828 
829                         parmlen = buf[x+1];
830                         /*parmlen =(parmlen << 24) >> 24;*/
831                         x+=2;
832 
833                         switch (parmtype) {
834                                 case 4:         /* Called party number */
835                                         bcd_decode2(parmlen,&buf[x],crap);
836 					tmpcdrptr->BSubscriberNumberLength = (char)parmlen;
837                                         strcpy(tmpcdrptr->BSubscriberNumber,crap);
838 					tmpcdrptr->BSubscriberNumber[parmlen] = '\0';
839                                         x=x+(parmlen/2);
840                                         if (parmlen % 2) x++;
841                                         tmpcdrptr->USED_FIELDS |=  B_BSubscriberNumber;
842 					#ifdef SETDBG
843 						puts("BNumber");
844 					#endif
845 					check = MyOperation->setValue("BNumber",(char*)&tmpcdrptr->BSubscriberNumber);
846 					if (check == -1)
847 						error_handler(MyTransaction->getNdbErrorString());
848                                 break;
849                                 case 9:         /* Calling Partys cataegory */
850                                         if (parmlen != 1) printf("ERROR: Calling partys category has wrong length %d\n",parmlen);
851                                         else tmpcdrptr->ACategory=(char)buf[x];
852                                         x+=parmlen;
853                                         tmpcdrptr->USED_FIELDS |= B_ACategory;
854 					#ifdef SETDBG
855 						puts("ACategory");
856 					#endif
857 					check = MyOperation->setValue("ACategory",(char*)&tmpcdrptr->ACategory);
858 					if (check == -1)
859 						error_handler(MyTransaction->getNdbErrorString());
860                                 break;
861                                 case 10:        /* Calling Party Number */
862                                         bcd_decode2(parmlen,&buf[x],crap);
863 					tmpcdrptr->ASubscriberNumberLength = (char)parmlen;
864                                         strcpy(tmpcdrptr->ASubscriberNumber,crap);
865 					tmpcdrptr->ASubscriberNumber[parmlen] = '\0';
866                                         x=x+(parmlen/2);
867                                         if (parmlen % 2) x++;
868                                         tmpcdrptr->USED_FIELDS |= B_ASubscriberNumber;
869 					#ifdef SETDBG
870 						puts("ANumber");
871 					#endif
872 					check = MyOperation->setValue("ANumber",(char*)&tmpcdrptr->ASubscriberNumber);
873 					if (check == -1)
874 						error_handler(MyTransaction->getNdbErrorString());
875                                 break;
876                                 case 11:        /* Redirecting number */
877                                         bcd_decode2(parmlen,&buf[x],crap);
878                                         strcpy(tmpcdrptr->RedirectingNumber,crap);
879                                         x=x+(parmlen/2);
880                                         if (parmlen % 2) x++;
881                                         tmpcdrptr->USED_FIELDS |= B_RedirectingNumber;
882 					#ifdef SETDBG
883 						puts("RNumber");
884 					#endif
885 					check = MyOperation->setValue("RNumber",(char*)&tmpcdrptr->RedirectingNumber);
886 					if (check == -1)
887 						error_handler(MyTransaction->getNdbErrorString());
888                                 break;
889                                 case 17:        /* Called partys category */
890                                         if (parmlen != 1) printf("ERROR: Called partys category has wrong length %d\n",parmlen);
891                                         else tmpcdrptr->EndOfSelectionInformation=(char)buf[x];
892                                         x+=parmlen;
893                                         tmpcdrptr->USED_FIELDS |= B_EndOfSelectionInformation;
894 					#ifdef SETDBG
895 						puts("EndOfSelInf");
896 					#endif
897 					check = MyOperation->setValue("EndOfSelInf",(char*)&tmpcdrptr->EndOfSelectionInformation);
898 					if (check == -1)
899 						error_handler(MyTransaction->getNdbErrorString());
900                                 break;
901                                 case 18:        /* Release reason */
902                                         if (parmlen != 1) printf("ERROR: Release reason has wrong length %d\n",parmlen);
903                                         else tmpcdrptr->CauseCode=(char)buf[x];
904                                         x+=parmlen;
905                                         tmpcdrptr->USED_FIELDS |= B_CauseCode;
906 					#ifdef SETDBG
907 						puts("CauseCode");
908 					#endif
909 					check = MyOperation->setValue("CauseCode",(char*)&tmpcdrptr->CauseCode);
910 					if (check == -1)
911 						error_handler(MyTransaction->getNdbErrorString());
912                                 break;
913                                 case 19:        /* Redirection information */
914                                         switch (parmlen) {
915                                                 case 1:
916                                                         tmpcdrptr->ReroutingIndicator= (char)buf[x];
917                                                         tmpcdrptr->USED_FIELDS |= B_ReroutingIndicator;
918                                                 break;
919                                                 case 2:
920                                                         swab(buf+x,buf+x,2);
921                                                         tmpcdrptr->ReroutingIndicator= buf[x];
922                                                         tmpcdrptr->USED_FIELDS |= B_ReroutingIndicator;
923                                                 break;
924                                                 default :
925                                                         BaseString::snprintf(msg,sizeof(msg),"ERROR: Redirection information has wrong length %d\n",parmlen);
926 	  						if ((checkchangelog(log,lognamn))==0)
927                                                           n2log(log,msg);
928                                                 break;
929 						#ifdef SETDBG
930 							puts("RI");
931 						#endif
932 						check = MyOperation->setValue("RI",(char*)&tmpcdrptr->ReroutingIndicator);
933 						if (check == -1)
934 							error_handler(MyTransaction->getNdbErrorString());
935                                         }
936                                         x+=parmlen;
937                                 break;
938                                 case 32:        /* User to user information */
939                                         if (parmlen != 1) printf("ERROR: User to User information has wrong length %d\n",parmlen);
940                                         else tmpcdrptr->UserToUserInformation=(char)buf[x];
941                                         x+=parmlen;
942                                         tmpcdrptr->USED_FIELDS |= B_UserToUserInformation;
943 					#ifdef SETDBG
944 						puts("UserToUserInf");
945 					#endif
946 					check = MyOperation->setValue("UserToUserInf",(char*)&tmpcdrptr->UserToUserInformation);
947 					if (check == -1)
948 						error_handler(MyTransaction->getNdbErrorString());
949                                 break;
950                                 case 40:        /* Original called number */
951                                         bcd_decode2(parmlen,&buf[x],crap);
952                                         strcpy(tmpcdrptr->OriginalCalledNumber,crap);
953                                         x=x+(parmlen/2);
954                                         if (parmlen % 2) x++;
955                                         tmpcdrptr->USED_FIELDS |= B_OriginalCalledNumber;
956 					#ifdef SETDBG
957 						puts("ONumber");
958 					#endif
959 					check = MyOperation->setValue("ONumber",(char*)&tmpcdrptr->OriginalCalledNumber);
960 					if (check == -1)
961 						error_handler(MyTransaction->getNdbErrorString());
962                                 break;
963                                 case 42:        /* User to user indicator */
964                                         if (parmlen != 1) printf("ERROR: User to User indicator has wrong length %d\n",parmlen);
965                                         else tmpcdrptr->UserToUserIndicatior=(char)buf[x];
966                                         x+=parmlen;
967                                         tmpcdrptr->USED_FIELDS |= B_UserToUserIndicatior;
968 					#ifdef SETDBG
969 						puts("UserToUserInd");
970 					#endif
971 					check = MyOperation->setValue("UserToUserInd",(char*)&tmpcdrptr->UserToUserIndicatior);
972 					if (check == -1)
973 						error_handler(MyTransaction->getNdbErrorString());
974                                 break;
975                                 case 63:        /* Location number */
976                                         bcd_decode2(parmlen,&buf[x],crap);
977                                         strcpy(tmpcdrptr->LocationCode,crap);
978                                         x=x+(parmlen/2);
979                                         if (parmlen % 2) x++;
980                                         tmpcdrptr->USED_FIELDS |= B_LocationCode;
981 					#ifdef SETDBG
982 						puts("LocationCode");
983 					#endif
984 					check = MyOperation->setValue("LocationCode",(char*)&tmpcdrptr->LocationCode);
985 					if (check == -1)
986 						error_handler(MyTransaction->getNdbErrorString());
987                                 break;
988                                 case 240:       /* Calling Partys cataegory */
989                                         if (parmlen != 1) printf("ERROR: Calling partys category has wrong length %d\n",parmlen);
990                                         else tmpcdrptr->NetworkIndicator=(char)buf[x];
991                                         x+=parmlen;
992                                         tmpcdrptr->USED_FIELDS |= B_NetworkIndicator;
993 					#ifdef SETDBG
994 						puts("NIndicator");
995 					#endif
996 					check = MyOperation->setValue("NIndicator",(char*)&tmpcdrptr->NetworkIndicator);
997 					if (check == -1)
998 						error_handler(MyTransaction->getNdbErrorString());
999                                 break;
1000                                 case 241:       /* Calling Partys cataegory */
1001                                         if (parmlen != 1) printf("ERROR: Calling partys category has wrong length %d\n",parmlen);
1002                                         else tmpcdrptr->TonASubscriberNumber=(char)buf[x];
1003                                         x+=parmlen;
1004                                         tmpcdrptr->USED_FIELDS |= B_TonASubscriberNumber;
1005 					#ifdef SETDBG
1006 						puts("TonANumber");
1007 					#endif
1008 					check = MyOperation->setValue("TonANumber",(char*)&tmpcdrptr->TonASubscriberNumber);
1009 					if (check == -1)
1010 						error_handler(MyTransaction->getNdbErrorString());
1011                                 break;
1012                                 case 242:       /* Calling Partys cataegory */
1013                                         if (parmlen != 1) printf("ERROR: Calling partys category has wrong length %d\n",parmlen);
1014                                         else tmpcdrptr->TonBSubscriberNumber=(char)buf[x];
1015                                         x+=parmlen;
1016                                         tmpcdrptr->USED_FIELDS |= B_TonBSubscriberNumber;
1017 					#ifdef SETDBG
1018 						puts("TonBNumber");
1019 					#endif
1020 					check = MyOperation->setValue("TonBNumber",(char*)&tmpcdrptr->TonBSubscriberNumber);
1021 					if (check == -1)
1022 						error_handler(MyTransaction->getNdbErrorString());
1023                                 break;
1024                                 case 243:       /* Calling Partys cataegory */
1025                                         if (parmlen != 1) printf("ERROR: Calling partys category has wrong length %d\n",parmlen);
1026                                         else tmpcdrptr->TonRedirectingNumber=(char)buf[x];
1027                                         x+=parmlen;
1028                                         tmpcdrptr->USED_FIELDS |= B_TonRedirectingNumber;
1029 					#ifdef SETDBG
1030 						puts("TonRNumber");
1031 					#endif
1032 					check = MyOperation->setValue("TonRNumber",(char*)&tmpcdrptr->TonRedirectingNumber);
1033 					if (check == -1)
1034 						error_handler(MyTransaction->getNdbErrorString());
1035                                 break;
1036                                 case 244:       /* Calling Partys cataegory */
1037                                         if (parmlen != 1) printf("ERROR: Calling partys category has wrong length %d\n",parmlen);
1038                                         else tmpcdrptr->TonOriginalCalledNumber=(char)buf[x];
1039                                         x+=parmlen;
1040                                         tmpcdrptr->USED_FIELDS |= B_TonOriginalCalledNumber;
1041 					#ifdef SETDBG
1042 						puts("TonONumber");
1043 					#endif
1044 					check = MyOperation->setValue("TonONumber",(char*)&tmpcdrptr->TonOriginalCalledNumber);
1045 					if (check == -1)
1046 						error_handler(MyTransaction->getNdbErrorString());
1047                                 break;
1048                                 case 245:       /* Calling Partys cataegory */
1049                                         if (parmlen != 1) printf("ERROR: Calling partys category has wrong length %d\n",parmlen);
1050                                         else tmpcdrptr->TonLocationCode=(char)buf[x];
1051                                         x+=parmlen;
1052                                         tmpcdrptr->USED_FIELDS |= B_TonLocationCode;
1053 					#ifdef SETDBG
1054 						puts("TonLocationCode");
1055 					#endif
1056 					check = MyOperation->setValue("TonLocationCode",(char*)&tmpcdrptr->TonLocationCode);
1057 					if (check == -1)
1058 						error_handler(MyTransaction->getNdbErrorString());
1059                                 break;
1060                                 case 252:       /* RINParameter Parameter */
1061                                         switch (parmlen) {
1062                                                 case 1:
1063                                                         tmpcdrptr->RINParameter=buf[x];
1064                                                         tmpcdrptr->USED_FIELDS |= B_RINParameter;
1065                                                 break;
1066                                                 case 2:
1067                                                         swab(buf+x,buf+x,2);
1068                                                         tmpcdrptr->RINParameter = buf[x] << 8;
1069                                                         tmpcdrptr->USED_FIELDS |= B_RINParameter;
1070                                                 break;
1071                                                 default :
1072                                                         BaseString::snprintf(msg,sizeof(msg),"ERROR: Rin parameter has wrong length %d\n",parmlen);
1073 	  						if ((checkchangelog(log,lognamn))==0)
1074                                                           n2log(log,msg);
1075                                                 break;
1076                                         }
1077                                         x+=parmlen;
1078 					#ifdef SETDBG
1079 						puts("RINParameter");
1080 					#endif
1081 					check = MyOperation->setValue("RINParameter",(char*)&tmpcdrptr->RINParameter);
1082 					if (check == -1)
1083 						error_handler(MyTransaction->getNdbErrorString());
1084                                 break;
1085                                 case 253:       /* OriginatingPointCode */
1086                                         switch (parmlen) {
1087                                                 case 2:
1088                                                         swab(buf+x,buf+x,2);
1089                                                         memcpy(&tmpcdrptr->OriginatingPointCode,(buf+x),2);
1090                                                         tmpcdrptr->USED_FIELDS |= B_OriginatingPointCode;
1091                                                 break;
1092                                                 case 3:
1093                                                         swab(buf+x,buf+x,2);
1094                                                         swab(buf+(x+1),buf+(x+1),2);
1095                                                         swab(buf+x,buf+x,2);
1096                                                         memcpy(&tmpcdrptr->OriginatingPointCode,(buf+x),3);
1097                                                         tmpcdrptr->USED_FIELDS |= B_OriginatingPointCode;
1098                                                 break;
1099                                                 default :
1100                                                         BaseString::snprintf(msg,sizeof(msg),"ERROR: OriginatingPointCode parameter has wrong length %d\n",parmlen);
1101 	  						if ((checkchangelog(log,lognamn))==0)
1102                                                           n2log(log,msg);
1103                                                 break;
1104                                         }
1105                                         x+=parmlen;
1106 					#ifdef SETDBG
1107 						puts("OPC");
1108 					#endif
1109 					check = MyOperation->setValue("OPC",(char*)&tmpcdrptr->OriginatingPointCode);
1110 					if (check == -1)
1111 						error_handler(MyTransaction->getNdbErrorString());
1112                                 break;
1113                                 case 254:       /* DestinationPointCode */
1114                                         switch (parmlen) {
1115                                                 case 2:
1116                                                         swab(buf+x,buf+x,2);
1117                                                         memcpy(&tmpcdrptr->DestinationPointCode,(buf+x),2);
1118 							/*
1119                                                         tmpcdrptr->DestinationPointCode = buf[x] << 8;
1120 							*/
1121                                                         tmpcdrptr->USED_FIELDS |= B_DestinationPointCode;
1122                                                 break;
1123                                                 case 3:
1124                                                         swab(buf+x,buf+x,2);
1125                                                         swab(buf+(x+1),buf+(x+1),2);
1126                                                         swab(buf+x,buf+x,2);
1127                                                         memcpy(&tmpcdrptr->DestinationPointCode,(buf+x),3);
1128                                                         tmpcdrptr->USED_FIELDS |= B_DestinationPointCode;
1129                                                 break;
1130                                                 default :
1131                                                         BaseString::snprintf(msg,sizeof(msg),"ERROR: DestinationPointCode parameter has wrong length %d\n",parmlen);
1132 	  						if ((checkchangelog(log,lognamn))==0)
1133                                                           n2log(log,msg);
1134                                                 break;
1135                                         }
1136                                         x+=parmlen;
1137 					#ifdef SETDBG
1138 						puts("DPC");
1139 					#endif
1140 					check = MyOperation->setValue("DPC",(char*)&tmpcdrptr->DestinationPointCode);
1141 					if (check == -1)
1142 						error_handler(MyTransaction->getNdbErrorString());
1143                                 break;
1144                                 case 255:       /* CircuitIdentificationCode */
1145                                         swab(buf+x,buf+x,2);
1146                                         memcpy(&tmpcdrptr->CircuitIdentificationCode,(buf+x),2);
1147                                         tmpcdrptr->USED_FIELDS |= B_CircuitIdentificationCode;
1148                                         x+=parmlen;
1149 					#ifdef SETDBG
1150 						puts("CIC");
1151 					#endif
1152 					check = MyOperation->setValue("CIC",(char*)&tmpcdrptr->CircuitIdentificationCode);
1153 					if (check == -1)
1154 						error_handler(MyTransaction->getNdbErrorString());
1155                                 break;
1156                                 default:
1157                                         printf("ERROR: Undefined parmtype %d , previous %d, length %d\n",parmtype,parmtype_prev,parmlen);
1158                                         BaseString::snprintf(msg,sizeof(msg),"ERROR: Undefined parmtype %d , previous %d, length %d\n",parmtype,parmtype_prev,parmlen);
1159 	  				if ((checkchangelog(log,lognamn))==0)
1160                                           n2log(log,msg);
1161                                         if (parmlen == 0) {
1162                                                 x++;
1163                                         }
1164                                         x+=parmlen;
1165                                 break;
1166                         }
1167                         parmtype_prev=parmtype;
1168                         if ((cdrrestlen-x) == 1) {
1169                                 done=TRUE;
1170                         }
1171                 }
1172 		time(&ourtime);
1173 		if (ourtime != tmptime)
1174 		{
1175 			transfer = tmptransfer;
1176 			tmptransfer = 0;
1177 			if (++act_index == 30)
1178 			{
1179 				act_index = 0;
1180 				printf("Transfer=%d\n",transfer);
1181 				printf("Total operations=%d\n",reqcnt);
1182 				printf("CAS1=%d\n",c1/30);
1183 				printf("CAS2=%d\n",c2/30);
1184 				printf("CAS3=%d\n",c3/30);
1185 				c1=0;
1186 				c2=0;
1187 				c3=0;
1188 			}
1189 			tmptime = ourtime;
1190 		}
1191                 switch (cdrsubtype) {
1192                         case 0:
1193                                 tmpcdrptr->ClientId = servernum;
1194 				#ifdef SETDBG
1195 					puts("ClientId");
1196 				#endif
1197 				check = MyOperation->setValue("ClientId",(char*)&tmpcdrptr->ClientId);
1198 				if (check == -1)
1199 					error_handler(MyTransaction->getNdbErrorString());
1200                                 tmpcdrptr->OurSTART_TIME = ourtime;
1201 				#ifdef SETDBG
1202 					puts("OurSTART_TIME");
1203 				#endif
1204 				check = MyOperation->setValue("OurSTART_TIME",(char*)&tmpcdrptr->OurSTART_TIME);
1205 				if (check == -1)
1206 					error_handler(MyTransaction->getNdbErrorString());
1207                                 tmpcdrptr->USED_FIELDS |= B_START_TIME;
1208 				#ifdef SETDBG
1209 					puts("USED_FIELDS");
1210 				#endif
1211 				check = MyOperation->setValue("USED_FIELDS",(char*)&tmpcdrptr->USED_FIELDS);
1212 				if (check == -1)
1213 					error_handler(MyTransaction->getNdbErrorString());
1214                         break;
1215 
1216                         case 1:
1217                                 tmpcdrptr->OurTimeForStartOfCharge = ourtime;
1218 				#ifdef SETDBG
1219 					puts("OurStartOfCharge");
1220 				#endif
1221 				check = MyOperation->setValue("OurStartOfCharge",(char*)&tmpcdrptr->OurTimeForStartOfCharge);
1222 				if (check == -1)
1223 					error_handler(MyTransaction->getNdbErrorString());
1224                                 tmpcdrptr->USED_FIELDS |= B_TimeForStartOfCharge;
1225 				#ifdef SETDBG
1226 					puts("USED_FIELDS");
1227 				#endif
1228 				check = MyOperation->setValue("USED_FIELDS",(char*)&tmpcdrptr->USED_FIELDS);
1229 				if (check == -1)
1230 					error_handler(MyTransaction->getNdbErrorString());
1231                         break;
1232 
1233                         case 2:
1234                                 tmpcdrptr->OurTimeForStopOfCharge = ourtime;
1235 				#ifdef SETDBG
1236 					puts("OurStopOfCharge");
1237 				#endif
1238 				check = MyOperation->setValue("OurStopOfCharge",(char*)&tmpcdrptr->OurTimeForStopOfCharge);
1239 				if (check == -1)
1240 					error_handler(MyTransaction->getNdbErrorString());
1241                                 tmpcdrptr->USED_FIELDS |= B_TimeForStopOfCharge;
1242 				#ifdef SETDBG
1243 					puts("USED_FIELDS");
1244 				#endif
1245 				check = MyOperation->setValue("USED_FIELDS",(char*)&tmpcdrptr->USED_FIELDS);
1246 				if (check == -1)
1247 					error_handler(MyTransaction->getNdbErrorString());
1248                         break;
1249 
1250                         case 3:
1251                                 tmpcdrptr->CallAttemptState  = 4;
1252                         break;
1253 			default:
1254         			snprintf(msg,sizeof(msg),"cdrtype %d unknown",cdrsubtype);
1255 				if ((checkchangelog(log,lognamn))==0)
1256           				n2log(log,msg);
1257                                 goto errout;
1258                         break;
1259                 }
1260                                 ops++;
1261                                 if (ops == ops_before_exe) {
1262                                   ops = 0;
1263                                   #ifdef SETDBG
1264                                         puts("Going to execute");
1265                                   #endif
1266                                   check = MyTransaction->execute(Commit, CommitAsMuchAsPossible);
1267                 		  if ((check == -1) && (MyTransaction->getNdbError() != 0))
1268                                         error_handler(MyTransaction->getNdbErrorString());
1269                                   MyNdb.closeTransaction(MyTransaction);
1270                                   #ifdef SETDBG
1271                                         puts("Transaction closed");
1272                                   #endif
1273 
1274                                   #ifdef SETDBG
1275                                         puts("New transaction initiated");
1276                                   #endif
1277                                 }//if
1278                 /* Increment the request count. */
1279                 reqcnt++;
1280 
1281                 /* Send a response back to the client. */
1282 
1283                 /* if (send(s, buf, 10, 0) != 10) goto errout;  */
1284         }
1285 
1286         /* The loop has terminated, because there are no                */
1287         /* more requests to be serviced. As mentioned above,            */
1288         /* this close will block until all of the sent replies          */
1289         /* have been received by the remote host. The reason            */
1290         /* for lingering on the close is so that the server will        */
1291         /* have a better idea of when the remote has picked up          */
1292         /* all of the data. This will allow the start and finish        */
1293         /* times printed in the log file to reflect more accurately     */
1294         /* the length of time this connection was                       */
1295         /* The port number must be converted first to host byte         */
1296         /* order before printing. On most hosts, this is not            */
1297         /* necessary, but the ntohs() call is included here so          */
1298         /* that this program could easily be ported to a host           */
1299         /* that does require it.                                        */
1300 
1301         BaseString::snprintf(msg,sizeof(msg),"Completed %s port %u, %d requests",hostname,ntohs(peeraddr_in.sin_port), reqcnt);
1302 	if ((checkchangelog(fi,temp))==0)
1303           c2log(fi,msg);
1304 	error_from_client = 1;
1305         BaseString::snprintf(msg,sizeof(msg),"Communicate with threads");
1306 	if ((checkchangelog(log,lognamn))==0)
1307           n2log(log,msg);
1308         BaseString::snprintf(msg,sizeof(msg),"Waiting for threads to return from work");
1309 	if ((checkchangelog(log,lognamn))==0)
1310           n2log(log,msg);
1311         BaseString::snprintf(msg,sizeof(msg),"Closing down");
1312 	if ((checkchangelog(log,lognamn))==0)
1313           n2log(log,msg);
1314         close(s);
1315         fclose(log);
1316         return EXIT_SUCCESS;
1317 
1318 errout:
1319         BaseString::snprintf(msg,sizeof(msg),"Connection with %s aborted on error\n", hostname);
1320 	if ((checkchangelog(log,lognamn))==0)
1321           n2log(log,msg);
1322 	if ((checkchangelog(fi,temp))==0)
1323           c2log(fi,msg);
1324 	error_from_client = 1;
1325         BaseString::snprintf(msg,sizeof(msg),"Communicate with threads");
1326 	if ((checkchangelog(log,lognamn))==0)
1327           n2log(log,msg);
1328         BaseString::snprintf(msg,sizeof(msg),"Waiting for threads to return from work");
1329 	if ((checkchangelog(log,lognamn))==0)
1330           n2log(log,msg);
1331         BaseString::snprintf(msg,sizeof(msg),"Closing down");
1332 	if ((checkchangelog(log,lognamn))==0)
1333           n2log(log,msg);
1334         close(s);
1335         fclose(log);
1336 	return EXIT_FAILURE;
1337 }
1338 
1339 void
create_table(Ndb * pMyNdb)1340 create_table(Ndb* pMyNdb)
1341 {
1342 
1343  /****************************************************************
1344    *    Create table and attributes.
1345    *
1346    *    create table basictab1(
1347    *        col1 int,
1348    *        col2 int not null,
1349    *        col3 int not null,
1350    *        col4 int not null
1351    *     )
1352    *
1353    ***************************************************************/
1354 
1355   int                   check;
1356   int                   i;
1357   NdbSchemaCon          *MySchemaTransaction;
1358   NdbSchemaOp           *MySchemaOp;
1359   int			tAttributeSize;
1360 
1361   tAttributeSize = 1;
1362 
1363   cout << "Creating " << tableName << "..." << endl;
1364 
1365    MySchemaTransaction = pMyNdb->startSchemaTransaction();
1366    if( MySchemaTransaction == NULL )
1367       error_handler(MySchemaTransaction->getNdbErrorString());
1368 
1369    MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
1370    if( MySchemaOp == NULL )
1371       error_handler(MySchemaTransaction->getNdbErrorString());
1372 
1373    // Createtable
1374    check = MySchemaOp->createTable( tableName,
1375                                      8,         // Table Size
1376                                      TupleKey,  // Key Type
1377                                      40         // Nr of Pages
1378                                    );
1379    if( check == -1 )
1380       error_handler(MySchemaTransaction->getNdbErrorString());
1381 
1382    // CallIdentificationNumber Create first column, primary key
1383    check = MySchemaOp->createAttribute( "CIN",
1384 					TupleKey,
1385 					32,
1386                                         tAttributeSize,
1387 					UnSigned, MMBased,
1388                                         NotNullAttribute
1389 					);
1390    if( check == -1 )
1391       error_handler(MySchemaTransaction->getNdbErrorString());
1392 
1393 
1394    // USED_FIELDS Create attributes
1395    check = MySchemaOp->createAttribute( "USED_FIELDS", NoKey, 32,
1396                                          tAttributeSize, UnSigned, MMBased,
1397                                          NullAttribute );
1398    if( check == -1 )
1399       error_handler(MySchemaTransaction->getNdbErrorString());
1400 
1401    // ClientId Create attributes
1402    check = MySchemaOp->createAttribute( "ClientId", NoKey, 32,
1403                                          tAttributeSize, UnSigned, MMBased,
1404                                          NullAttribute );
1405    if( check == -1 )
1406       error_handler(MySchemaTransaction->getNdbErrorString());
1407 
1408    // START_TIME Create attributes
1409    check = MySchemaOp->createAttribute( "START_TIME", NoKey, 32,
1410                                          tAttributeSize, UnSigned, MMBased,
1411                                          NullAttribute );
1412    if( check == -1 )
1413       error_handler(MySchemaTransaction->getNdbErrorString());
1414 
1415    // OurSTART_TIME Create attributes
1416    check = MySchemaOp->createAttribute( "OurSTART_TIME", NoKey, 32,
1417                                          tAttributeSize, UnSigned, MMBased,
1418                                          NullAttribute );
1419    if( check == -1 )
1420       error_handler(MySchemaTransaction->getNdbErrorString());
1421 
1422    // TimeForStartOfCharge Create attributes
1423    check = MySchemaOp->createAttribute( "StartOfCharge", NoKey, 32,
1424                                          tAttributeSize, UnSigned, MMBased,
1425                                          NullAttribute );
1426    if( check == -1 )
1427       error_handler(MySchemaTransaction->getNdbErrorString());
1428 
1429    // TimeForStopOfCharge Create attributes
1430    check = MySchemaOp->createAttribute( "StopOfCharge", NoKey, 32,
1431                                          tAttributeSize, UnSigned, MMBased,
1432                                          NullAttribute );
1433    if( check == -1 )
1434       error_handler(MySchemaTransaction->getNdbErrorString());
1435 
1436    // OurTimeForStartOfCharge Create attributes
1437    check = MySchemaOp->createAttribute( "OurStartOfCharge", NoKey, 32,
1438                                          tAttributeSize, UnSigned, MMBased,
1439                                          NullAttribute );
1440    if( check == -1 )
1441       error_handler(MySchemaTransaction->getNdbErrorString());
1442 
1443    // OurTimeForStopOfCharge Create attributes
1444    check = MySchemaOp->createAttribute( "OurStopOfCharge", NoKey, 32,
1445                                          tAttributeSize, UnSigned, MMBased,
1446                                          NullAttribute );
1447    if( check == -1 )
1448       error_handler(MySchemaTransaction->getNdbErrorString());
1449 
1450    // DestinationPointCode Create attributes
1451    check = MySchemaOp->createAttribute( "DPC", NoKey, 16,
1452                                          tAttributeSize, UnSigned, MMBased,
1453                                          NullAttribute );
1454    if( check == -1 )
1455       error_handler(MySchemaTransaction->getNdbErrorString());
1456 
1457    // OriginatingPointCode Create attributes
1458    check = MySchemaOp->createAttribute( "OPC", NoKey, 16,
1459                                          tAttributeSize, UnSigned, MMBased,
1460                                          NullAttribute );
1461    if( check == -1 )
1462       error_handler(MySchemaTransaction->getNdbErrorString());
1463 
1464    // CircuitIdentificationCode Create attributes
1465    check = MySchemaOp->createAttribute( "CIC", NoKey, 16,
1466                                          tAttributeSize, UnSigned, MMBased,
1467                                          NullAttribute );
1468    if( check == -1 )
1469       error_handler(MySchemaTransaction->getNdbErrorString());
1470 
1471    // ReroutingIndicator Create attributes
1472    check = MySchemaOp->createAttribute( "RI", NoKey, 16,
1473                                          tAttributeSize, UnSigned, MMBased,
1474                                          NullAttribute );
1475    if( check == -1 )
1476       error_handler(MySchemaTransaction->getNdbErrorString());
1477 
1478    // RINParameter Create attributes
1479    check = MySchemaOp->createAttribute( "RINParameter", NoKey, 16,
1480                                          tAttributeSize, UnSigned, MMBased,
1481                                          NullAttribute );
1482    if( check == -1 )
1483       error_handler(MySchemaTransaction->getNdbErrorString());
1484 
1485    // NetworkIndicator Create attributes
1486    check = MySchemaOp->createAttribute( "NIndicator", NoKey, 8,
1487                                          tAttributeSize, Signed, MMBased,
1488                                          NullAttribute );
1489    if( check == -1 )
1490       error_handler(MySchemaTransaction->getNdbErrorString());
1491 
1492    // CallAttemptState Create attributes
1493    check = MySchemaOp->createAttribute( "CAS", NoKey, 8,
1494                                          tAttributeSize, Signed, MMBased,
1495                                          NullAttribute );
1496    if( check == -1 )
1497       error_handler(MySchemaTransaction->getNdbErrorString());
1498 
1499    // ACategory Create attributes
1500    check = MySchemaOp->createAttribute( "ACategory", NoKey, 8,
1501                                          tAttributeSize, Signed, MMBased,
1502                                          NullAttribute );
1503    if( check == -1 )
1504       error_handler(MySchemaTransaction->getNdbErrorString());
1505 
1506    // EndOfSelectionInformation Create attributes
1507    check = MySchemaOp->createAttribute( "EndOfSelInf", NoKey, 8,
1508                                          tAttributeSize, Signed, MMBased,
1509                                          NullAttribute );
1510    if( check == -1 )
1511       error_handler(MySchemaTransaction->getNdbErrorString());
1512 
1513    // UserToUserInformation Create attributes
1514    check = MySchemaOp->createAttribute( "UserToUserInf", NoKey, 8,
1515                                          tAttributeSize, Signed, MMBased,
1516                                          NullAttribute );
1517    if( check == -1 )
1518       error_handler(MySchemaTransaction->getNdbErrorString());
1519 
1520    // UserToUserIndicator Create attributes
1521    check = MySchemaOp->createAttribute( "UserToUserInd", NoKey, 8,
1522                                          tAttributeSize, Signed, MMBased,
1523                                          NullAttribute );
1524    if( check == -1 )
1525       error_handler(MySchemaTransaction->getNdbErrorString());
1526 
1527    // CauseCode Create attributes
1528    check = MySchemaOp->createAttribute( "CauseCode", NoKey, 8,
1529                                          tAttributeSize, Signed, MMBased,
1530                                          NullAttribute );
1531    if( check == -1 )
1532       error_handler(MySchemaTransaction->getNdbErrorString());
1533 
1534    // ASubscriberNumber attributes
1535    check = MySchemaOp->createAttribute( "ANumber", NoKey, 8,
1536                                          ASubscriberNumber_SIZE, Signed, MMBased,
1537                                          NullAttribute );
1538    if( check == -1 )
1539       error_handler(MySchemaTransaction->getNdbErrorString());
1540 
1541    // ASubscriberNumberLenght attributes
1542    check = MySchemaOp->createAttribute( "ANumberLength", NoKey, 8,
1543                                          tAttributeSize, Signed, MMBased,
1544                                          NullAttribute );
1545    if( check == -1 )
1546       error_handler(MySchemaTransaction->getNdbErrorString());
1547 
1548    // TonASubscriberNumber attributes
1549    check = MySchemaOp->createAttribute( "TonANumber", NoKey, 8,
1550                                          tAttributeSize, Signed, MMBased,
1551                                          NullAttribute );
1552    if( check == -1 )
1553       error_handler(MySchemaTransaction->getNdbErrorString());
1554 
1555    // BSubscriberNumber attributes
1556    check = MySchemaOp->createAttribute( "BNumber", NoKey, 8,
1557                                          BSubscriberNumber_SIZE, Signed, MMBased,
1558                                          NullAttribute );
1559    if( check == -1 )
1560       error_handler(MySchemaTransaction->getNdbErrorString());
1561 
1562    // BSubscriberNumberLength attributes
1563    check = MySchemaOp->createAttribute( "BNumberLength", NoKey, 8,
1564                                          tAttributeSize, Signed, MMBased,
1565                                          NullAttribute );
1566    if( check == -1 )
1567       error_handler(MySchemaTransaction->getNdbErrorString());
1568 
1569    // TonBSubscriberNumber attributes
1570    check = MySchemaOp->createAttribute( "TonBNumber", NoKey, 8,
1571                                          tAttributeSize, Signed, MMBased,
1572                                          NullAttribute );
1573    if( check == -1 )
1574       error_handler(MySchemaTransaction->getNdbErrorString());
1575 
1576    // RedirectingNumber attributes
1577    check = MySchemaOp->createAttribute( "RNumber", NoKey, 8,
1578                                          ASubscriberNumber_SIZE, Signed, MMBased,
1579                                          NullAttribute );
1580    if( check == -1 )
1581       error_handler(MySchemaTransaction->getNdbErrorString());
1582 
1583    // TonRedirectingNumber attributes
1584    check = MySchemaOp->createAttribute( "TonRNumber", NoKey, 8,
1585                                          tAttributeSize, Signed, MMBased,
1586                                          NullAttribute );
1587    if( check == -1 )
1588       error_handler(MySchemaTransaction->getNdbErrorString());
1589 
1590    // OriginalCalledNumber attributes
1591    check = MySchemaOp->createAttribute( "ONumber", NoKey, 8,
1592                                          ASubscriberNumber_SIZE, Signed, MMBased,
1593                                          NullAttribute );
1594    if( check == -1 )
1595       error_handler(MySchemaTransaction->getNdbErrorString());
1596 
1597    // TonOriginalCalledNumber attributes
1598    check = MySchemaOp->createAttribute( "TonONumber", NoKey, 8,
1599                                          tAttributeSize, Signed, MMBased,
1600                                          NullAttribute );
1601    if( check == -1 )
1602       error_handler(MySchemaTransaction->getNdbErrorString());
1603 
1604    // LocationCode attributes
1605    check = MySchemaOp->createAttribute( "LocationCode", NoKey, 8,
1606                                          ASubscriberNumber_SIZE, Signed, MMBased,
1607                                          NullAttribute );
1608    if( check == -1 )
1609       error_handler(MySchemaTransaction->getNdbErrorString());
1610 
1611    // TonLocationCode attributes
1612    check = MySchemaOp->createAttribute( "TonLocationCode", NoKey, 8,
1613                                          tAttributeSize, Signed, MMBased,
1614                                          NullAttribute );
1615    if( check == -1 )
1616       error_handler(MySchemaTransaction->getNdbErrorString());
1617 
1618    if( MySchemaTransaction->execute() == -1 ) {
1619        cout << tableName << " already exist" << endl;
1620        cout << "Message: " << MySchemaTransaction->getNdbErrorString() << endl;
1621    }
1622    else
1623    {
1624      cout << tableName << " created" << endl;
1625    }
1626    pMyNdb->closeSchemaTransaction(MySchemaTransaction);
1627 
1628    return;
1629 }
1630 
1631 void
error_handler(const char * errorText)1632 error_handler(const char* errorText)
1633 {
1634   // Test failed
1635   cout << endl << "ErrorMessage: " << errorText << endl;
1636   bTestPassed = -1;
1637 }
1638