1 /*
2 Copyright (C) 2003-2006 MySQL AB
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