/*****************************************************************************
File: qmsockets.c
Author:
Date:
Description:
Invocation:  ---
*****************************************************************************/

/*****************************************************************************
   Table of Contents:
   Reusable Functions:

   Intern Functions:
      ---
   Includes:

   Source code in this file:

*********************************************************************************/

/********************************************************************************
Import Libraries
*********************************************************************************/
#include "qmsockets.h"
#include "qmqueue.h"
#include "groupcomm.h"
#include "utilities.h"
#include "log.h"
#include <string.h>

// socket support
#include "socku.h"

// system imports
#include <sys/utsname.h>

// postgres
//#include "libpq-fe.h"

// ensemble imports
#include "hot_sys.h"
#include "hot_error.h"
#include "hot_msg.h"
#include "hot_ens.h"

// hash table
#include "hashtable.h"
#include "hashtypes.h"

#include "declarations.h"
#include "tools.h"
#include "database.h"
#include "sqlmiddlertools.h"

#include "stat.h"

/********************************************************************************
Defines
*********************************************************************************/
/* Log Management */
#define FATAL_QMSOCKETS
#define ERROR_QMSOCKETS
//#define INFO_QMSOCKETS
//#define WARN_QMSOCKETS
//#define DEBUG_QMSOCKETS
//#define DEBUG_QMSOCKETS_SENDSIZE
//#define DEBUG_QMSOCKETS_SEND
//#define DEBUG_QMSOCKETS_RECV
//#define DEBUG_QMSOCKETS_CLOSE
//#define DEBUG_QMSOCKETS_SEND_QMMESSAGE
//#define DEBUG_QMSOCKETS_RECV_QMMESSAGE
//#define DEBUG_QMSOCKETS_QMMESSAGE
//#define DEBUG_QMSOCKETS_COMMIT
//#define DEBUG_QMSOCKETS_LOG
//#define DEBUG_FILES_FLAG
//#define DEBUG_FILES_QUEUE
//#define NOTIFICATION_DEBUG_QMSOCKETS
//#define DEBUG_QMSOCKETS_STATS

/********************************************************************************
Variables
*********************************************************************************/
// the notification thread iterates while it is 1
// and finishes when it is 0
int running;

static int not_sock;          // client side
static int notification_sock; // server side
static int total_cc;

int num_stored_procs=0;
int num_commands[STPROCS];
char stored_procs [STPROCS][COMMANDS][MAX_TXT /*+ EXTRASIZE - RMEXTRASIZE */];
int num_params[STPROCS][COMMANDS];
//int freeQMs[MAXQM+1/*JSalas + 1*/]; // bool array, true the QM is free, otherwise is busy
//QMID hot_uint32 tQMThread[MAXQM+1/*JSalas + 1*/];
T_QMQueue_ptr waitingforQM[MAXQM+1];

T_Dllist_ptr freeQMs;
T_Dllist_ptr freeConQMs;
QMState stateQMs[MAXQM+1/*JSalas + 1*/];

extern log_t log_queue;


void printQMMessage(QM_message msg);


//int numFields;
int autocommit = TRUE;

/********************************************************************************
Prototype Functions
*********************************************************************************/
void FreeQM(int);
char *makebitmask(struct DBType *db, int tuple, int nfields);
void oldClient (int, int);
void pgserverClient (int, int);
void QMFactory();

/********************
 *  IMPLEMENTATION  *
 *******************/
// dcadena
void oldClient (int qid, int sock) {
  /* Delete by JSalas */
}

int CheckEarlyDisconnect(QM_message *mess){
	int stp = 0;
	int client = 0;	
    struct itemhPetition *foundPet = NULL;
    int discon_petition = 0;
    
    sscanf(&mess->trans.transaction.sqlcode[0], "%d", &stp);	
	switch (mess->type) {        	 
        case QM_connect: break;       	
       	case QM_disconnect: break;		
        case QM_execute:
          if (/*(stp == CON) ||*/ (stp == CON_RESPONSE) /*|| (stp == RECON_RESPONSE)*/ /*|| (stp == RECON)*/){
          	//TODO IN insertNextPetition
     	    /*client = (mess->trans.idConnection * MAX_PETITION_PER_CLIENT) + 0;     	  	 
     	  	if ((foundPet = (struct itemhPetition *) get_hashtable(&hPetition, &client)) == NULL) {			  			  
			  foundPet = (struct itemhPetition *) malloc (sizeof(struct itemhPetition));
			  foundPet->id = client;
			  foundPet->discon.idConnection = mess->trans.idConnection;
			  foundPet->discon.idPetition = mess->trans.idPetition;
			  foundPet->discon.last_petition = client;
			  foundPet->discon.isfirst_petition = 2;
			  //foundPet->discon.disconnect_petition = -1;			  			  				    
			  foundPet->discon.is_delay_disconnect = 0;
			  foundPet->discon.backup_stp = DISCON_RESPONSE;
			  foundPet->discon.tid = 0;
			    
			  if (!insert_hashtable(&hPetition, &foundPet->id, foundPet)) {
#ifdef ERROR_QMSOCKETS
    		    printf("(QMSOCKETS) ERROR Insert hPetition\n");
#endif
  			  }			  
     	  	}*/
     	  	
     	  } else if (/*(stp == DISCON) ||*/ (stp == DISCON_RESPONSE) || (stp == EARLY_DISCON)){
     	  	client = (mess->trans.idConnection * MAX_PETITION_PER_CLIENT) + 0;     	  	 
     	  	if ((foundPet = (struct itemhPetition *) get_hashtable(&hPetition, &client)) != NULL) {			  			  
     	  	  foundPet->discon.idConnection = mess->trans.idConnection;	
     	  	  foundPet->discon.idPetition = mess->trans.idPetition;
			  foundPet->discon.tid = mess->trans.transaction.tid;			  		  			  				    			  

              mess->discon.tid = mess->trans.transaction.tid;
//printf("TID DISCON=<%d>", foundPet->discon.tid);	
			  discon_petition = (mess->trans.idConnection * MAX_PETITION_PER_CLIENT) + mess->trans.idPetition;
//Tprintf("DISCON 56 <%d> <%d> <%d>\n",discon_petition, foundPet->discon.last_petition, foundPet->discon.isfirst_petition);		  				  
			  if (CheckNotificationDisconnect(discon_petition, foundPet->discon.last_petition, foundPet->discon.last_received, foundPet->discon.isfirst_petition) == 1){
			    mess->discon.is_delay_disconnect = 0;			    
			    mess->discon.send_discon_message = 1;
			    mess->discon.backup_stp = stp;
			    
			    mess->discon.idConnection = foundPet->discon.idConnection;
			    mess->discon.idPetition = foundPet->discon.idPetition;
			    /* TODO Quitar entrada de tabla hash */
			    /*if (delete_hashtable(&hPetition, &client) == 0) {
			    	printf("2 (QMSOCKETS) Petition %d not found TYPE<%d> SQLCODE<%s>\n", client, mess->type, mess->trans.transaction.sqlcode);
				}else{
	    			printf("2 (QMSOCKETS) Petition %d found TYPE<%d> SQLCODE<%s>\n", client, mess->type, mess->trans.transaction.sqlcode);
		
#ifdef DEBUG_QMSOCKETS_HASH
                  printf("(QMSOCKETS) Petition %d not found\n", client);

                } else {
                  printf("(QMSOCKETS) HashTable hPetition number of elements <%d>\n", num_elements_hashtable(& hPetition));
#endif
                }*/			  
			  } else {	
//Tprintf("DISCON 57\n");		  				  			  			  				  				  				    
			    foundPet->discon.is_delay_disconnect = 1;
			    if (stp == EARLY_DISCON){
			      foundPet->discon.backup_stp = DELAY_EARLY_DISCON;	
			    }else{
			      foundPet->discon.backup_stp = DELAY_DISCON;	
			    }
			    
			    mess->discon.is_delay_disconnect = 1;			    
			    mess->discon.send_discon_message = 0;		    
			  }
        	}else{
#ifdef ERROR_QMSOCKETS
              printf("(QMSOCKETS) ERROR lookup hPetition 1\n");
#endif        		                       
     	  	}  
          } else { //NOT CONNECTION AND NOT DISCONNECTION
          	if (mess->trans.transaction.isQuery) {
          	  client = (mess->trans.idConnection * MAX_PETITION_PER_CLIENT) + 0;     	  	 
          	  if ((foundPet = (struct itemhPetition *) get_hashtable(&hPetition, &client)) != NULL) {
          	    /* Update last petition */
                foundPet->discon.last_petition = (mess->trans.idConnection * MAX_PETITION_PER_CLIENT) + mess->trans.idPetition;
          	  } 
          	}
          }          	
          break;

        case QM_commit:
		  client = (mess->trans.idConnection * MAX_PETITION_PER_CLIENT) + 0;     	  	 
     	  if ((foundPet = (struct itemhPetition *) get_hashtable(&hPetition, &client)) != NULL) {
            if (foundPet->discon.isfirst_petition > 0){
              foundPet->discon.isfirst_petition--;
            }
      
	        /* Update last petition */
            foundPet->discon.last_petition = (mess->trans.idConnection * MAX_PETITION_PER_CLIENT) + mess->trans.idPetition;

            if (foundPet->discon.is_delay_disconnect){  
              discon_petition = (foundPet->discon.idConnection * MAX_PETITION_PER_CLIENT) + foundPet->discon.idPetition;	          
              if (CheckNotificationDisconnect(discon_petition, foundPet->discon.last_petition, foundPet->discon.last_received, 0) == 1){                  	            
                foundPet->discon.is_delay_disconnect = 0;          
                
                mess->discon.is_delay_disconnect = 1;			    
			    mess->discon.send_discon_message = 1;
			    mess->discon.idConnection = foundPet->discon.idConnection;
			    mess->discon.idPetition = foundPet->discon.idPetition;
			                    	
			    mess->discon.backup_stp = foundPet->discon.backup_stp;
			    mess->discon.tid = foundPet->discon.tid; 
			    
                /* TODO Quitar entrada de tabla hash */
			    /*if (delete_hashtable(&hPetition, &client) == 0) {
			    	printf("3 (QMSOCKETS) Petition %d not found\n", client);
				}else{
	    			printf("3 (QMSOCKETS) Petition %d found\n", client);
		
#ifdef DEBUG_QMSOCKETS_HASH
                  printf("(QMSOCKETS) Petition %d not found\n", client);

                } else {
                  printf("(QMSOCKETS) HashTable hPetition number of elements <%d>\n", num_elements_hashtable(& hPetition));
#endif
                }*/
              }
            }
          } else {
#ifdef ERROR_QMSOCKETS
			printf("(QMSOCKETS) ERROR lookup hPetition 2 client<%d> idcon<%d> idPet<%d>\n", client, mess->trans.idConnection, mess->trans.idPetition);
#endif        		                       
     	  } 
          break;

        case QM_abort:
          break;

        case QM_apply_ws_and_commit:
		  client = (mess->trans.idConnection * MAX_PETITION_PER_CLIENT) + 0;     	  	 
     	  if ((foundPet = (struct itemhPetition *) get_hashtable(&hPetition, &client)) != NULL) {
            if (foundPet->discon.isfirst_petition > 0){
              foundPet->discon.isfirst_petition--;
            }
      
	        /* Update last petition */
            foundPet->discon.last_petition = (mess->trans.idConnection * MAX_PETITION_PER_CLIENT) + mess->trans.idPetition;

            if (foundPet->discon.is_delay_disconnect){  
              discon_petition = (foundPet->discon.idConnection * MAX_PETITION_PER_CLIENT) + foundPet->discon.idPetition;	          
              if (CheckNotificationDisconnect(discon_petition, foundPet->discon.last_petition, foundPet->discon.last_received, 0) == 1){                  	            
                foundPet->discon.is_delay_disconnect = 0;   
                
                mess->discon.is_delay_disconnect = 1;			    
			    mess->discon.send_discon_message = 1;
			    mess->discon.idConnection = foundPet->discon.idConnection;
			    mess->discon.idPetition = foundPet->discon.idPetition;
			                    	
			    mess->discon.backup_stp = foundPet->discon.backup_stp;
			    mess->discon.tid = foundPet->discon.tid;
			            
                 /* TODO Quitar entrada de tabla hash */
			    /*if (delete_hashtable(&hPetition, &client) == 0) {
					printf("4 (QMSOCKETS) Petition %d not found\n", client);
			    }else{
					printf("4 (QMSOCKETS) Petition %d found\n", client);
			    	
#ifdef DEBUG_QMSOCKETS_HASH
                  printf("(QMSOCKETS) Petition %d not found\n", client);

                } else {
                  printf("(QMSOCKETS) HashTable hPetition number of elements <%d>\n", num_elements_hashtable(& hPetition));
#endif
                }*/
              }
            }
            
          } else {
#ifdef ERROR_QMSOCKETS
            printf("(QMSOCKETS) ERROR lookup hPetition 3 client<%d> idcon<%d> idPet<%d>\n", client, mess->trans.idConnection, mess->trans.idPetition);
#endif        		                       
     	  } 
          break;

        default:
#ifdef ERROR_QMSOCKETS
          printf("(QMSOCKETS) Error kind_of_QM message incorrect %d\n", mess->type);
#endif
	} // switch
  	
    return 0;
}

/********************************************************************************
Reusable Function.
   void SendMessageToQM(T_Transaction* trans, QM_message* mess);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void SendMessageToQM(T_Transaction* trans, QM_message* mess) {
  SendMessageToQMPriority(trans, mess, 0);
}

void SendMessageToQMPriority(T_Transaction* trans, QM_message* mess, int priority) {
   int bytes;
   int result;
   char sql[MAX_TXT];
   //struct itemhClient *found;
   
#ifdef DEBUG_FILES_QUEUE
     char buffer_log[2048];
#endif

#ifdef DEBUG_QMSOCKETS_STATS
   struct timeval time;      
#endif
//printf("SendMessageToQMPriority Tid <%d>\n", trans->transaction.tid);
   //Tprintf("SendMessageToQMPriority Tid <%d> <%d> <%d>\n", trans->transaction.tid, trans->idConnection, trans->idPetition);
   if (!priority){
     decSemaphore(&QM_mutex);
     //printf("decSemaphore(&QM_mutex) Tid <%d>\n", trans->transaction.tid);
   }
#ifdef DEBUG_FILES_QUEUE
   bzero(buffer_log, sizeof(buffer_log));
   sprintf(buffer_log, "INI SendMessageToQM <%d> Priority <%d> Tid <%d>\n", trans->qid, priority, trans->transaction.tid);
   write_in_log_qmqueue(&log_queue, buffer_log);
#endif

   //if ((mess->type == QM_execute) || (mess->type == QM_apply_ws_and_commit)) {
   if (mess->type != QM_commit) {
     //printf("((mess->type == QM_execute) || (mess->type == QM_apply_ws_and_commit)) <%d>\n", trans->qid);
     if ((QMQ_isEmpty(waitingforQM[0/* QMID trans->qmId */])) || (priority)){
       /* Get free QM */
       result = GetQM(trans->qmId, mess);
       mess->trans.qmId = result;/* QMID trans->qid;*/
       //printf("Petition QM <%d> assigned <%d>\n", trans->qmId, result);
       if (result == -1) {
         if (priority){
           printf("0 enqueue with priority <%d>\n", trans->qmId);
           exit(0);
         } else {
           /* Queue the message and a pointer to the transaction */
#ifdef DEBUG_FILES_QUEUE
          bzero(buffer_log, sizeof(buffer_log));
          sprintf(buffer_log, "Message to <%d> enqueue tid <%d>\n", trans->qmId, trans->transaction.tid);
          write_in_log_qmqueue(&log_queue, buffer_log);
#endif

           //printf("0 Message to <%d> enqueue tid <%d>\n", trans->qmId, trans->transaction.tid);
           QMQ_enqueue(waitingforQM[0/* QMID trans->qmId*/], mess, trans);
           //QMQ_printFirstAndNumElements(waitingforQM[trans->qid]);//TODO Quitar
           //printf("incSemaphore(&QM_mutex) Tid <%d>\n", trans->transaction.tid);
           incSemaphore(&QM_mutex);
           return;
         }

       } else if (priority) {
         QMQ_dequeue(waitingforQM[0/* QMID trans->qid*/]);
         //printf("2 Message to <%d> dequeue tid <%d>\n", trans->qmId, trans->transaction.tid);

       } else {       	        	 
         //printf("8 Message to <%d> NO dequeue tid <%d>\n", trans->qmId, trans->transaction.tid);
       }
     } else {
       //printf("1 Message to <%d> enqueue tid <%d>\n", trans->qid, trans->transaction.tid);
       // QMID mess->trans.qid = trans->qid;
       QMQ_enqueue(waitingforQM[0/* QMID trans->qid*/], mess, trans);
       if (!priority){
         //printf("incSemaphore(&QM_mutex) Tid <%d>\n", trans->transaction.tid);
         incSemaphore(&QM_mutex);
       }
       return;
     }
   }

   trans->qmId = mess->trans.qmId;
   
   /* Info Update Early Disconnect */
   //UpdateQMMessageEarlyDisconnect(mess->trans.idConnection, mess->early);
   CheckEarlyDisconnect(mess);
   
#ifdef DEBUG_QMSOCKETS_SEND_QMMESSAGE
   printf("(QMSOCKETS) (SEND 12) Bytes <%d> Message To QM%d <---> (QMMESSAGE)\n", sizeof(*mess), trans->qmId);
#endif

   /* Sending message */
   //bytes = send(sock[trans->qid], (char*) &mess, sizeof(mess), 0);
   //printf("sendQMMessage sock[%d]=%d\n", mess->trans.qmId, sock[mess->trans.qmId]);

#ifdef DEBUG_QMSOCKETS_STATS
   //struct timeval time;   
   gettimeofday(&time, NULL);//STATS
   //setFinishTimeArray(1, trans->idConnection, trans->idPetition, time.tv_sec, time.tv_usec);
   if (mess->type != QM_commit) {
   	 SETFINISHTIME(1, trans->idConnection, trans->idPetition, time.tv_sec, time.tv_usec);
   	 SETSTARTTIME(2, trans->idConnection, trans->idPetition, time.tv_sec, time.tv_usec);
   }
   //printf("GETTIME CHECK SEN QM<%ld> <%ld> <%d|%d|%d>\n", (steps[2][trans->idConnection][trans->idPetition]).startTime.tv_sec, (steps[2][trans->idConnection][trans->idPetition]).startTime.tv_usec, 2, trans->idConnection, trans->idPetition);  	        
   //(steps[2][trans->idConnection][trans->idPetition]).startTime.tv_sec = time.tv_sec;
   //(steps[2][trans->idConnection][trans->idPetition]).startTime.tv_usec = time.tv_usec;
   //(steps[2][trans->idConnection][trans->idPetition]).inUse = 1;
#endif

   /*if ((found = (struct itemhClient *)get_hashtable(&hClient, &trans->idConnection)) == NULL) {
      #ifdef ERROR_TRANSMNG
        printf("(Transmng) Not possible found connection in hashtable\n");
      #endif
   }else{
      mess->last_petition_executed = found->last_petition_executed;
      found->last_petition_executed = (trans->idConnection * MAX_PETITION_PER_CLIENT) + trans->idPetition; 
   }*/
//Tprintf("sendQMMessage Tid <%d> <%d> <%d>\n", trans->transaction.tid, trans->idConnection, trans->idPetition);   
   bytes = sendQMMessage(sock[mess->trans.qmId], mess);
   //printf("sendQMMessage sock[MAXQM]=%d\n", sock[MAXQM]);
   if (bytes == -1) {
     perror("send message\n");
   }
   //NOTE: NOT use freeQMMessage because the T_Transaction in mess is assign with T_Transaction
   //The rest of memory will be free when call freeT_Transaction
   Free(mess);
   /*if (trans->qid == MAXQM){
     freeTrans(&trans);
   }*/
#ifdef DEBUG_FILES_QUEUE
    bzero(buffer_log, sizeof(buffer_log));
    sprintf(buffer_log, "END SendMessageToQM Priority <%d> Tid <%d>\n", priority, trans->transaction.tid);
    write_in_log_qmqueue(&log_queue, buffer_log);
#endif

   if (!priority){
     //printf("incSemaphore(&QM_mutex) Tid <%d>\n", trans->transaction.tid);
     incSemaphore(&QM_mutex);
   }
}

int sendQMMessage(int socket, QM_message *msg) {
  int rval;
  void *buffer;
  int sizeCC, sizemsg, sizeQMMessage;
//printf("sendQMMessage 0\n");
/*if ((*msg).type == QM_execute){
  printf("SQLCODE sendQMMessage <%s>\n", &(*msg).trans.transaction.sqlcode[3]);
}*/

  /* Add size to message */
  sizeQMMessage = sizeof(QM_message);
  sizeCC = ((*msg).trans.transaction.noCC * sizeof(hot_uint32));
  sizemsg = sizeQMMessage + sizeCC;

  if (!(buffer = (void *) malloc (sizemsg))) {
#ifdef FATAL_QMSOCKETS
    printf("%s# %d # Out of memory.\n", __FILE__, __LINE__);
#endif
    exit(-1);
  }
  bzero(buffer, sizeof(buffer));

  memcpy(buffer, msg, sizeQMMessage);
  memcpy(buffer + sizeQMMessage, (*msg).trans.transaction.transCC, sizeCC);

  /* Send message */
  if ((rval = send(socket, buffer, sizemsg, 0)) < 0) {
    Free(buffer);
    return -1;
  }

#ifdef DEBUG_QMSOCKETS_QMMESSAGE
  printf("Send Bytes: %d\n", sizemsg);
  //printQMMessage(*msg);
#endif

  Free(buffer);
//printf("sendQMMessage 1\n");
  return sizemsg;
}

int recvQMMessageTest(int socket, QM_message *msg, char *txt){
	if (txt == NULL){
	  return recvQMMessage(socket, msg);
	}else{
	  int rval = 0, cread = 0;
	  int sizeQMMessage = 0, sizeCC = 0;
	
	  sizeQMMessage = sizeof(QM_message);
	
	  cread = 0;
	  while (cread < sizeQMMessage) {	
	    if ((rval = recv(socket, msg + cread, sizeQMMessage - cread, 0)) <= 0) {
	      if (rval == 0){
	      	printf("opposite client close socket <%s>\n", txt);
	      	exit(0);
	      }else{	
	        return -1;
	      }
	    }	
	    cread = cread + rval;
	  }
	
	  /* Get size transCC */
	  sizeCC = ((*msg).trans.transaction.noCC * sizeof(hot_uint32));
	#ifdef DEBUG_QMSOCKETS_QMMESSAGE
	  printf("sizeCC <%d> | noCC <%d>", sizeCC, (*msg).trans.transaction.noCC);
	#endif
	
	  if (sizeCC > 0){	
	    if (!((*msg).trans.transaction.transCC = (hot_uint32 *) malloc (sizeCC))) {
	#ifdef FATAL_QMSOCKETS
	      printf("%s# %d # Out of memory.\n", __FILE__, __LINE__);
	#endif
	      exit(-1);
	    }
	
	    /* Get data of message */
	    cread = 0;
	    while (cread < sizeCC) {
	      if ((rval = recv(socket, ((*msg).trans.transaction.transCC) + cread, sizeCC - cread, 0)) < 0) {
	        return -1;
	      }
	      cread = cread + rval;
	    }
	
	  } else {	
	     (*msg).trans.transaction.transCC = NULL;
	  }
	
#ifdef DEBUG_QMSOCKETS_QMMESSAGE
	  printf("Received Bytes: %d\n", sizeCC + sizeQMMessage);
	  //printQMMessage(*msg);
#endif
	
	  return sizeQMMessage + sizeCC;
  }
}

int recvQMMessage(int socket, QM_message *msg) {
  int rval = 0, cread = 0;
  int sizeQMMessage = 0, sizeCC = 0;
//printf("recvQMMessage 0\n");
  sizeQMMessage = sizeof(QM_message);
//printf("recvQMMessage 1\n");
  cread = 0;
  while (cread < sizeQMMessage) {
//printf("recvQMMessage 1_0\n");  	
    if ((rval = recv(socket, msg + cread, sizeQMMessage - cread, 0)) <= 0) {
      if (rval == 0){
      	printf("opposite client close socket\n");
      	exit(0);
      }else{
//printf("recvQMMessage 1_1\n");
        return -1;
      }
    }
//printf("recvQMMessage 1_2\n");    
    cread = cread + rval;
  }
//printf("recvQMMessage 2\n");
  /* Get size transCC */
  sizeCC = ((*msg).trans.transaction.noCC * sizeof(hot_uint32));
#ifdef DEBUG_QMSOCKETS_QMMESSAGE
  printf("sizeCC <%d> | noCC <%d>", sizeCC, (*msg).trans.transaction.noCC);
#endif
//printf("recvQMMessage 3\n");
  if (sizeCC > 0){
//printf("recvQMMessage 4\n");  	
    if (!((*msg).trans.transaction.transCC = (hot_uint32 *) malloc (sizeCC))) {
#ifdef FATAL_QMSOCKETS
      printf("%s# %d # Out of memory.\n", __FILE__, __LINE__);
#endif
      exit(-1);
    }
//printf("recvQMMessage 5\n");
    /* Get data of message */
    cread = 0;
    while (cread < sizeCC) {
      if ((rval = recv(socket, ((*msg).trans.transaction.transCC) + cread, sizeCC - cread, 0)) < 0) {
        return -1;
      }
      cread = cread + rval;
    }
//printf("recvQMMessage 6\n");
  } else {
//printf("recvQMMessage 7\n");  	
     (*msg).trans.transaction.transCC = NULL;
  }

#ifdef DEBUG_QMSOCKETS_QMMESSAGE
  printf("Received Bytes: %d\n", sizeCC + sizeQMMessage);
  //printQMMessage(*msg);
#endif
//printf("recvQMMessage 8\n");
  return sizeQMMessage + sizeCC;
}

void AssignMsgDisconnect(QM_message_Disconnect *dest, QM_message_Disconnect *orig){
  
  (*dest).tid = (*orig).tid;
  (*dest).idConnection = (*orig).idConnection;
  (*dest).idPetition = (*orig).idPetition;
  (*dest).is_delay_disconnect = (*orig).is_delay_disconnect;
  (*dest).send_discon_message = (*orig).send_discon_message;
  (*dest).backup_stp = (*orig).backup_stp;
  
  return;
}

void initMsgDisconnect(QM_message_Disconnect *orig){
        	  	 	
  (*orig).tid = 0;
  (*orig).idConnection = 0;
  (*orig).idPetition = 0;
  (*orig).is_delay_disconnect = 0;
  (*orig).send_discon_message = 0;
  (*orig).backup_stp = DISCON_RESPONSE;

  return;
}

int cloneQMMessage(QM_message *dest, QM_message *orig) {
  /*(*msg).type = (*msg).type;
  (*msg).thId = (*msg).thId;
  (*msg).size = (*msg).size;
  strcpy((*msg).buffer, (*msg).buffer); //QMMessage_buffer

  //printf("\nT_Transaction trans:\n");
  (*msg).trans.local = (*msg).trans.local;
  (*msg).trans.executedByAll = (*msg).trans.executedByAll;
  (*msg).trans.localNode = 0;
  (*msg).trans.finished = 0;
  (*msg).trans.committable = 0;
  (*msg).trans.executing = 0;
  (*msg).trans.aborting = 0;
  (*msg).trans.committing = 0;
  (*msg).trans.commitreceived = 0;

  //printf("\nT_writeset writeset:\n");
  //printf("char writeset;\n");
  (*msg).trans.writeset[0] = '\0';
  (*msg).trans.writeset_length = 0;

  (*msg).trans.qid = 0;
  (*msg).trans.idConnection = 0;
  (*msg).trans.idPetition = 0;
  (*msg).trans.recordsUpdates = 0;
  (*msg).trans.error = 0;

  //printf("\nT_Trans transaction:\n");
  (*msg).trans.transaction.noCC = 0;
  (*msg).trans.transaction.transCC = NULL;

  (*msg).trans.transaction.sqlcode[0] = '\0';
  (*msg).trans.transaction.tid = 0;

  //(*msg).trans.transaction.endpoint, "";
  (*msg).trans.transaction.isQuery = 0;
  (*msg).trans.transaction.typeSQL = '\0';
*/

/*int sizeQMMessage = 0, sizeCC = 0;

  sizeQMMessage = sizeof(QM_message);

  //Copy Struct
  memcpy(dest, org, sizeQMMessage);

  //Get size transCC
  sizeCC = ((*org).trans.transaction.noCC * sizeof(hot_uint32));
#ifdef DEBUG_QMSOCKETS_QMMESSAGE
  printf("sizeCC <%d> | noCC <%d>", sizeCC, (*org).trans.transaction.noCC);
#endif

  if (sizeCC > 0){
    if (!((*dest).trans.transaction.transCC = (hot_uint32 *) malloc (sizeCC))) {
#ifdef FATAL_QMSOCKETS
      printf("%s# %d # Out of memory.\n", __FILE__, __LINE__);
#endif
      exit(-1);
    }

    //Copy TransCC
    memcpy((*dest).trans.transaction.transCC, (*org).trans.transaction.transCC, sizeCC);

  } else {
     (*dest).trans.transaction.transCC = NULL;
  }

  //printQMMessage(*dest);
#ifdef DEBUG_QMSOCKETS_QMMESSAGE
  printf("Received Bytes: %d\n", sizeCC + sizeQMMessage);
  //printQMMessage(*msg);
#endif

  return sizeQMMessage + sizeCC;
}*/

  (*dest).type = (*orig).type;
  AssignMsgDisconnect(&(*dest).discon, &(*orig).discon);
  //(*dest).mclientId = (*orig).mclientId;
  //(*dest).last_petition_executed = (*orig).last_petition_executed;
  (*dest).size = (*orig).size;
  strcpy((*dest).buffer, (*orig).buffer);
  cloneT_Transaction(&dest->trans, &orig->trans);
}

void initQMMessage(QM_message *msg) {
  (*msg).type = QM_empty;
  //(*msg).mclientId = -1;
  (*msg).size = 0;
  //(*msg).last_petition_executed = 0;
  initMsgDisconnect(&(*msg).discon);
//printf("sizeof((*msg).buffer) <%d>\n", sizeof((*msg).buffer));
  bzero((*msg).buffer, sizeof((*msg).buffer));
  
  InitT_Transaction(&(*msg).trans);
}

void freeQMMessage(QM_message **msg) {
  /*T_Trans *t_trans;
  T_Transaction *transact;
  transact = &(*msg)->trans;
  t_trans = &transact->transaction;
  resetT_Trans(&t_trans);

  //resetT_Trans(&(*msg)->trans.transaction);
  */
  /*
  if ((*msg)->trans.transaction.noCC != 0){
    free((*msg)->trans.transaction.transCC);
    (*msg)->trans.transaction.transCC = NULL;
  }
  */
  Free(*msg);
}

void resetQMMessage(QM_message *msg) {
  /*
  T_Trans *t_trans;
  T_Transaction *transact;
  transact = &(*msg).trans;
  t_trans = &transact->transaction;
  resetT_Trans(&t_trans);
*/
  //resetT_Trans(&(*msg).trans.transaction);
  Free((*msg).trans.transaction.transCC);
  /*
  if ((*msg).trans.transaction.noCC != 0){
    free((*msg).trans.transaction.transCC);
    (*msg).trans.transaction.transCC = NULL;
  }
  */
  initQMMessage(msg);
}

void printQMMessage(QM_message msg){
  int i;

  printf("enum kind_of_QM_message type <%d>;\n", msg.type);
  // QMID printf("hot_uint32 thId <%d>;\n", msg.thId);
  printf("char buffer[TAMBUFFER] <%s>;\n", msg.buffer); //QMMessage_buffer
  printf("hot_uint32 size <%d>;\n", msg.size);
  //printf("hot_uint32 last_petition_executed <%d>;\n", msg.last_petition_executed);
  
  printf("\nT_Transaction trans:\n");
  printf("bool local <%d>;\n", msg.trans.local);
  printf("bool executedByAll <%d>;\n", msg.trans.executedByAll);
  printf("bool localNode <%d>;\n", msg.trans.localNode);
  printf("bool finished <%d>;\n", msg.trans.finished);
  printf("bool committable <%d>;\n", msg.trans.committable);
  printf("bool executing <%d>;\n", msg.trans.executing);
  printf("bool aborting <%d>;\n", msg.trans.aborting);
  printf("bool committing <%d>;\n", msg.trans.committing);
  printf("bool commitreceived <%d>;\n", msg.trans.commitreceived);
  printf("long writeset_length <%ld>;\n", msg.trans.writeset_length);
  printf("hot_uint32 qid <%d>;\n", msg.trans.qmId);
  printf("hot_uint32 idConnection <%d>;\n", msg.trans.idConnection);
  printf("hot_uint32 idPetition <%d>;\n", msg.trans.idPetition);
  printf("int recordsUpdates <%d>;\n", msg.trans.recordsUpdates);
  printf("int error <%d>;\n", msg.trans.error);

  printf("\nT_Trans transaction:\n");
  printf("hot_uint32 noCC <%d>;\n", msg.trans.transaction.noCC);
  printf("hot_uint32 *transCC;\n");
  for (i = 0; i < msg.trans.transaction.noCC; i++) {
    printf("transCC[%d] = %d;\n", i, msg.trans.transaction.transCC[i]);
  }
  printf("char sqlcode <%s>;\n", msg.trans.transaction.sqlcode);
  printf("T_Tid tid <%d>;\n", msg.trans.transaction.tid);
  printf("hot_endpt_t endpoint;\n");
  printf("hot_uint32 isQuery <%d>;\n", msg.trans.transaction.isQuery);
  printf("char typeSQL <%c>;\n", msg.trans.transaction.typeSQL);

  printf("\nT_writeset writeset:\n");
  printf("char writeset;\n");
}

/********************************************************************************
Reusable Function.
   void FillParams(char command[COMMANDS], char pattern[COMMANDS],
                   int nparms, char params[PARAMS][MAX_TXT]);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void FillParams(char command[COMMANDS], char pattern[COMMANDS],
                int nparms, char params[PARAMS][MAX_TXT /*+ EXTRASIZE - RMEXTRASIZE */]) {
//printf("NUM PARAMS <%d>\n", nparms);
  switch (nparms) {
    case 0:
      strcpy(command, pattern);
      break;
    case 1:
//printf("PARAMS <%s>\n", params[0]);
      sprintf(command, pattern, params[0]);
      break;
    case 2:
      sprintf(command, pattern, params[0], params[1]);
      break;
    case 3:
      sprintf(command, pattern, params[0], params[1],
         params[2]);
      break;
    case 4:
      sprintf(command, pattern, params[0], params[1],
         params[2], params[3]);
      break;
    case 5:
      sprintf(command, pattern, params[0], params[1],
         params[2], params[3], params[4]);
      break;
    case 6:
      sprintf(command, pattern, params[0], params[1],
         params[2], params[3], params[4], params[5]);
      break;
    case 7:
      sprintf(command, pattern, params[0], params[1],
         params[2], params[3], params[4], params[5],
         params[6]);
      break;
    case 8:
      sprintf(command, pattern, params[0], params[1],
         params[2], params[3], params[4], params[5],
         params[6], params[7]);
      break;
    case 9:
      sprintf(command, pattern, params[0], params[1],
         params[2], params[3], params[4], params[5],
         params[6], params[7], params[8]);
       break;
  }
}

/********************************************************************************
Reusable Function.
   char *ConnectionErrorMsg(char *msg);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
char *ConnectionErrorMsg(char *msg){
  char *buffer = NULL;

  if (!(buffer = (char*) malloc(sizeof(char) * (strlen(msg) + 1 + EOF_SIZE)))) {
    #ifdef FATAL_QMSOCKETS
      printf("%s# %d # Out of memory.\n", __FILE__, __LINE__ );
    #endif
    exit(0);
  }

  /* Send "E" + error message */
  strcpy(buffer, "E");
  strcat(buffer, msg);

  #ifdef DEBUG_QMSOCKETS
    printf("ConnectionErrorMsg -> <%s>\n", buffer);
  #endif
  return buffer;
}

/********************************************************************************
Reusable Function.
   char *ExecuteQueryErrorMsg(char *msg);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
char *ExecuteQueryErrorMsg(char *msg, int *size){
  char *buffer = NULL;
  int pos = 0;

  *size = 3 + EOF_SIZE; /* 'E' + msg + '\0' + 'Z' + '\0' */

  if (msg == NULL){
    printf("Msg in ExecuteQuery is NULL");
  } else {
    (*size)+=strlen(msg);
  }

  if (!(buffer = (char*) malloc(sizeof(char) * (*size)))) {
    #ifdef FATAL_QMSOCKETS
      printf("%s# %d # Out of memory.\n", __FILE__, __LINE__ );
    #endif
    exit(0);
  }

  /* Send "E" + error message + "Z" */
  strcpy(buffer, "E");
  if (msg != NULL){
    strcat(buffer, msg);
    pos = (*size)-2;
    /* length without EOF */
    (*size)--;

  } else {
    pos = 2;
    /* length without EOF */
    *size = 3;
  }

  buffer[pos] = 'Z';
  buffer[pos-1] = '\0';


#ifdef DEBUG_QMSOCKETS
    printf("ExecuteQueryErrorMsg -> <%d> <%s>\n", *size, buffer);
#endif
  return buffer;

}

/********************************************************************************
Reusable Function.
   char *ExecuteStatusMsg(char *msg);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
char *ExecuteStatusMsg(char *msg){
  char *buffer = NULL;

  if (!(buffer = (char*) malloc(sizeof(char) * (strlen(msg) + 1 + EOF_SIZE)))) {
    #ifdef FATAL_QMSOCKETS
      printf("%s# %d # Out of memory.\n", __FILE__, __LINE__ );
    #endif
    exit(0);
  }

  /* Send "C" + status message */
  strcpy(buffer, "C");
  strcat(buffer, msg);

  #ifdef DEBUG_QMSOCKETS
    printf("ExecuteStatusMsg -> <%s>\n", buffer);
  #endif
  return buffer;
}

/********************************************************************************
Reusable Function.
   char *ExecuteUpdateErrorMsg(char *msg);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
char *ExecuteUpdateErrorMsg(char *msg, int *size){
  char *buffer = NULL;
  int pos = 0;

  *size = 3 + EOF_SIZE; /* 'E' + msg + '\0' + 'Z' + '\0' */

  if (msg == NULL){
    printf("Msg in ExecuteUpdate is NULL");
  } else {
    (*size)+=strlen(msg);
  }

  /*exit(0); //TODO quitar*/
  if (!(buffer = (char*) malloc(sizeof(char) * (*size)))) {
    #ifdef FATAL_QMSOCKETS
      printf("%s# %d # Out of memory.\n", __FILE__, __LINE__ );
    #endif
    exit(0);
  }

  /* Send "E" + error message + "Z" */
  strcpy(buffer, "E");
  if (msg != NULL){
    strcat(buffer, msg);
    pos = (*size)-2;
    /* length without EOF */
    (*size)--;

  } else {
    pos = 2;
    /* length without EOF */
    *size = 3;
  }

  buffer[pos] = 'Z';
  buffer[pos-1] = '\0';


#ifdef DEBUG_QMSOCKETS
    printf("ExecuteUpdateErrorMsg -> <%d> <%s>\n", *size, buffer);
#endif
  return buffer;
}

/********************************************************************************
Reusable Function.
   int SendNOTToNotificationThread(int type, int thId, int sock, QM_message *msg);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
int SendNOTToNotificationThread(int type, int thId, int sock, QM_message *msg, int sizemsg){
int value;
#ifdef DEBUG_QMSOCKETS_SEND_QMMESSAGE
  printf("(QMSOCKETS) (SendNOTToThread) Bytes <%d> Message To Thread%d <---> (QMMESSAGE)\n", sizemsg, thId);
#endif
//printf("SendNOTToNotificationThread 0 THID %d, sock %d\n", thId, sock);
  (*msg).type = type;
  (*msg).trans.mclientId = thId;
//printf("SendNOTToNotificationThread 1\n");
  value = sendQMMessage(sock, msg);
//printf("SendNOTToNotificationThread 2 %d\n", value);  
  //return send(sock, (char*) msg, sizemsg, 0);
  return value;
}

/********************************************************************************
Reusable Function.
   int SendNOTResponseMsg(int sock, QM_message *msg, char *txt, int size);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
int SendNOTResponseMsg(int sock, QM_message *msg, int sizemsg, char *txt, int size){
  (*msg).type = NOT_response;

  if ((txt != NULL) && (sizeof((*msg).buffer) >= (size + EOF_SIZE))){//QMMessage_buffer
    //strcpy((*msg).buffer, txt);
    copyBuffer ((*msg).buffer, txt, size);//QMMessage_buffer
  }
  (*msg).size = size;

#ifdef DEBUG_QMSOCKETS_SEND_QMMESSAGE
  printf("(QMSOCKETS) (SendNOTResponseMsg sock<%d>) Bytes <%d> <---> (QMMESSAGE)\n", sock, sizemsg);
#endif
  //return send(sock, (char*) msg, sizemsg, 0);
  return sendQMMessage(sock, msg);
}

/********************************************************************************
Reusable Function.
   int ExecuteQueryWithSendError(int sock, struct DBType *db, char *query);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
int ExecuteQueryWithSendError(int sock, struct DBType *db, char *query){
  char *buffer = NULL;
  int rval = 0;
  int size_bufferJDBC = 0;

  if (ExecuteQuery(db, query) == -1){
    buffer = ExecuteQueryErrorMsg(GetErrorMessage(db), &size_bufferJDBC);

    #ifdef DEBUG_QMSOCKETS_SENDSIZE
      printf("(QMSOCKETS) (SENDSIZE 2) Bytes <%d> Message <%s> (ERROR)\n", size_bufferJDBC/*strlen(buffer) + EOF_SIZE*/, buffer);
    #endif
    if((rval=sendWithSize(sock, buffer, size_bufferJDBC/*strlen(buffer) + EOF_SIZE*/))<0) {
      #ifdef ERROR_QMSOCKETS
        printf("(QM) ERROR sending datas to groupcomm\n");
      #endif
    }
    Free(buffer);
  }
  return rval;
}

/********************************************************************************
Reusable Function.
   int ExecuteUpdateWithSendError(int sock, struct DBType *db, char *query);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
int ExecuteUpdateWithSendError(int sock, struct DBType *db, char *query, char type){
  char *buffer = NULL;
  int rval = 0;
  int size_bufferJDBC = 0;

  if (ExecuteUpdate(db, query, type) == -1){
    #ifdef DEBUG_QMSOCKETS_SENDSIZE
      printf("(QMSOCKETS) (SENDSIZE 3) Bytes <%d> Message <%s> (ERROR)\n", strlen(buffer) + EOF_SIZE, buffer);
      //exit(0); //TODO quitar
    #endif
    buffer = ExecuteUpdateErrorMsg(GetErrorMessage(db), &size_bufferJDBC);
    if((rval=sendWithSize(sock, buffer, size_bufferJDBC/*strlen(buffer) + EOF_SIZE*/))<0) {
      #ifdef ERROR_QMSOCKETS
        printf("(QM Special) ERROR sending datas to groupcomm\n");
      #endif
    }
    Free(buffer);
  }
  return rval;
}

/********************************************************************************
Reusable Function.
   int ConnectionWithSendError(int sock, struct DBType *db);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
int ConnectionWithSendError(int sock, struct DBType *db){
  char *buffer = NULL;
  int rval = 0;
  if ((rval = Connect(db)) == -1){
    buffer = ConnectionErrorMsg(GetErrorMessage(db));
    #ifdef DEBUG_QMSOCKETS_SENDSIZE
      printf("(QMSOCKETS) (SENDSIZE 4) Bytes <%d> Message <%s> (ERROR)\n", strlen(buffer) + EOF_SIZE, buffer);
    #endif
    if((sendWithSize(sock, buffer, strlen(buffer) + EOF_SIZE))<0) {
      rval = -2;
      #ifdef ERROR_QMSOCKETS
        printf("(QM Special) ERROR sending datas to groupcomm\n");
      #endif
    }
    Free(buffer);
  }
  return rval;
}

/********************************************************************************
Reusable Function.
   void QMSpecial_Init(int sock, struct DBType *dbschema);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void QMSpecial_Init(int sock, struct DBType *dbschema){

  int len = 0, /*i = 0,*/ rval = 0, ntuples = 0, tuple = 0, size = 0;
  char *buffer = NULL;
  char sqlcode[MAX_TXT /*+ EXTRASIZE - RMEXTRASIZE*/];
  int pos = 0;

  /* Obtain records of conflict_classes */
  bzero(sqlcode, sizeof(sqlcode));
  strcpy (sqlcode, SQLRecordsDBSchema());

  ExecuteQueryWithSendError(sock, dbschema, sqlcode);

  ntuples = GetNumberTuples (dbschema);
  size = 0;
  for (tuple = 0; tuple < ntuples; tuple++) {
    len = GetValueLenght(dbschema, tuple, 0);
    size = size + len;
    len = GetValueLenght(dbschema, tuple, 1);
    size = size + len;
    //len = GetValueLenght(dbschema, tuple, 2);
    size = size += 3 + sizeof(int);
  }
  size = size + 4;  // $$$.

  /* Obtain tables in conflict_classes */
  if (!(buffer = (char*) calloc(sizeof(char),(size + EOF_SIZE)))) {
    #ifdef FATAL_QMSOCKETS
      printf("%s# %d # Out of memory.\n", __FILE__, __LINE__ );
    #endif
    exit(0);
  }
  //bzero (buffer, sizeof(buffer));
  pos = 0;
  for (tuple = 0; tuple < ntuples; tuple++) {
    int id_aux;
    int bufferlen;

    bufferlen = strlen(GetResultValue(dbschema, tuple, 0));
    memcpy(& buffer[pos], GetResultValue(dbschema, tuple, 0), bufferlen);
    pos += bufferlen;
    buffer[pos++] = '.';

    bufferlen = strlen(GetResultValue(dbschema, tuple, 1));
    memcpy(& buffer[pos], GetResultValue(dbschema, tuple, 1), bufferlen);
    pos += bufferlen;
    buffer[pos++] = '.';

    id_aux = atoi(GetResultValue(dbschema, tuple, 2));
    memcpy(& buffer[pos], & id_aux, sizeof(int));
    pos += sizeof(int);
    buffer[pos++] = '.';

    //strcat (buffer, GetResultValue(dbschema, tuple, 0));
    //strcat (buffer, ".");
    //strcat (buffer, GetResultValue(dbschema, tuple, 1));
    //strcat (buffer, ".");

    //strcat (buffer, GetResultValue(dbschema, tuple, 2));
    //convertToChar(straux, 4, 0,  atoi(GetResultValue(dbschema, tuple, 2)));
    //straux[4] = '\0';
  }
  //strcat (buffer, "$$$.");
  buffer[pos++] = '$';
  buffer[pos++] = '$';
  buffer[pos++] = '$';
  buffer[pos++] = '.';

  /* SEND TABLES AND ID_CC                */
  /* FORMAT : (DBNAME.TABLE.ID_CC.).$$$.  */
  #ifdef DEBUG_QMSOCKETS_SENDSIZE
    printf("(QMSPECIAL) (SENDSIZE 6) Bytes <%d> Message <%s> ((DBNAME.TABLE.ID_CC.).$$$.)\n", size + EOF_SIZE, buffer);
  #endif
  if((rval=sendWithSize(sock, buffer, size + EOF_SIZE))<0) {
    #ifdef ERROR_QMSOCKETS
      printf("(QMSPECIAL) ERROR sending datas to groupcomm\n");
    #endif
  }
  Free (buffer);
  FreeResult(dbschema);
}

/********************************************************************************
Reusable Function.
   int QMSpecial_Connection(int sock, struct DBType *dbschema, struct DBType *dbreplica, QM_message *msg, int existdb);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
int QMSpecial_Connection(int sock, struct DBType *dbschema, struct DBType *dbreplica, QM_message *msg, int existdb){

  int bytes = 0;
  int len = 0, i = 0, rval = 0, ntuples = 0, tuple = 0, maxidcc = 0, size = 0;
  char *buffer = NULL;
  char straux[INTASCHAR + EOF_SIZE /*+ EXTRASIZE - RMEXTRASIZE */];
  char *dbname = NULL;
  char sqlcode[MAX_TXT /*+ EXTRASIZE - RMEXTRASIZE*/];
  //char buf_JDBC[TAMBUFFERJDBC /*+ EXTRASIZE - RMEXTRASIZE*/];
  char maxidCC[INTASCHAR];
  int pos;

  dbname = GetDatabaseName(dbreplica);

  /* CONNECTION */
  if (existdb) {
    //if (!(buffer = (char*) malloc(sizeof(char) * (1 + EOF_SIZE)))) {//CPG
    if (!(buffer = (char*) calloc(sizeof(char), (4 + EOF_SIZE)))) {
      #ifdef FATAL_QMSOCKETS
        printf("%s# %d # Out of memory.\n", __FILE__, __LINE__ );
      #endif
      exit(0);
    }
    //strcpy (buffer, ".");//CPG
    strcpy (buffer, "$$$.");
    #ifdef DEBUG_QMSOCKETS_SENDSIZE
      printf("(QMSPECIAL) (SENDSIZE 7) Bytes <%d> Message <%s> (.)\n", 1 + EOF_SIZE, buffer);
    #endif
    //if((rval=sendWithSize(sock, buffer, 1 + EOF_SIZE))<0) {//CPG
    if((rval=sendWithSize(sock, buffer, 4 + EOF_SIZE))<0) {
      #ifdef ERROR_QMSOCKETS
        printf("(QMSPECIAL) ERROR sending datas to groupcomm\n");
      #endif
      Free(buffer);
      return -1;
    }

  } else {
    // dbname do not exist in conflict_classes
    #ifdef WARN_QMSOCKETS
      printf ("(QM Special) %s do not exist in conflict_classes\n", dbname);
    #endif
    /* CONNECT TO DBNAME */
    //printf("(QM Special) connecting to postgres, dbname = %s\n", dbname);
    /* Connect with database replica */
    if (ConnectionWithSendError(sock, dbreplica) < 0){
      //JJJ Disconnect(dbreplica);
      Disconnect(dbreplica);
      return -2;
    }

    /* Obtain MAX(id_cc) */
    bzero(sqlcode, sizeof(sqlcode));
    strcpy (sqlcode, SQLLastIDCC());

    ExecuteQueryWithSendError(sock, dbschema, sqlcode);

    tuple = 0;
    maxidcc = atoi (GetResultValue(dbschema, tuple, 0)) + 1;
    FreeResult (dbschema);

    /* Obtain tables of dbname */
    bzero(sqlcode, sizeof(sqlcode));
    strcpy (sqlcode, SQLTablesDB());

    ExecuteQueryWithSendError(sock, dbreplica, sqlcode);

    ntuples = GetNumberTuples(dbreplica);
    size = strlen(dbname) + 1;
    for (tuple = 0; tuple < ntuples; tuple++) {
      if (!isFieldNull(dbreplica, tuple, 0)) {
        len = GetValueLenght(dbreplica, tuple, 0);
      }
      size = size + len + 1 + 4 + 1;
    }
    size = size + 4;  // $$$.

    /* insert tables in conflict_classes */
    if (!(buffer = (char*) calloc(sizeof(char), (size + EOF_SIZE)))) {
      #ifdef FATAL_QMSOCKETS
        printf("%s# %d # Out of memory.\n", __FILE__, __LINE__ );
      #endif
      exit(0);
    }

    pos = 0;
    len = strlen(dbname);
    memcpy(& buffer[pos], dbname, len);
    pos += len;
    buffer[pos++] = '.';

    ExecuteTransaction(dbschema, "BEGIN");
    FreeResult(dbschema);
    for (tuple = 0; tuple < ntuples; tuple++) {
      char * straux = NULL;
      //printf("%s:%d: [QM Special]\n", __FILE__, __LINE__);
      if (!isFieldNull(dbreplica, tuple, 0)) {

        straux = GetResultValue(dbreplica, tuple, 0);
        len = strlen(straux);
        memcpy(& buffer[pos], straux, len);
        pos += len;
        buffer[pos++] = '.';
        //printf("%s:%d: [QM Special]\n", __FILE__, __LINE__);

        memcpy(& buffer[pos], & maxidcc, sizeof(int));
        pos += sizeof(int);
        buffer[pos++] = '.';

        //printf("%s:%d: [QM Special]: %s %s\n", __FILE__, __LINE__, maxidCC, dbname);


        // Insert table in clonflict_classes
        sprintf(maxidCC, "%d", maxidcc);
        bzero(sqlcode, sizeof(sqlcode));
        strcpy(sqlcode, SQLInsertTableDB(maxidCC, dbname, GetResultValue(dbreplica, tuple, 0)));

        ExecuteUpdateWithSendError(sock, dbschema, sqlcode, 'I');

        maxidcc++;
        FreeResult(dbschema);
      }
    }
    ExecuteTransaction(dbschema, "END");
    FreeResult(dbschema);
    FreeResult(dbreplica);

    Disconnect(dbreplica);

    //strcat (buffer, "$$$.");
    buffer[pos++] = '$';
    buffer[pos++] = '$';
    buffer[pos++] = '$';
    buffer[pos++] = '.';

    /* SEND TABLES AND ID_CC           */
    /* FORMAT : DBNAME.(TABLE.ID_CC.)  */
    //#ifdef DEBUG_QMSOCKETS_SENDSIZE
      //printf("(QMSPECIAL) (SENDSIZE 8) Bytes <%d> Message <%s> (DBNAME.(TABLE.ID_CC.))\n", size /*+ EOF_SIZE*/, buffer);
      //printf("(QMSPECIAL) (SENDSIZE 8) Bytes <%d> Message <---> (DBNAME.(TABLE.ID_CC.))\n", size /*+ EOF_SIZE*/);
    //#endif
    if((rval=sendWithSize(sock, buffer, size /*+ EOF_SIZE*/))<0) {
      #ifdef ERROR_QMSOCKETS
        printf("(QMSPECIAL) ERROR sending datas to groupcomm\n");
      #endif
    }
  }
  //Free(dbname)
  Free(buffer);
  //JJJ Disconnect(dbreplica);
  return 0;
}

/********************************************************************************
Reusable Function.
   void QMSpecial_CreateTable(int sock, struct DBType *dbschema, QM_message *msg);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void QMSpecial_CreateTable(int sock, struct DBType *dbschema, QM_message *msg){

  int i = 0, maxidcc = 0, rval = 0;
  char straux[INTASCHAR + EOF_SIZE /*+ EXTRASIZE - RMEXTRASIZE */]; //6 = Number of bytes need to store int into char[]
  char buffer[MAX_TXT];
  char sqlcode[MAX_TXT /*+ EXTRASIZE - RMEXTRASIZE*/];
  char tableName[MAXTABLENAME];
  char dbname[MAXDBNAME /*+ EXTRASIZE - RMEXTRASIZE */];
  char bufferSend[MAXDBNAME + 1 /*.*/ + MAXTABLENAME  + 1/*.*/ + INTASCHAR + 1/*.*/ + 4/*$$$.*/ + EOF_SIZE];
  char idCC[INTASCHAR + EOF_SIZE];
  int pos, len;

  /* CONNECT TO MIDDLER */
  strcpy (sqlcode, &(*msg).trans.transaction.sqlcode[LENGTHSQLCODE]);

  bzero(dbname, sizeof(dbname));
  bzero(buffer, sizeof(buffer));

  i = getToken (sqlcode, ';', 0, buffer);
  i = getToken (sqlcode, ';', i, dbname);

  /* Obtain MAX(id_cc) */
  bzero(buffer, sizeof(buffer));
  strcpy (buffer, SQLLastIDCC());

  ExecuteQueryWithSendError(sock, dbschema, buffer);

  maxidcc = atoi (GetResultValue(dbschema, 0, 0)) + 1;
  FreeResult(dbschema);

  bzero (buffer, sizeof(buffer));
  bzero (tableName, sizeof(tableName));
  i = getToken (sqlcode, ' ', 0, buffer);
  i = getToken (sqlcode, ' ', i, buffer);
  i = getToken (sqlcode, ' ', i, tableName);

  pos = 0;
  len = strlen(dbname);
  memcpy(& bufferSend[pos], dbname, len);
  pos += len;
  bufferSend[pos++] = '.';
  //printf("%s:%d: [QM Special]\n", __FILE__, __LINE__);

  len = strlen(tableName);
  memcpy(& bufferSend[pos], tableName, len);
  pos += len;
  bufferSend[pos++] = '.';
  //printf("%s:%d: [QM Special]\n", __FILE__, __LINE__);

  memcpy(& bufferSend[pos], & maxidcc, sizeof(int));
  pos += sizeof(int);
  bufferSend[pos++] = '.';

  ExecuteTransaction(dbschema, "BEGIN");
  FreeResult(dbschema);

  // Insert table in clonflict_classes
  bzero(sqlcode, sizeof(sqlcode));
  sprintf(idCC, "%d", maxidcc);
  strcpy(sqlcode, SQLInsertTableDB(idCC, dbname, tableName));

  ExecuteUpdateWithSendError(sock, dbschema, sqlcode, 'I');
  FreeResult(dbschema);

  ExecuteTransaction(dbschema, "END");
  FreeResult(dbschema);

  bufferSend[pos++] = '$';
  bufferSend[pos++] = '$';
  bufferSend[pos++] = '$';
  bufferSend[pos++] = '.';

  /* SEND TABLES AND ID_CC           */
  /* FORMAT : DBNAME.(TABLE.ID_CC.)  */
  //printf("CREATE bufferSend <%s>\n", bufferSend);
  #ifdef DEBUG_QMSOCKETS_SENDSIZE
    printf("(QMSPECIAL) (SENDSIZE 9) Bytes <%d> Message <%s> (DBNAME.(TABLE.ID_CC.))\n", sizeof(bufferSend), bufferSend);
  #endif
  //if((rval=sendWithSize(sock, bufferSend, strlen(bufferSend) + EOF_SIZE))<0) {
  if ((rval = sendWithSize(sock, bufferSend, sizeof(bufferSend))) < 0) {
    #ifdef ERROR_QMSOCKETS
      printf("(QM Special) ERROR sending datas to groupcomm\n");
    #endif
  }
}

/********************************************************************************
Reusable Function.
   void QMSpecial_DropTable(int sock, struct DBType *dbschema, QM_message *msg);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void QMSpecial_DropTable(int sock, struct DBType *dbschema, QM_message *msg){
  int i = 0, end_tables = 0;
  char buffer[MAX_TXT];
  char tables[MAX_TXT];
  char sqlcode[MAX_TXT /*+ EXTRASIZE - RMEXTRASIZE*/];
  char dbname[MAXDBNAME /*+ EXTRASIZE - RMEXTRASIZE*/];
  char tableName[MAXTABLENAME];

  /* CONNECT TO MIDDLER */
  //printf ("(QM Special) Sentence DROP\n");
  strcpy (sqlcode, &(*msg).trans.transaction.sqlcode[LENGTHSQLCODE]);

  bzero(dbname, sizeof(dbname));
  bzero(buffer, sizeof(buffer));
  i = getToken (sqlcode, ';', 0, buffer);
  i = getToken (sqlcode, ';', i, dbname);

  /* delete table in conflict_classes  */
  i = getToken (sqlcode, ' ', 0, buffer);
  i = getToken (sqlcode, ' ', i, tableName);
  i = getToken (sqlcode, ';', i, tables);

  end_tables = 1;
  i = 0;

  ExecuteTransaction(dbschema, "BEGIN");
  FreeResult(dbschema);
  while (end_tables != 0) {
    i = getToken (tables, ',', i, tableName);
    if (i == 0) {
      end_tables = 0;
    }

    // Insert table in clonflict_classes
    bzero(sqlcode, sizeof(sqlcode));
    strcpy (sqlcode, SQLDeleteTableDB(dbname, tableName));

    ExecuteUpdate(dbschema, sqlcode, 'D');
    FreeResult(dbschema);

  }
  ExecuteTransaction(dbschema, "END");
  FreeResult(dbschema);
}

/********************************************************************************
Reusable Function.
   void QMSpecial (int sock);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void QMSpecial (int sock) {
  QM_message msg;
  int bytes = 0, len = 0, end = 0, stp = 0, ntuples = 0;
  char *dbname2=NULL;
  char sqlcode[MAX_TXT /*+ EXTRASIZE - RMEXTRASIZE*/];
  char dbname[MAXDBNAME /*+ EXTRASIZE - RMEXTRASIZE*/];
  char *buffer = NULL;

  struct DBType *dbreplica = NULL;
  struct DBType *dbschema = NULL;

  #ifdef WARN_QMSOCKETS
    printf("(QM Special) Starting\n");
  #endif

  initQMMessage(&msg); //08092004
  while (!end) {
    len = 0;
    #ifdef DEBUG_QMSOCKETS
      printf("(QM Special) Waiting petition\n");
    #endif

    //bytes = recv(sock, (char*) &msg, sizeof(msg), 0);
    //printf("(QM_SPECIAL) IN recvQMMessage\n");
    bytes = recvQMMessageTest(sock, &msg, "(QM_SPECIAL)");
    //printf("(QM_SPECIAL) OUT recvQMMessage <%d>\n", msg.trans.transaction.tid);
    #ifdef DEBUG_QMSOCKETS_RECV_QMMESSAGE
      printf("(QMSpecial) (RECV 6) Bytes <%d> StructSize <%d> Message <---> (QMMessage)\n", bytes, sizeof(msg));
    #endif

    if (bytes > 0) {
      sscanf(&msg.trans.transaction.sqlcode[len], "%d", &stp);

      if (stp == INI) {
        /* INIT */
        #ifdef DEBUG_QMSOCKETS
          printf("Message is INIT\n");
        #endif
        dbname2 = malloc (sizeof(char) * (strlen(NAMEDBSCHEMA) + EOF_SIZE));
        strcpy (dbname2, NAMEDBSCHEMA);
        /* CONNECT TO MIDDLER */
        //JSalas FALTA options
        dbschema = CreateDBType(dbname2, NULL);
        if (Connect(dbschema) == -1){
          //printf("(QM Special) Connection to database middleR failed : %s\n", buf_JDBC);
          #ifdef DEBUG_QMSOCKETS
            printf ("(QM Special) Sending NOT_response\n");
          #endif

          buffer = ConnectionErrorMsg(GetErrorMessage(dbschema));
          bytes = SendNOTResponseMsg(notification_sock, &msg, sizeof(msg), buffer, strlen(buffer));
          if (bytes == -1) {
            #ifdef ERROR_QMSOCKETS
              printf("(QM Special) ERROR sending datas to notification_sock\n");
            #endif
            //exit(1);
          }
          Free(buffer);
          //Disconnect(dbschema);
          //NotifyAllEnd();
          end = 1; //Jisbco 2
          
        } else {
	        QMSpecial_Init(sock, dbschema);
    	    Free(dbname2);
        	//JJJ Disconnect(dbschema);
        }

      } else if ((stp == CON) || (stp == CON_RESPONSE)){
        /* CONNECTION */
        #ifdef DEBUG_QMSOCKETS
          printf("Message is CONNECTION\n");
        #endif

        /* Connect with database schema */
        /*JJJ
        if (Connect(dbschema) == -1){
          //printf("(QM Special) Connection to database middleR failed : %s\n", buf_JDBC);
          #ifdef DEBUG_QMSOCKETS
            printf ("(QM Special) Sending NOT_response\n");
          #endif
          buffer = ConnectionErrorMsg(GetErrorMessage(dbschema));
          bytes = SendNOTResponseMsg(notification_sock, &msg, sizeof(msg), buffer, strlen(buffer));
          if (bytes == -1) {
            #ifdef FATAL_QMSOCKETS
              printf("(QM Special) ERROR sending datas to notification_sock\n");
            #endif
            exit(1);
          }
          Free(buffer);
          Disconnect(dbschema);
        }/**/

        // read database name
        sscanf(&msg.trans.transaction.sqlcode[LENGTHSQLCODE], "%s", dbname); //TODO removed &dbname

        //JSalas FALTA options
        dbreplica = CreateDBType(dbname, NULL);

        /* Exist dbname in conflictive_classes? */
        strcpy (sqlcode, SQLExistDBInDBSchema(dbname));

        if (ExecuteQuery(dbschema, sqlcode) == -1) {
          int size_bufferJDBC = 0;

          #ifdef DEBUG_QMSOCKETS
            printf ("(QM Special) Sending NOT_response\n");
          #endif

          buffer = ExecuteQueryErrorMsg(GetErrorMessage(dbschema), &size_bufferJDBC);
          bytes = SendNOTResponseMsg(notification_sock, &msg, sizeof(msg), buffer, size_bufferJDBC);
          if (bytes == -1) {
            #ifdef ERROR_QMSOCKETS
              printf("(QM Special) ERROR sending datas to notification_sock\n");
            #endif
            exit(1);
          }
          Free(buffer);
          
          ntuples = 0;
          
        } else {
          ntuples = GetNumberTuples(dbschema);
          FreeResult(dbschema);
        }

        //ntuples = GetNumberTuples(dbschema);
        //FreeResult(dbschema);
        if (ntuples > 0){
          /* Exist database in conflict_classes */
          QMSpecial_Connection(sock, dbschema, dbreplica, &msg, 1);
        } else {
          /* Not exist database in conflict_classes */
          QMSpecial_Connection(sock, dbschema, dbreplica, &msg, 0);
        }
        //Disconnect(dbreplica);
        DestroyDB(&dbreplica);
        //JJJ Disconnect(dbschema);

      } else {
        // sentence sql is of type CREATE TABLE
        /* CREATE TABLE */
        if (msg.trans.transaction.typeSQL == 'C') {
          #ifdef DEBUG_QMSOCKETS
            printf("Message is CREATE TABLE\n");
          #endif

          /*JJJ
          if (Connect(dbschema) == -1){
            buffer = ConnectionErrorMsg(GetErrorMessage(dbschema));
            bytes = SendNOTResponseMsg(notification_sock, &msg, sizeof(msg), buffer, strlen(buffer));
            if (bytes == -1) {
              #ifdef FATAL_QMSOCKETS
                printf("(QM Special) ERROR sending datas to notification_sock\n");
              #endif
              exit(1);
            }
            Free(buffer);
            Disconnect(dbschema);
          }/**/

          QMSpecial_CreateTable(sock, dbschema, &msg);
          //JJJ Disconnect(dbschema);

        } else if (msg.trans.transaction.typeSQL == 'R'){
          /* DROP TABLE */
          #ifdef DEBUG_QMSOCKETS
            printf("Message is DROP TABLE\n");
          #endif

          /*JJJ
          if (Connect(dbschema) == -1){
            #ifdef DEBUG_QMSOCKETS
              printf("(QM Special) Connection to database middleR failed\n");
            #endif
            buffer = ConnectionErrorMsg(GetErrorMessage(dbschema));
            bytes = SendNOTResponseMsg(notification_sock, &msg, sizeof(msg), buffer, strlen(buffer));
            if (bytes == -1) {
              #ifdef ERROR_QMSOCKETS
                printf("(QM Special) ERROR sending datas to notification_sock\n");
              #endif
              exit(1);
            }
            Free(buffer);
            Disconnect(dbschema);
          }/**/

          QMSpecial_DropTable(sock, dbschema, &msg);
          //JJJ Disconnect(dbschema);

        } else {
          #ifdef ERROR_QMSOCKETS
            printf("Error QM_SPECIAL stp<%d> typeSQL <%c>", stp, msg.trans.transaction.typeSQL);
          #endif
          //NotifyAllEnd();
          end = 1; //Jisbco 2
        }
      }
    }
    else {
      #ifdef FATAL_QMSOCKETS
        printf("(QM Special) ERROR Receiving Datas (FATAL ERROR) -> Message ");
        perror("");
      #endif
      //NotifyAllEnd();
      end = 1; //Jisbco 2
    }

    /* Free the last QMMessage received */
    //printf ("%s:%d resetQMMessage IN\n", __FILE__, __LINE__ );
    resetQMMessage(&msg);
    //printf ("%s:%d resetQMMessage OUT\n", __FILE__, __LINE__ );
  }

  #ifdef WARN_QMSOCKETS
    printf("(QM Special) Finishing\n");
  #endif
  Disconnect(dbschema);
  DestroyDB(&dbschema);
  exit(0);
}

int CheckNotificationDisconnect(int disconnect_petition, int last_petition, int last_received, int is_first){
  if (((disconnect_petition == last_petition + 1) || (last_petition == last_received) /*REVIEW Only necesary this condition*/) 
     || is_first){  	
    return 1;
  }
  return 0;
}

int sendNotificationDisconnect(int notification_sock, int qmId, int tid, char *dbname, int discon_type, int idConnection, int idPetition){
  int bytes;
  QM_message discon_msg;

  #ifdef DEBUG_QMSOCKETS
    printf("(QM%d) QM Execute disconnect_petition <%d> last_petition <%d> last_received <%d> is_first <%d>\n", (*discon_msg).trans.qmId, disconnect_petition, last_petition, last_received, is_first);
  #endif
  //if (disconnect_petition == (last_petition + 1) || is_first){
  	initQMMessage(&discon_msg);
  	(discon_msg).trans.transaction.tid = tid;
  	(discon_msg).trans.qmId = qmId;
  	(discon_msg).trans.idConnection = idConnection;
  	(discon_msg).trans.idPetition = idPetition;
    (discon_msg).trans.writeset_length=0;
    (discon_msg).type = NOT_disconnect;
    //(discon_msg).trans.mclientId = thId;

    (discon_msg).trans.transaction.sqlcode[0]='\0';
    //printf("sendNotificationDisconnect <%s>\n", dbname);
    sprintf((discon_msg).trans.transaction.sqlcode, "%2d %s\n", discon_type, dbname);
    //strcpy((*discon_msg).trans.transaction.sqlcode, dbname);

    bytes = sendQMMessage(notification_sock, &discon_msg);
    if (bytes == -1) {
      #ifdef FATAL_QMSOCKETS
        printf("(QM%d) ERROR sending datas to notification_sock\n", (discon_msg).trans.qmId);
      #endif
      exit(1);
    }
    //resetQMMessage(discon_msg);
  //if (disconnect_petition == (last_petition + 1) || is_first){
    return 1;
  //}
  //return 0;
}

int connectQMToDB(int qid, int stp, struct DBType **dbreplica, QM_message *msg, char *dbname, char *connect_respmsg, int *length_connect_respmsg){
  int thId = msg->trans.mclientId;
  int bytes = 0;
  char *bufferJDBC = NULL;
  char buf_JDBC[TAMBUFFERJDBC /*+ EXTRASIZE - RMEXTRASIZE*/];

//printf("connectQMToDB 0 -> ThId %d\n", thId);  	
  //read database name
  sscanf(&msg->trans.transaction.sqlcode[3], "%s", dbname);
  //printf("sscanf(&msg.trans.transaction.sqlcode[len], %s);\n", dbname);  
  
#ifdef DEBUG_QMSOCKETS_LOG
      write_in_log_qm(&logqm, dbname);
      write_in_log_qm(&logqm, "\n");
#endif
//printf("connectQMToDB 1\n");  
  if ((stp == RECON) || (stp == RECON_RESPONSE)){
//printf("connectQMToDB 2\n");  	
  	Disconnect(*dbreplica);
  	DestroyDB(dbreplica);
  }

  //JSalas FALTA options
//printf("connectQMToDB 3\n");  
  *dbreplica = CreateDBType(dbname, NULL);
//printf("connectQMToDB 4\n");  
  if (Connect(*dbreplica) == -1){
//printf("connectQMToDB 5\n");  	
    // Send error to pgserver
    if (msg->trans.localNode) {
      bufferJDBC = ConnectionErrorMsg(GetErrorMessage(*dbreplica));

#ifdef ERROR_QMSOCKETS
      printf("(QM%d) ERROR connecting to <%s> -> <%s>\n", qid, dbname, bufferJDBC);
#endif
#ifdef DEBUG_QMSOCKETS_SEND
      printf("(QM%d) (SEND 13) Bytes <%d> Message <%s> ()\n", qid, sizeof(*msg), bufferJDBC);
#endif
	  
	  bzero(connect_respmsg, sizeof(connect_respmsg));
	  *length_connect_respmsg = strlen(bufferJDBC);
	  memcpy(connect_respmsg, bufferJDBC, *length_connect_respmsg); 
	  if ((stp == CON_RESPONSE) || (stp == RECON_RESPONSE)){
        bytes = SendNOTResponseMsg(notification_sock, msg, sizeof(QM_message), bufferJDBC, strlen(bufferJDBC));
        if (bytes == -1) {

#ifdef ERROR_QMSOCKETS
          printf("(QM%d) ERROR sending datas to notification_sock\n", qid);
#endif

          Free(bufferJDBC);
          Disconnect(*dbreplica);
          DestroyDB(dbreplica);
          exit(1);
        }
	  }
      Free(bufferJDBC);
    }
//printf("connectQMToDB 6\n");    
    Disconnect(*dbreplica);
    DestroyDB(dbreplica);

    /* Free the last QMMessage received */
	//TODO el resto tiene que saber que no has podido conectar, sino se perderán todos los mensajes
    return 0;

  } else {
  	int pid = 0;
#ifdef DEBUG_QMSOCKETS
    printf("(QM%d) Connected to <%s> | number of connection \n", qid, dbname);
#endif
//printf("connectQMToDB 7\n");  
//printf("connectQMToDB 8\n");	  	
	
	// Send authentication information and the pid and cancellation key to pgserver
  	bzero(buf_JDBC, sizeof(buf_JDBC));
  	// Send "R" + 0
  	strcpy(buf_JDBC, "R");
  	pid = ProcessConectionPid(*dbreplica);
  	buf_JDBC[5]= 'K';
  	convertToChar (buf_JDBC, 4, 6, pid);
  	// cancellation key
    convertToChar (buf_JDBC, 4, 10, 0);
    buf_JDBC[14]= 'Z';
    buf_JDBC[15] = '\0';

#ifdef DEBUG_QMSOCKETS_SEND
    printf("(QM%d) (SEND 14) Bytes <%d> Message <%s> (NOT_response)\n", qid, sizeof(*msg), buf_JDBC);
#endif
//printf("connectQMToDB 9\n");
	bzero(connect_respmsg, sizeof(connect_respmsg));
//printf("connectQMToDB 10\n");	  
	*length_connect_respmsg = 15;
//printf("connectQMToDB 11\n");	  
	memcpy(connect_respmsg, buf_JDBC, *length_connect_respmsg);
//printf("connectQMToDB 12\n");	  
	if (msg->trans.localNode) { //JSalas 15092004
	  if ((stp == CON_RESPONSE)|| (stp == RECON_RESPONSE)){
//printf("connectQMToDB 13 %d\n", sizeof(QM_message));	  	
        //TODO Descomment 
        bytes = SendNOTResponseMsg(notification_sock, msg, sizeof(QM_message), buf_JDBC, 15);
//printf("connectQMToDB 14\n");        
        if (bytes == -1) {
//printf("connectQMToDB 15\n");        	
      	  Disconnect(*dbreplica);
          DestroyDB(dbreplica);
#ifdef ERROR_QMSOCKETS
          printf("(QM%d) ERROR sending datas to notification_sock\n", qid);
#endif
            /* Free the last QMMessage received */
		  return 0;
        }
      }
	}
  }
//printf("connectQMToDB 16\n");
  msg->trans.writeset_length=0;

  // send message of notification
#ifdef DEBUG_QMSOCKETS_SEND
  printf("(QM%d) (SEND 15) Bytes <%d> Message <---> (NOT_connection)\n", qid, sizeof(*msg));
#endif
//printf("connectQMToDB 17\n");
  if ((stp == CON_RESPONSE) || (stp == RECON_RESPONSE)){
//printf("connectQMToDB 18 %d\n", sizeof(QM_message));  	
    //TODO Descomment 
    bytes = SendNOTToNotificationThread(NOT_connection, thId, notification_sock, msg, sizeof(QM_message));
    if (bytes == -1) {
//printf("connectQMToDB 19\n");    	
#ifdef FATAL_QMSOCKETS
      printf("(QM%d) SendNOTToNotificationThread (FATAL ERROR) -> Message ", qid);
      perror("");
#endif
      //TODO se podria restablecer el socket?
      exit(1);
    }      
  }
  
  /* Initialice last petition with connection petition */
  //last_petition = (msg->trans.idConnection * MAX_PETITION_PER_CLIENT) + msg.trans.idPetition;
//printf("connectQMToDB 20\n");  
  return 1;
}

/*void UpdateQMMessageEarlyDisconnect(int idConnection, earlyDisconnect *dest){
	struct itemhPetition *foundPet = NULL;	
	int petition = (idConnection * MAX_PETITION_PER_CLIENT) + 0;
		
	if ((foundPet = (struct itemhPetition *) get_hashtable(&hPetition, & petition)) != NULL) {
		AssignEarlyDisconnect(dest, foundPet->early);
	} else {
		printf("UpdateQMMessageEarlyDisconnect ERROR hPetition NOT FOUND ");
	}	
}*/

int setDataStyle(struct DBType *dbreplica){
	int status = -1;
	
    status = ExecuteUpdate(dbreplica, "set datestyle to 'ISO'", 'T');
	
	return status;
}

/********************************************************************************
Reusable Function.
   void QMSpecial (int sock);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void pgserverClient(int qid, int sock) {
  if (qid == MAXQM) {
    QMSpecial (sock);

  } else {
    QM_message msg;
    //QM_message discon_msg;
	QM_message connect_msg;
	
    int end = 0, len = 0, size = 0, i = 0, sizecs = 0, numFields = 0, tuple = 0, ntuples = 0;
    int status = -7;
    //int is_delay_disconnect = 0;
    //int disconnect_petition = 0;
    //int last_petition = 0;
    //int isfirst_petition = 1;
    int count_connection = 0;
    //int backup_stp = DISCON_RESPONSE;
    int bytes, pid, stp, /*thId = -1,*/ com;

    char sqlcode[MAX_TXT /*+ EXTRASIZE - RMEXTRASIZE*/];
    char dbname[MAXDBNAME /*+ EXTRASIZE - RMEXTRASIZE*/];
    char params[PARAMS][MAX_TXT /*+ EXTRASIZE - RMEXTRASIZE*/];
    char buf_JDBC[TAMBUFFERJDBC /*+ EXTRASIZE - RMEXTRASIZE*/];
    char *bufferJDBC = NULL;
    char *sqlaux = NULL;
    
    struct DBType *dbreplica = NULL;
    int size_bufferJDBC = 0;
	
	char connect_respmsg[TAMBUFFER];
	int length_connect_respmsg = 0;
	
	//struct hashtable hQMClient;
	
#ifdef DEBUG_QMSOCKETS_COMMIT
    int count_commit = 0; //TODO quitar
    int count_commit_ws = 0; //TODO quitar
#endif

#ifdef DEBUG_QMSOCKETS_LOG
    log_t logqm;
    char buffer_log[2048];
#endif

    /* QM */
#ifdef DEBUG_QMSOCKETS
      printf("(QM%d) Starting\n", qid);
#endif

	//hQMClient = (HASHTABLE)hash_create(100000, FALSE);
  	/*if(!init_hashtable(&hQMClient, 100000, numeric_hash, key_numeric_copy, value_copy, keys_numeric_compare)){
    	fprintf(stderr, "Could not initialize hashtable.\n");
      	exit(EXIT_FAILURE);
  	}*/
  
    initQMMessage(&msg);
    //initQMMessage(&discon_msg);
	initQMMessage(&connect_msg);
	
#ifdef DEBUG_QMSOCKETS_LOG
      init_log_qm(&logqm, qid);
      write_in_log_qm(&logqm, "CONNECTION ");
#endif

#ifdef DEBUG_QMSOCKETS_COMMIT
      count_commit = 0;//TODO quitar
      count_commit_ws = 0;//TODO quitar
#endif
	  
	  /* Initialice state Disconnect */
      //is_delay_disconnect = 0;
      //disconnect_petition = 0;
      /* DISCON can be the second petition after CON. We have to control this to avoid delay disconnect */
      //isfirst_petition = 2;
      
      end = 0;
      bytes = 1;
      bzero(dbname, sizeof(dbname));
      while ((!end) && (bytes > 0)) {
#ifdef DEBUG_QMSOCKETS
        printf("(QM%d) Waiting command\n", qid);
#endif
        /* Free the last QMMessage received */
        //printf ("%s:%d resetQMMessage IN\n", __FILE__, __LINE__ );
        resetQMMessage(&msg);
        //printf ("%s:%d resetQMMessage OUT\n", __FILE__, __LINE__ );
//printf("(QM%d) IN recvQMMessage\n", qid);
        bytes = recvQMMessageTest(sock, &msg, "(QM)");
//printf("(QM%d) OUT recvQMMessage <%d>\n", qid, msg.trans.transaction.tid);
#ifdef DEBUG_QMSOCKETS_RECV_QMMESSAGE
        printf("(QM%d) (RECV 8) Bytes <%d> StructSize <%d> Message <---> (QMMessage|Action)\n", qid, bytes, sizeof(msg));
#endif

        if (bytes <= 0){
#ifdef FATAL_QMSOCKETS
          printf("(QM%d) Bytes <%d> (FATAL ERROR | Finishing execution)\n", qid, bytes);
#endif
          //TODO seria posible restablecer el socket?
          exit(0);
        }

        len=0;
        sscanf(&msg.trans.transaction.sqlcode[len], "%d", &stp);
		//last_petition = msg.last_petition_executed;
		
#ifdef DEBUG_QMSOCKETS
        printf("(QM%d) Stp <%d> Type <%d>\n", qid, stp, msg.type);
#endif

		if (dbreplica == NULL){			
			if ((stp != CON) && (stp != CON_RESPONSE) && (stp != RECON)){continue;}			
		}else{			 
			if (!hasConnection(dbreplica)){				
				if ((stp != CON) && (stp != CON_RESPONSE) && (stp != RECON)){continue;}				
			}			
		}
		
		//printf("THID %d", msg.trans.mclientId);
        switch (msg.type) {        	 
        case QM_connect: break;       	
       	case QM_disconnect: break;		
        case QM_execute:
#ifdef NOTIFICATION_DEBUG_QMSOCKETS
            printf("(QM%d) QM_EXECUTE: %d\n", qid, msg.trans.transaction.tid);
#endif

        	if ((stp == CON) || (stp == CON_RESPONSE) || (stp == RECON)){
        		//int client;
        		//struct itemhQMClient *foundPet;
        		
#ifdef DEBUG_QMSOCKETS_RECV_QMMESSAGE
				printf("(QM%d) (RECV 7) Bytes <%d> StructSize <%d> Message <---> (QMMessage|CON)\n", qid, bytes, sizeof(msg));
#endif
//printf("msg[%S] == orig[%s]\n", msg.trans.transaction.dbname, dbname);
//if (strcmp(msg.trans.transaction.dbname, "")==0){
//	printf("sqlcode\n");
//}
				if (strcmp(msg.trans.transaction.dbname, dbname)==0){
//printf("Connection is stablished QM[%d]", qid);					
  					//Only send response
  					if (stp == CON_RESPONSE){
  						if (msg.trans.localNode){
//printf(", only response[%d] size <%d>\n", msg.trans.mclientId, length_connect_respmsg);  						
        				  bytes = SendNOTResponseMsg(notification_sock, &msg, sizeof(msg), connect_respmsg, length_connect_respmsg);
        				  if (bytes == -1) {
      	  					Disconnect(dbreplica);
          					DestroyDB(&dbreplica);
#ifdef ERROR_QMSOCKETS
          					printf("(QM%d) ERROR sending datas to notification_sock\n", qid);
#endif
            				/* Free the last QMMessage received */
		  					continue;
        				  }
  						}else{
//printf(", not response[%d] size <%d>\n", msg.trans.mclientId, length_connect_respmsg);  							
  						}      				  			  				
  					
#ifdef DEBUG_QMSOCKETS_SEND
  						printf("(QM%d) (SEND 15) Bytes <%d> Message <---> (NOT_connection)\n", qid, sizeof(msg));
#endif
						// send message of notification						
	    				bytes = SendNOTToNotificationThread(NOT_connection, msg.trans.mclientId, notification_sock, &msg, sizeof(msg));
	    				if (bytes == -1) {
#ifdef FATAL_QMSOCKETS
	      					printf("(QM%d) SendNOTToNotificationThread (FATAL ERROR) -> Message ", qid);
					        perror("");
#endif
	      					//TODO se podria restablecer el socket?
					        exit(1);
	    				}     	    				 
	  				} else {//if (stp != CON_RESPONSE)
//printf(", not response[%d] size <%d>\n", msg.trans.mclientId, length_connect_respmsg);	  					
  					}				
	  				//continue;
				} else {//if (strcmp(msg.trans.transaction.dbname, dbname)!=0){				
//				  printf("Connection is not stablished QM[%d]\n", qid);	
				  connectQMToDB(qid, stp, &dbreplica, &msg, dbname, connect_respmsg, &length_connect_respmsg);
//printf("----------------- stp <%d> size <%d>\n", stp, length_connect_respmsg);				  
				  cloneQMMessage(&connect_msg, &msg);	
				  setDataStyle(dbreplica);
				}
				//last_petition = (msg.trans.idConnection * MAX_PETITION_PER_CLIENT) + msg.trans.idPetition;							 
//printf("HOLA 1");
				/* Save old STATE*/
/*				if (is_delay_disconnect){
					client = (disconnect_petition/MAX_PETITION_PER_CLIENT);
					if ((foundPet = (struct itemhQMClient *) get_hashtable(&hQMClient, &client)) == NULL) {
						foundPet = (struct itemhQMClient *) malloc (sizeof(struct itemhQMClient));
						foundPet->id = client;
						foundPet->discon.disconnect_petition = disconnect_petition;
					    foundPet->discon.is_delay_disconnect = is_delay_disconnect;
					    foundPet->discon.backup_stp = backup_stp;
					    cloneQMMessage(&foundPet->discon.discon_msg, &discon_msg);
					    
					    if (!insert_hashtable(&hQMClient, &foundPet->id, foundPet)) {
#ifdef ERROR_TRANSMNG
    						printf("(Transmng) ERROR in table hash hPetition to add connection %d and petition %d\n", petition->num_connection, petition->num_petition);
#endif
  						}
        			}
				}*/
//printf("HOLA 2");				
				/* Set-up QM STATE */
/*				client = msg.trans.idConnection;
        		if ((foundPet = (struct itemhQMClient *) get_hashtable(&hQMClient, &client)) != NULL) {
					foundPet = (struct itemhQMClient *) malloc (sizeof(struct itemhQMClient));
					disconnect_petition = foundPet->discon.disconnect_petition;
					is_delay_disconnect = foundPet->discon.is_delay_disconnect;
					backup_stp = foundPet->discon.backup_stp;
					cloneQMMessage(&discon_msg, &foundPet->discon.discon_msg);
        		}else{
        			disconnect_petition = 0;
					is_delay_disconnect = 0;
					backup_stp = DISCON_RESPONSE;
					resetQMMessage(&discon_msg);
        		}*/
//printf("HOLA 3");        		
        	} else if ((stp == DISCON) || (stp == DISCON_RESPONSE) || (stp == EARLY_DISCON)){
        		//Tprintf("DISCON Tid <%d> <%d> <%d> 1\n", msg.trans.transaction.tid, msg.trans.idConnection, msg.trans.idPetition);   
	            if (stp == DISCON){
	              Disconnect(dbreplica);	
	            	
	              /* Notification Free QM */	              
	              /* 
	              msg.type = NOT_freeqm;
	              printf("DISCON <%d>", msg.trans.idConnection);
	              bytes = sendQMMessage(notification_sock, &msg);
	              msg.type = QM_execute;
	              */
	            } else {		            
		            /* Update discon petition */
		            //disconnect_petition = (msg.trans.idConnection * MAX_PETITION_PER_CLIENT) + msg.trans.idPetition;
		            //printf("(QM%d) QM Execute disconnect_petition <%d> last_petition <%d> isfirst_petition <%d>\n", qid, msg.early.disconnect_petition, msg.early.last_petition, msg.early.isfirst_petition);
		            //Tprintf("DISCON <%d> <%d> <%d> 2 <%d> <%d>\n", msg.trans.transaction.tid, msg.trans.idConnection, msg.trans.idPetition, msg.discon.is_delay_disconnect, msg.discon.send_discon_message);   
		            if ((!msg.discon.is_delay_disconnect) && (msg.discon.send_discon_message)){
		              sendNotificationDisconnect(notification_sock, qid, msg.trans.transaction.tid, dbname, stp, msg.discon.idConnection, msg.discon.idPetition);
		              //stp = DISCON;
		              //msg.early.is_delay_disconnect = 0;
#ifdef DEBUG_QMSOCKETS_LOG
		              bzero(buffer_log, sizeof(buffer_log));
		              sprintf(buffer_log, "DISCON: <%d> STATUS: <%d>\n", msg.trans.transaction.tid, msg.discon.is_delay_disconnect);
		              write_in_log_qm(&logqm, buffer_log);
#endif
//Tprintf("DISCON <%d> <%d> <%d> 3\n", msg.trans.transaction.tid, msg.trans.idConnection, msg.trans.idPetition);   
		            } else {
		              //char sqlcode_aux[MAX_TXT];		
		              /* The connection is delay until arrive petition with id equals to disconnect_petition-1 */
		              //printf("(QM%d) Delay idConnection[%d] thId[%d]\n", qid, msg.trans.idConnection, msg.trans.mclientId);
		              //msg.early.is_delay_disconnect = 1;
		              //msg.early.backup_stp = stp;
		              //stp = DELAY_DISCON;
		              //cloneQMMessage(&discon_msg, &msg);	
		              /* Change Discon to Delay discon */
		              //memcpy(sqlcode_aux, & msg.trans.transaction.sqlcode[3], strlen(& msg.trans.transaction.sqlcode[3]));
		              //bzero(msg.trans.transaction.sqlcode, sizeof(msg.trans.transaction.sqlcode));
		              //sprintf(msg.trans.transaction.sqlcode, "%2d %s\n", DELAY_DISCON, sqlcode_aux);
		
		              /* Notification Free QM */	              
		              msg.type = NOT_freeqm;
		              bytes = sendQMMessage(notification_sock, &msg);
		              msg.type = QM_execute;
//Tprintf("DISCON <%d> <%d> <%d> 4\n", msg.trans.transaction.tid, msg.trans.idConnection, msg.trans.idPetition);   		              
		            }
		            //printf("(QM%d) is_delay_disconnect <%d>\n", qid, is_delay_disconnect);
	            }      
          } else { //NOT CONNECTION AND NOT DISCONNECTION                   
            if (!msg.trans.transaction.isQuery) {
              if ((status=ExecuteTransaction(dbreplica, "BEGIN")) == -1) {
                #ifdef ERROR_QMSOCKETS
                  printf("(QM%d) Error PQexec postgres <%s>\n", qid, GetErrorMessage(dbreplica));
                  printf("(QM%d) ERROR executing begin\n", qid);
                #endif
                FreeResult(dbreplica);
                //TODO ckeck, no es posible emplear postAbort en QM
                //postAbort(msg.trans.transaction.tid);
                continue;
              }

              FreeResult(dbreplica);

#ifdef DEBUG_QMSOCKETS_LOG
              bzero(buffer_log, sizeof(buffer_log));
              sprintf(buffer_log, "BEGIN: <%d> STATUS: <%d>\n", msg.trans.transaction.tid, status);
              write_in_log_qm(&logqm, buffer_log);
#endif
            }

            len+=3; // length of the stp# field
//printf("SQLCODE BEFORE BEFORE<%s> STP <%d>\n", &msg.trans.transaction.sqlcode[len], stp);
            for (com=0;com<num_commands[stp]; com++) {
              if ((stp ==  SQG) || (stp == UPDG) || (stp == CDB)) {
                strcpy (params[0], &msg.trans.transaction.sqlcode[len]);
              } else {
                sscanf(&msg.trans.transaction.sqlcode[len],
                       "%s %s %s %s %s %s %s %s %s %s",
                       params[0], params[1], params[2],
                       params[3], params[4], params[5],
                       params[6], params[7],
                       params[8], params[9]);

                for (i=0;i<num_params[stp][com];i++) {
                  len += strlen(params[i])+1;
                }
                len++; // for the ! separator
              }
              FillParams(sqlcode, stored_procs[stp][com], num_params[stp][com], params);

//printf("SQLCODE BEFORE<%s> STP <%d>\n", sqlcode, stp);
              if ((msg.trans.transaction.typeSQL == 'C') || (msg.trans.transaction.typeSQL == 'R')) {
                if (!(sqlaux = (char *) malloc(sizeof(sqlcode) + EOF_SIZE))) {
#ifdef FATAL_QMSOCKETS
                  printf("%s# %d # Out of memory.\n", __FILE__, __LINE__);
#endif
                  //TODO avisar que nos matamos
                  exit(0);
                }
                bzero(sqlaux, sizeof(sqlaux));
                i = getToken (sqlcode, ';', 0, sqlaux);
                bzero(sqlcode, sizeof(sqlcode));
                strcpy(sqlcode, sqlaux);
//printf("SQLCODE AFTER<%s> STP <%d>\n", sqlcode, stp);
                Free(sqlaux);
              }

              // If is a update
              if (!msg.trans.transaction.isQuery){
                status = ExecuteUpdate(dbreplica, sqlcode, msg.trans.transaction.typeSQL);
                if ((status == -1) && (!msg.trans.error)){ //&& (PQresultStatus(res) != PGRES_TUPLES_OK)) {
#ifdef ERROR_QMSOCKETS
                  printf("(QM%d) Executed Error PG\n", qid);
#endif
                  //TODO only store the first error
                  bufferJDBC = ExecuteUpdateErrorMsg(GetErrorMessage(dbreplica), &size_bufferJDBC);
                  msg.trans.error = 1;
                }

              }else{ // If is a query
                status = ExecuteQuery(dbreplica, sqlcode);
                if (status == -1) { //&& (PQresultStatus(res) != PGRES_TUPLES_OK)) {
#ifdef ERROR_QMSOCKETS
                  printf("(QM%d) Executed Error PG\n", qid);
#endif
                  // Send error
                  bufferJDBC = ExecuteUpdateErrorMsg(GetErrorMessage(dbreplica), &size_bufferJDBC);
#ifdef DEBUG_QMSOCKETS_SEND
                  printf("(QM%d) (SEND 16) Bytes <%d> Message <%s> (NOT_response)\n", qid, sizeof(msg), bufferJDBC);
#endif
                  bytes = SendNOTResponseMsg(notification_sock, &msg, sizeof(msg), bufferJDBC, size_bufferJDBC/*strlen(bufferJDBC)*/);
                  if (bytes == -1) {
                    #ifdef FATAL_QMSOCKETS
                      printf("(QM%d) ERROR sending datas to notification_sock\n", qid);
                    #endif
                    FreeResult(dbreplica);
                    Disconnect(dbreplica);
                    DestroyDB(&dbreplica);
                    Free(bufferJDBC);
                    //TODO se podria restablecer el socket?
                    exit(1);
                  }
#ifdef ERROR_QMSOCKETS
                  printf("(QM%d) Error executing sql in postgres <%s> type <%c>\n", qid, GetErrorMessage(dbreplica), msg.trans.transaction.typeSQL);
#endif
                  FreeResult(dbreplica);
                  Free(bufferJDBC);
                  msg.trans.error = 1;
                }
              }
#ifdef DEBUG_QMSOCKETS_LOG
              bzero(buffer_log, sizeof(buffer_log));
              sprintf(buffer_log, "EXECUTE: <%d> STATUS: <%d>\n", msg.trans.transaction.tid, status);
              write_in_log_qm(&logqm, buffer_log);
#endif
            } //for com

            if (!msg.trans.error) {
//printf("!msg.trans.error\n");
              // Getting command status
              bzero(msg.trans.response, sizeof(msg.trans.response));
              msg.trans.response[0] = 'C';
              //TODO check habria que liberar GetCommandStatus
              strcat (msg.trans.response, GetCommandStatus(dbreplica));
              sizecs = strlen(GetCommandStatus(dbreplica)) + 1;
              msg.trans.response[sizecs] = '\0';
              msg.trans.response_length = sizecs + 1;

              if ((!msg.trans.transaction.isQuery) && (stp != CDB)){
//printf("(!msg.trans.transaction.isQuery) && (stp != CDB))\n");
                  //The response is store in msg
                  // Get the writeset and fill in the msg
                  bytes = GetWriteSet(dbreplica, msg.trans.writeset);
                  msg.trans.writeset_length = bytes;
#ifdef DEBUG_QMSOCKETS
                  printf("WriteSet: <%d> <%d>\n", (int*) msg.trans.writeset, bytes);
#endif
                  //Get and store affected rows
                  //TODO check Seria necesario borrar la memoria de GetRowsAffected
                  msg.trans.recordsUpdates = atoi(GetRowsAffected(dbreplica));

              } else if ((msg.trans.transaction.isQuery) || (stp == CDB)) {
//printf("(msg.trans.transaction.isQuery) || (stp == CDB))\n");
                //Not writeset in querys
                msg.trans.writeset_length = 0;

                //Send Notification response
                msg.type = NOT_response;
                msg.size = msg.trans.response_length;
                copyBuffer (msg.buffer, msg.trans.response, msg.trans.response_length);//QMMessage_buffer

                bytes = sendQMMessage(notification_sock, &msg);
                #ifdef DEBUG_QMSOCKETS_SEND_QMMESSAGE
                  printf("(QM%d) (SEND 18) Bytes <%d> Message <%s> (NOT_response|QMMESSAGE)\n", qid, sizeof(msg), buf_JDBC);
                #endif
                //bytes = SendNOTResponseMsg(notification_sock, &msg, sizeof(msg), bufferJDBC, strlen(bufferJDBC));
                if (bytes == -1) {
                  #ifdef FATAL_QMSOCKETS
                    printf("(QM%d) ERROR sending datas to notification_sock\n", qid);
                  #endif
                  //Free(bufferJDBC);
                  Disconnect(dbreplica);
                  DestroyDB(&dbreplica);
                  //TODO ?
                  exit(1);
                }
                //Free(bufferJDBC);

                // Send Fields information
                if ((numFields = sendFieldsMetadata (sock, dbreplica, msg.trans, stp)) == -1) {
                  #ifdef FATAL_QMSOCKETS
                    printf("(QM%d) ERROR sending datas to thread\n", qid);
                  #endif
                  Disconnect(dbreplica);
                  DestroyDB(&dbreplica);
                  //TODO ?
                  exit(0);
                }
//printf("NUMFIELDS=%d\n", numFields);
                if (numFields > 0) {
                  // send tuples
                  ntuples = GetNumberTuples(dbreplica);

                  bzero(buf_JDBC, sizeof(buf_JDBC));
                  convertToChar (buf_JDBC, 4, 0, ntuples);
                  msg.type = NOT_response;
                  msg.size = 4;
                  copyBuffer (msg.buffer, buf_JDBC, 4);//QMMessage_buffer
#ifdef DEBUG_QMSOCKETS_SEND_QMMESSAGE
                  printf("(QM%d) (SEND 19) Bytes <%d> Message <%s> (NOT_response|QMMESSAGE)\n", qid, sizeof(msg), msg.buffer);
#endif
                  bytes = sendQMMessage(notification_sock, &msg);
                  if (bytes == -1) {
                    Disconnect(dbreplica);
                    DestroyDB(&dbreplica);
                    #ifdef FATAL_QMSOCKETS
                      printf("(QM%d) ERROR sending datas to notification_sock\n", qid);
                    #endif
                    //TODO ?
                    exit(1);
                  }

                  for (tuple = 0; tuple < ntuples; tuple++) {
                    if (ExistBinaryTuples(dbreplica)) {
                      if (sendTuple (1, sock, dbreplica, msg.trans, stp, tuple, numFields)<0) {
                        #ifdef FATAL_QMSOCKETS
                          printf("(QM%d) ERROR sending datas to thread\n", qid);
                        #endif
                        Disconnect(dbreplica);
                        DestroyDB(&dbreplica);
                        //TODO ?
                        exit(0);
                      }
                    } else {
                      if (sendTuple (0, sock, dbreplica, msg.trans, stp, tuple, numFields)<0) {
                        #ifdef FATAL_QMSOCKETS
                          printf("(QM%d) ERROR sending datas to thread\n", qid);
                        #endif
                        Disconnect(dbreplica);
                        DestroyDB(&dbreplica);
                        exit(0);
                      }
                    }
                  }
                } /* if (numFields > 0) */
                FreeResult(dbreplica);
              }

            } else if (msg.trans.error) {
              if (!msg.trans.transaction.isQuery){
                //Store the response in msg
                bzero(msg.trans.response, sizeof(msg.trans.response));              	              	
              	copyBuffer (msg.trans.response, bufferJDBC, size_bufferJDBC);              	
              	sizecs = size_bufferJDBC;
              	msg.trans.response[sizecs] = '\0';
              	msg.trans.response_length = sizecs;
                
                Free(bufferJDBC);
                                            	
                //bzero(msg.trans.response, sizeof(msg.trans.response));                
                //msg.trans.response_length = size_bufferJDBC;

                msg.trans.writeset_length = 0;
                msg.trans.recordsUpdates = 0;
#ifdef DEBUG_QMSOCKETS
                printf("WriteSet: <%d> <%d>\n", (int*) msg.trans.writeset, bytes);
#endif                
                //Abort Transaction
                //printf("(QM%d) <abort> <%s>\n", qid, GetErrorMessage(dbreplica));
                /* Abort transaction */
                if (ExecuteTransaction(dbreplica, "ABORT") == -1) {
#ifdef FATAL_QMSOCKETS
                  printf("(QM%d) Error executing <abort> <%s>\n", qid, GetErrorMessage(dbreplica));
#endif
                  FreeResult(dbreplica);
                  Disconnect(dbreplica);
                  DestroyDB(&dbreplica);
                  //TODO ?
                  exit(0);
                }
                                
                FreeResult(dbreplica);

                /* Compensate transaction with another Begin transaction */
                //TODO review with no autocommit */
                if (ExecuteTransaction(dbreplica, "BEGIN") == -1) {
                  #ifdef ERROR_QMSOCKETS
                    printf("(QM%d) Error PQexec postgres <%s>\n", qid, GetErrorMessage(dbreplica));
                    printf("(QM%d) ERROR executing begin\n", qid);
                  #endif
                  FreeResult(dbreplica);
                  //TODO ckeck, no es posible emplear postAbort en QM
                  //postAbort(msg.trans.transaction.tid);
                  //continue;
                }
                FreeResult(dbreplica);
                //printf("(QM%d) <abort> <END>\n", qid);
                
                if (stp == CDB){
#ifdef DEBUG_QMSOCKETS                	                	                	
                	int i;
#endif                	
                	//Send Notification response
	                msg.type = NOT_response;
	                msg.size = msg.trans.response_length;
	                copyBuffer (msg.buffer, msg.trans.response, msg.size);//QMMessage_buffer

#ifdef DEBUG_QMSOCKETS	                
					//printf("Error Response CDB: <%s>\n", msg.buffer);
					printf("RESPONSE CDB: ");
                	for (i=0; i<TAMBUFFERJDBC;i++){
                		printf("%c", msg.trans.response[i]);
                		if (i == msg.trans.response_length){
                			printf("|");
                		}
                	}
                	printf("\n");
#endif                	
#ifdef DEBUG_QMSOCKETS	                                		                
	                printf("RESPONSE CDB: ");
                	for (i=0; i<TAMBUFFERJDBC;i++){
                		printf("%c", msg.buffer[i]);
                		if (i == msg.size){
                			printf("|");
                		}
                	}
                	printf("\n");
#endif
                	
	                bytes = sendQMMessage(notification_sock, &msg);
	                #ifdef DEBUG_QMSOCKETS_SEND_QMMESSAGE
	                  printf("(QM%d) (SEND 18) Bytes <%d> Message <%s> (NOT_response|QMMESSAGE)\n", qid, sizeof(msg), buf_JDBC);
	                #endif
	                //bytes = SendNOTResponseMsg(notification_sock, &msg, sizeof(msg), bufferJDBC, strlen(bufferJDBC));
	                if (bytes == -1) {
	                  #ifdef FATAL_QMSOCKETS
	                    printf("(QM%d) ERROR sending datas to notification_sock\n", qid);
	                  #endif
	                  //Free(bufferJDBC);
	                  Disconnect(dbreplica);
	                  DestroyDB(&dbreplica);
	                  //TODO ?
	                  exit(1);
	                }
                } else {
#ifdef DEBUG_QMSOCKETS                	
                	int i;
                	//printf("Error Response !CDB: <%s>\n", msg.trans.response);
                	printf("RESPONSE NOT CDB: ");
	                for (i=0; i<TAMBUFFERJDBC;i++){
	                	printf("%c", msg.trans.response[i]);
	                }
	                printf("\n");
#endif	                
                }                                              
              } /* if (!msg.trans.transaction.isQuery) */
            } /* if (msg.trans.error) */

            //printf("SENDING a writeset of %d bytes\n", msg.trans.writeset_length);
            //printf("SENDING a response of %d bytes\n", msg.trans.response_length);

            // send the notification to the thread
            // TODO make the message shorter
            if (stp == CDB) {
              bytes = SendNOTToNotificationThread(NOT_cdb, msg.trans.mclientId, notification_sock, &msg, sizeof(msg));
            } else {
              bytes = SendNOTToNotificationThread(NOT_exec, msg.trans.mclientId, notification_sock, &msg, sizeof(msg));
            }

            #ifdef DEBUG_QMSOCKETS_SEND
            printf("(QM%d) (SEND 17) Bytes <%d> Message <---> (NOT_cdb|NOT_exec)\n", qid, sizeof(msg));
            #endif
            if (bytes == -1) {
            #ifdef FATAL_QMSOCKETS
              printf("(QM%d) ERROR sending datas to notification_sock\n", qid);
            #endif
              //TODO ?
              exit(1);
            }
          }
//printf("HOLA 4");          
          break;

        case QM_commit:
#ifdef DEBUG_QMSOCKETS_COMMIT
          count_commit++; //TODO Quitar
#endif
         #ifdef NOTIFICATION_DEBUG_QMSOCKETS
            printf("(QM%d) QM_COMMIT: %d\n", qid, msg.trans.transaction.tid);
         #endif

          // send commit to postgres
          if (ExecuteTransaction(dbreplica, "END") == -1) {
            #ifdef FATAL_QMSOCKETS
              printf("(QM%d) Error executing <end> in postgres <%s>\n", qid, GetErrorMessage(dbreplica));
            #endif
            Disconnect(dbreplica);
            DestroyDB(&dbreplica);
            //TODO ?
            exit(0);
          }

#ifdef DEBUG_QMSOCKETS_LOG
          bzero(buffer_log, sizeof(buffer_log));
          sprintf(buffer_log, "COMMIT: <%d> STATUS: <%d>\n", msg.trans.transaction.tid, 0);
          write_in_log_qm(&logqm, buffer_log);
#endif

          //if (msg.trans.local){//TODO Quitar
            msg.trans.recordsUpdates = atoi(GetRowsAffected(dbreplica));
          //}
          FreeResult(dbreplica);

          /*if (msg.early.isfirst_petition > 0){
            msg.early.isfirst_petition--;
          }*/
          
		  /* Update last petition */
          //msg.early.last_petition = (msg.trans.idConnection * MAX_PETITION_PER_CLIENT) + msg.trans.idPetition;

          // send the notification to the thread
#ifdef DEBUG_QMSOCKETS_SEND_QMMESSAGE
            printf("(QM%d) (SEND 21) Bytes <%d> Message <---> (NOT_commit|commit|QMMESSAGE)\n", qid, sizeof(msg));
#endif
          bytes = SendNOTToNotificationThread(NOT_commit, msg.trans.mclientId, notification_sock, &msg, sizeof(msg));
          if (bytes == -1) {
            #ifdef FATAL_QMSOCKETS
              printf("(QM%d) ERROR sending datas to notification_sock\n", qid);
            #endif
            exit(1);
          }

//Tprintf("DISCON <%d> <%d> <%d> 7\n", msg.trans.transaction.tid, msg.trans.idConnection, msg.trans.idPetition);   
          if ((msg.discon.is_delay_disconnect) && (msg.discon.send_discon_message)){
            //printf("(QM%d) QM Execute disconnect_petition <%d> last_petition <%d> is_first <%d>\n", msg.trans.qid, disconnect_petition, last_petition, 0);
            printf("(QM%d) APPLY Delay idConnection[%d] thId[%d]\n", qid, msg.trans.idConnection, msg.trans.mclientId);
            sendNotificationDisconnect(notification_sock, qid, msg.discon.tid, dbname, msg.discon.backup_stp, msg.discon.idConnection, msg.discon.idPetition);            

#ifdef DEBUG_QMSOCKETS_LOG
              bzero(buffer_log, sizeof(buffer_log));
              sprintf(buffer_log, "DELAYDISCON: <%d> STATUS: <%d>\n", msg.trans.transaction.tid, 0);
              write_in_log_qm(&logqm, buffer_log);
#endif           
          }
          break;

        case QM_abort:
          #ifdef NOTIFICATION_DEBUG_QMSOCKETS
            printf("(QM%d) QM_ABORT: %d\n", qid, msg.trans.transaction.tid);
          #endif

          // send abort to postgres
          if (autocommit) {
            if (ExecuteTransaction(dbreplica, "ABORT") == -1) {
              #ifdef FATAL_QMSOCKETS
                printf("(QM%d) Error executing <abort> <%s>\n", qid, GetErrorMessage(dbreplica));
              #endif
              FreeResult(dbreplica);
              Disconnect(dbreplica);
              DestroyDB(&dbreplica);
              //TODO ?
              exit(0);
            }
            FreeResult(dbreplica);
          }

#ifdef DEBUG_QMSOCKETS_LOG
          bzero(buffer_log, sizeof(buffer_log));
          sprintf(buffer_log, "ABORT: <%d> STATUS: <%d>\n", msg.trans.transaction.tid, 0);
          write_in_log_qm(&logqm, buffer_log);
#endif

          // send the notification to the thread
#ifdef DEBUG_QMSOCKETS_SEND_QMMESSAGE
            printf("(QM%d) (SEND 22) Bytes <%d> Message <---> (NOT_abort|QMMESSAGE)\n", qid, sizeof(msg));
#endif
          bytes = SendNOTToNotificationThread(NOT_abort, msg.trans.mclientId, notification_sock, &msg, sizeof(msg));
          if (bytes == -1) {
#ifdef FATAL_QMSOCKETS
              printf("(QM%d) ERROR sending datas to notification_sock\n", qid);
#endif
            exit(1);
          }
          break;

        case QM_apply_ws_and_commit:
          //msg.trans.recordsUpdates = 601;//TODO Quitar
#ifdef DEBUG_QMSOCKETS_COMMIT
          count_commit_ws++; //TODO Quitar
#endif
          #ifdef NOTIFICATION_DEBUG_QMSOCKETS
            printf("(QM%d) QM_apply_ws_and_commit: %d\n", qid, msg.trans.transaction.tid);
          #endif

          // send ws to postgres
          if ((!msg.trans.error) && (msg.trans.writeset_length != 0)) {
            // send ws to postgres
            #ifdef DEBUG_QMSOCKETS
              printf("QM%d sending ws tid %d to postgres\n", qid, msg.trans.transaction.tid);
            #endif

            #ifdef DEBUG_QMSOCKETS_WRITESET
              printf("APPLYING a writeset of %d bytes\n", msg.trans.writeset_length);
              printf("put_writeset: ");
              for(writeset_index = 0; writeset_index < msg.trans.writeset_length; writeset_index++){
                printf("%c", msg.trans.writeset[writeset_index]);
              }
            #endif
            //TODO control errores setwriteset
            status = SetWriteSet(dbreplica, msg.trans.writeset, msg.trans.writeset_length);
          }

#ifdef DEBUG_QMSOCKETS_LOG
          bzero(buffer_log, sizeof(buffer_log));
          sprintf(buffer_log, "APPLYWSANDCOMMIT: <%d> STATUS: <%d>\n", msg.trans.transaction.tid, status);
          write_in_log_qm(&logqm, buffer_log);
#endif

          //msg.trans.recordsUpdates = 602;//TODO Quitar

		  /*if (msg.early.isfirst_petition > 0){
            msg.early.isfirst_petition--;
          }*/

          /* Update last petition */
          //msg.early.last_petition = (msg.trans.idConnection * MAX_PETITION_PER_CLIENT) + msg.trans.idPetition;
          
          // send commit to postgres
          // send the notification to the thread
#ifdef DEBUG_QMSOCKETS_SEND_QMMESSAGE
            printf("(QM%d) (SEND 23) Bytes <%d> Message <---> (NOT_commit|apply_ws_and_commit|QMMESSAGE)\n", qid, sizeof(msg));
#endif
          bytes = SendNOTToNotificationThread(NOT_commit, msg.trans.mclientId, notification_sock, &msg, sizeof(msg));
          if (bytes == -1) {
#ifdef FATAL_QMSOCKETS
            printf("(QM%d) ERROR sending datas to notification_sock\n", qid);
#endif
            //TODO ?
            exit(1);
          }          

//Tprintf("DISCON <%d> <%d> <%d> 8\n", msg.trans.transaction.tid, msg.trans.idConnection, msg.trans.idPetition);   
          if ((msg.discon.is_delay_disconnect) && (msg.discon.send_discon_message)){
            //printf("1(QM%d) QM Execute disconnect_petition <%d> last_petition <%d> is_first <%d>\n", msg.trans.qid, disconnect_petition, last_petition, 0);
            printf("1(QM%d) APPLY Delay idConnection[%d] thId[%d]\n", qid, msg.trans.idConnection, msg.trans.mclientId);
            sendNotificationDisconnect(notification_sock, qid, msg.discon.tid, dbname, msg.discon.backup_stp, msg.discon.idConnection, msg.discon.idPetition);            

#ifdef DEBUG_QMSOCKETS_LOG
              bzero(buffer_log, sizeof(buffer_log));
              sprintf(buffer_log, "APLLYWSANDCOMMIT DELAYDISCON: <%d> STATUS: <%d>\n", msg.trans.transaction.tid, 0);
              write_in_log_qm(&logqm, buffer_log);
#endif           
          }
          break;

        default:
          #ifdef ERROR_QMSOCKETS
            printf("(QM%d) Error kind_of_QM message incorrect %d\n", qid, msg.type);
          #endif
        } // switch
//        printf("HOLA 5");
      } //while ((stp != DISCON) && (stp != EARLY_DISCON)) && (bytes > 0))
#ifdef DEBUG_QMSOCKETS_LOG
      close_log(&logqm);
#endif

#ifdef DEBUG_QMSOCKETS_COMMIT
      printf("(QM%d)------------->Received %d COMMIT\n", qid, count_commit); //TODO quitar
      printf("(QM%d)------------->Received %d APPLYWSANDCOMMIT\n", qid, count_commit_ws); //TODO quitar
      printf("(QM%d)------------->Received %d ALL\n", qid, count_commit+count_commit_ws); //TODO quitar
#endif
      /* Free the last QMMessage received */
    //printf ("%s:%d resetQMMessage IN\n", __FILE__, __LINE__ );
    //resetQMMessage(&msg);
    //printf ("%s:%d resetQMMessage OUT\n", __FILE__, __LINE__ );

    //Disconnect(dbreplica);
    //DestroyDB(&dbreplica);
    

    //printf("(QM%d) 3\n", qid);
#ifdef DEBUG_QMSOCKETS_CLOSE
    printf("(QM%d) Close Socket <%d> File: %s Line: %d\n", qid, sock, __FILE__, __LINE__);
#endif
    close(sock);
    //printf("(QM%d) 4\n", qid);
    //Disconnect(dbreplica);
    //DestroyDB(&dbreplica);
    //printf("(QM%d) 5\n", qid);
    #ifdef WARN_QMSOCKETS
      printf("(QM%d) finishing\n", qid);
    #endif
    exit(0);
  }
}

/********************************************************************************
Reusable Function.
   void QMSpecial (int sock);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void QM(int qid, int sock){
  switch (TYPECLIENT) {
  case 0 :
    oldClient (qid, sock);
    break;
  case 1:
    pgserverClient (qid, sock);
    break;
  }
}

/********************************************************************************
Reusable Function.
   void QMSpecial (int sock);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void QMFactory() {
  int sock, newsock, sockThread;
  int qid = 0, i;
  static struct utsname node_name;
  char server[MAXSERVERPATH /*+ EXTRASIZE - RMEXTRASIZE*/];
  char nameSocketThread[200 /*+ EXTRASIZE - RMEXTRASIZE*/];
  char *nodename = NULL;

  //JSalas FALTA ponerlo en una funcion
  uname(&node_name);
  //strcpy(server, PATH); //JSalas
  //strcat(server, "/dcadena/bdreplicadasDavid/"); //JSalas
  nodename = strtok(node_name.nodename, ".");
  strcpy(server, getcwd (NULL, MAXSERVERPATH - (1 + strlen(nodename) + EOF_SIZE)));
  strcat(server, "/");
  strcat(server, nodename);

  /* Create socket */
  sock = sockcreate(server);
  if (sock == -1) {
    perror("sockcreate");
    exit(1);
  }

  /* Create as many conections as QMs + 2. */
  /* For the notification thread and QMSpecial */
  notification_sock = sockaccept(sock);

  for (i=0;i<=MAXQM;i++) {
    /* Accept connections */
    newsock = sockaccept(sock);
    if (newsock < 0) {
      perror("sockaccept");
      exit(1);
    }

    if (createProcess() == 0) {
      /* Don't need old socket */
#ifdef DEBUG_QMSOCKETS_CLOSE
      printf("(QM%d) Close Socket <%d> File: %s Line: %d\n", qid, sock, __FILE__, __LINE__);
#endif
      close(sock);
      QM(qid, newsock);

    }else{
      qid++;
#ifdef DEBUG_QMSOCKETS_CLOSE
      printf("(FactoryQM) Close Socket <%d> File: %s Line: %d\n", newsock, __FILE__, __LINE__);
#endif
      close(newsock);
    }
  }
  /*if (0){//TODO DELETE
  	QM_message msg;
    initQMMessage(&msg);
    SendNOTResponseMsg(notification_sock, &msg, sizeof(msg), "HOLA", 4);
    printf("SE HA ACABADO");
    exit(0);
  }*/
  //exit(0); JSalas
}

int count_noticommit = 0; //TODO Quitar
/********************************************************************************
Reusable Function.
   void QMSpecial (int sock);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void TransNotificationThread(char* dummy) {
  QM_message msg;
  int err, i, bytes, stp;
  //char buffer[100];
  int rval = 0;
  log_t log_flag;

#ifdef DEBUG_FILES_FLAG
  char buffer_log[2048];
  init_log_flag(&log_flag, "all_TransNotificationThread");
#endif

  initQMMessage(&msg); //08092004
  running=1;
  while(running) {
    //err=recv(not_sock, (char*) &msg, sizeof(msg), 0);
#ifdef DEBUG_QMSOCKETS_RECV_QMMESSAGE
    printf("(TransNotificationThread) Waiting QMMessage ...\n");
#endif
//printf("(TransNotificationThread) IN recvQMMessage\n");
    err = recvQMMessageTest(not_sock, &msg, "(TransNotificationThread)");
//printf("(TransNotificationThread) OUT recvQMMessage <%d>\n", msg.trans.transaction.tid);    
#ifdef DEBUG_QMSOCKETS_RECV_QMMESSAGE
    //Se para a veces printf("(TransNotificationThread) (RECV 9) Bytes <%d> Message <TYPE:%d> StructSize <%d> (QMMessage|NOTIFICATION)\n", err, msg.type, sizeof(msg));
#endif
    if (err<0) { break; }

    //printf("EndTrans received: %d ", msg.trans.transaction.tid);

    if (msg.type == NOT_exec) {
#ifdef DEBUG_FILES_FLAG
      //char buffer_log[2048];
      bzero(buffer_log, sizeof(buffer_log));
      sprintf(buffer_log, "TransNotificationThread NOT_exec TID: <%d> | Status <%d>\n", msg.trans.transaction.tid, err);
      write_in_log_flag(&log_flag, buffer_log);
#endif

#ifdef NOTIFICATION_DEBUG_QMSOCKETS
      printf(" (NOT_exec)\n");
#endif
      if (postExecute(msg.trans.transaction.tid, msg.trans.writeset, msg.trans.writeset_length, msg.trans.response, msg.trans.response_length, msg.trans.recordsUpdates) < 0){
#ifdef DEBUG_FILES_FLAG
        close_log(&log_flag);
#endif
        exit(0);
      }
	  if (msg.trans.transaction.isQuery){
	  	FreeQM(msg.trans.qmId);
	  }	
    } else if (msg.type == NOT_commit) {
#ifdef DEBUG_FILES_FLAG
      //char buffer_log[2048];
      bzero(buffer_log, sizeof(buffer_log));
      sprintf(buffer_log, "TransNotificationThread NOT_commit TID: <%d> | Status <%d>\n", msg.trans.transaction.tid, err);
      write_in_log_flag(&log_flag, buffer_log);
#endif

#ifdef NOTIFICATION_DEBUG_QMSOCKETS
      printf("(NOT_commit)\n");
#endif
	  	  
      count_noticommit++; //TODO Quitar
      //printf("NOT_COMMIT <%s>\n", count_noticommit); //TODO Quitar
      //printf("RECORDS UPDATE <%s>\n", msg.trans.recordsUpdates); //TODO Quitar
//printf("(NOT_commit) 0\n");
      FreeQM(msg.trans.qmId);
//printf("(NOT_commit) 1\n");      
      postCommit(msg.trans.transaction.tid, msg.trans.recordsUpdates);
//printf("(NOT_commit) 2\n");      

    } else if (msg.type == NOT_abort) {
#ifdef DEBUG_FILES_FLAG
      //char buffer_log[2048];
      bzero(buffer_log, sizeof(buffer_log));
      sprintf(buffer_log, "TransNotificationThread NOT_abort TID: <%d> | Status <%d>\n", msg.trans.transaction.tid, err);
      write_in_log_flag(&log_flag, buffer_log);
#endif

#ifdef NOTIFICATION_DEBUG_QMSOCKETS
      printf("(NOT_abort)\n");
#endif
      FreeQM(msg.trans.qmId);
      postAbort(msg.trans.transaction.tid);

    } else if (msg.type == NOT_connection) {
      char dbname[MAXDBNAME];
      bzero(dbname, sizeof(dbname));
      sscanf(&msg.trans.transaction.sqlcode[3], "%s", dbname);
      //printf("connection dbname <%s>\n", dbname);

#ifdef DEBUG_FILES_FLAG
      //char buffer_log[2048];
      bzero(buffer_log, sizeof(buffer_log));
      sprintf(buffer_log, "TransNotificationThread NOT_connection TID: <%d> | Status <%d>\n", msg.trans.transaction.tid, err);
      write_in_log_flag(&log_flag, buffer_log);
#endif

#ifdef NOTIFICATION_DEBUG_QMSOCKETS
      printf("(NOT_connection)\n");
#endif
      FreeQM(msg.trans.qmId);
//      printf("(NOT_connection) 1\n");
      postConnection(msg.trans.transaction.tid, dbname);
//      printf("(NOT_connection) 2\n");

    } else if (msg.type == NOT_cdb) {
#ifdef DEBUG_FILES_FLAG
      //char buffer_log[2048];
      bzero(buffer_log, sizeof(buffer_log));
      sprintf(buffer_log, "TransNotificationThread NOT_CDB TID: <%d> | Status <%d>\n", msg.trans.transaction.tid, err);
      write_in_log_flag(&log_flag, buffer_log);
#endif

#ifdef NOTIFICATION_DEBUG_QMSOCKETS
        printf("(NOT_CDB)\n");
#endif
//printf("prueba 1\n");
      //FreeQM(msg.trans.qid);JSALAS COMMENT THIS 28102004
//
      postCDB(msg.trans.transaction.tid, msg.trans.response, msg.trans.response_length, msg.trans.recordsUpdates);
//printf("prueba 2\n");
    } else if (msg.type == NOT_disconnect) {
      int stp;
      int connection_petition = 0;

#ifdef DEBUG_FILES_FLAG
      //char buffer_log[2048];
      bzero(buffer_log, sizeof(buffer_log));
      sprintf(buffer_log, "TransNotificationThread NOT_disconnect TID: <%d> | Status <%d>\n", msg.trans.transaction.tid, err);
      write_in_log_flag(&log_flag, buffer_log);
#endif

#ifdef NOTIFICATION_DEBUG_QMSOCKETS
      printf("(NOT_disconnect)\n");
#endif
      sscanf(&msg.trans.transaction.sqlcode[0], "%d", &stp);
      //printf("postDisconnectLock <%s>", msg.trans.transaction.sqlcode);
//#ifdef NOTIFICATION_DEBUG_QMSOCKETS
        //Tprintf("(NOT_disconnect) <%d> <%d> <%d>\n", msg.trans.idConnection, msg.trans.idPetition, stp);
//#endif
      if ((stp == EARLY_DISCON) || (stp == DELAY_EARLY_DISCON)) {
        char dbname[MAXDBNAME];
        bzero(dbname, sizeof(dbname));
        sscanf(&msg.trans.transaction.sqlcode[3], "%s", dbname);
        //printf("disconnection dbname <%s>\n", dbname);
        if (stp == EARLY_DISCON){
          FreeQM(msg.trans.qmId);
        }
        if (stp == EARLY_DISCON){
        	printf("EARLY_DISCON <%d> <%d>\n", msg.trans.idConnection, msg.trans.idPetition);        
        }else{
        	printf("DELAY_EARLY_DISCON <%d> <%d>\n", msg.trans.idConnection, msg.trans.idPetition);        
        }
        postDisconnect(msg.trans.transaction.tid, 1, 0, dbname);

      } else {
        char dbname[MAXDBNAME];
        bzero(dbname, sizeof(dbname));
        sscanf(&msg.trans.transaction.sqlcode[3], "%s", dbname);
        //printf("disconnection dbname <%s>\n", dbname);
        if (stp != DELAY_DISCON){
          //printf("stp == <%d> -> FreeQM <%d>\n", stp, msg.trans.qid);
          FreeQM(msg.trans.qmId);
          //printf("END Free QM <%d>\n", msg.trans.qid);
          //printf("NOT DELAY_DISCON <%d> <%d>\n", msg.trans.idConnection, msg.trans.idPetition);
        }else{
        	//printf("DELAY_DISCON <%d> <%d>\n", msg.trans.idConnection, msg.trans.idPetition);
        }
        connection_petition = (msg.trans.idConnection * MAX_PETITION_PER_CLIENT) + 0; /*msg.trans.idPetition*/        
        postDisconnect(msg.trans.transaction.tid, 0, connection_petition, dbname);
      }

    } else if (msg.type == NOT_response) {
#ifdef DEBUG_FILES_FLAG
      //char buffer_log[2048];
      bzero(buffer_log, sizeof(buffer_log));
      sprintf(buffer_log, "TransNotificationThread NOT_response TID: <%d> | Status <%d>\n", msg.trans.transaction.tid, err);
      write_in_log_flag(&log_flag, buffer_log);
#endif

#ifdef NOTIFICATION_DEBUG_QMSOCKETS
      printf("  (NOT_response)\n");
#endif
      sscanf(&msg.trans.transaction.sqlcode[0], "%d", &stp);
      if (stp == CDB) {
        if (msg.trans.localNode) {
          //printf("1!!!!!!!!!!responseToThread <%s><%d><%d><%d><%s>\n", /*msg.buffer*/"", msg.size, msg.trans.mclientId, msg.trans.localNode, /*msg.trans.transaction.endpoint*/"");
          responseToThread (msg.trans.idConnection, msg.buffer, msg.size, msg.trans.mclientId, msg.trans.localNode, msg.trans.transaction.endpoint);//QMMessage_buffer
        }

      } else {
      	//printf("2!!!!!!!!!!responseToThread <%s><%d><%d><%d><%s>\n", /*msg.buffer*/"", msg.size, msg.trans.mclientId, msg.trans.localNode, /*msg.trans.transaction.endpoint*/"");
        responseToThread (msg.trans.idConnection, msg.buffer, msg.size, msg.trans.mclientId, msg.trans.localNode, msg.trans.transaction.endpoint);
      }

    } else if (msg.type == NOT_freeqm) {
#ifdef NOTIFICATION_DEBUG_QMSOCKETS
      printf("  (NOT_freeqm)\n");
#endif    	
      //printf("INI Free QM <%d>\n", msg.trans.qid);
      FreeQM(msg.trans.qmId);
      //printf("END Free QM <%d>\n", msg.trans.qid);

    } else {
#ifdef DEBUG_FILES_FLAG
      //char buffer_log[2048];
      bzero(buffer_log, sizeof(buffer_log));
      sprintf(buffer_log, "TransNotificationThread Error NOT_type incorrect <%d> TID: <%d> | Status <%d>\n", msg.type, msg.trans.transaction.tid, err);
      write_in_log_flag(&log_flag, buffer_log);
#endif

#ifdef ERROR_QMSOCKETS
  printf("Error NOT_type incorrect %d\n", msg.type);
#endif
    }

    /* Free the last QMMessage received */
    //printf ("%s:%d resetQMMessage IN\n", __FILE__, __LINE__ );
    resetQMMessage(&msg);
    //printf ("%s:%d resetQMMessage OUT\n", __FILE__, __LINE__ );
  } /* while(running) */

#ifdef WARN_QMSOCKETS
  printf("TransNotificationThread finishing\n");
#endif
  exit(0);
}

/********************************************************************************
Reusable Function.
   void QMSpecial (int sock);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void FillStoredProcs() {
  int com, id;
  int ups, qs;

  // 1 short Update stored procedure
  num_commands[UPD1]=1;
  strcpy(stored_procs[UPD1][0], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
  num_params[UPD1][0]= 7;

  // 1 short update + 1 short query
  num_commands[UPD1SQ1]= 2;
  strcpy(stored_procs[UPD1SQ1][0], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
  num_params[UPD1SQ1][0]= 7;
  strcpy(stored_procs[UPD1SQ1][1], "select avg(t_%s_param3), sum(t_%s_param3) from t_%s;");
  num_params[UPD1SQ1][1]= 3;

  // 1 long query
  num_commands[LQ1]= 1;
  strcpy(stored_procs[LQ1][0], "select * from t_%s;");
  num_params[LQ1][0]= 1;

  // 3 short updates + 1 short query
  id=UPD3SQ1;
  num_commands[id]= 4;
  com=0;
  strcpy(stored_procs[id][com], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
  num_params[id][com]= 7;
  com++;
  strcpy(stored_procs[id][com], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
  num_params[id][com]= 7;
  com++;
  strcpy(stored_procs[id][com], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
  num_params[id][com]= 7;
  com++;
  strcpy(stored_procs[id][com], "select avg(t_%s_param3), sum(t_%s_param3) from t_%s;");
  num_params[id][com]= 3;

  // 6 short updates + 1 short query
  id=UPD6SQ1;
  num_commands[id]= 7;
  com=0;
  strcpy(stored_procs[id][com], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
  num_params[id][com]= 7;
  com++;
  strcpy(stored_procs[id][com], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
  num_params[id][com]= 7;
  com++;
  strcpy(stored_procs[id][com], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
  num_params[id][com]= 7;
  com++;
  strcpy(stored_procs[id][com], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
  num_params[id][com]= 7;
  com++;
  strcpy(stored_procs[id][com], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
  num_params[id][com]= 7;
  com++;
  strcpy(stored_procs[id][com], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
  num_params[id][com]= 7;
  com++;
  strcpy(stored_procs[id][com], "select avg(t_%s_param3), sum(t_%s_param3) from t_%s;");
  num_params[id][com]= 3;

  // 2 short queries
  id=SQ1SQ1;
  num_commands[id]= 2;
  com=0;
  strcpy(stored_procs[id][com], "select avg(t_%s_param3), sum(t_%s_param3) from t_%s;");
  num_params[id][com]= 3;
  com++;
  strcpy(stored_procs[id][com], "select avg(t_%s_param3), sum(t_%s_param3) from t_%s;");
  num_params[id][com]= 3;

  // 8 short updates
  id=UPD8;
  ups = 8;
  qs=0;
  num_commands[id]= ups+qs;

  for (com=0;com<ups;com++) {
    strcpy(stored_procs[id][com], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
    num_params[id][com]= 7;
  }

  // 9 short updates 1 short query
  id=UPD9SQ1;
  ups= 9;
  qs= 1;
  num_commands[id]= ups+qs;

  for (com=0;com<ups;com++) {
    strcpy(stored_procs[id][com], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
    num_params[id][com]= 7;
  }
  for (com=ups;com<ups+qs;com++) {
    strcpy(stored_procs[id][com], "select avg(t_%s_param3), sum(t_%s_param3) from t_%s;");
    num_params[id][com]= 3;
  }

  // 6 short updates 2 short queries
  id=UPD4SQ2;
  ups= 4;
  qs= 2;
  num_commands[id]= ups+qs;


  for (com=0;com<ups;com++) {
    strcpy(stored_procs[id][com], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
    num_params[id][com]= 7;
  }
  for (com=ups;com<ups+qs;com++) {
    strcpy(stored_procs[id][com], "select avg(t_%s_param3), sum(t_%s_param3) from t_%s;");
    num_params[id][com]= 3;
  }

  // 3 short updates 3 short queries
  id=UPD3SQ3;
  ups= 3;
  qs= 3;
  num_commands[id]= ups+qs;

  for (com=0;com<ups;com++) {
    strcpy(stored_procs[id][com], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
    num_params[id][com]= 7;
  }
  for (com=ups;com<ups+qs;com++) {
    strcpy(stored_procs[id][com], "select avg(t_%s_param3), sum(t_%s_param3) from t_%s;");
    num_params[id][com]= 3;
  }

  // 4 short queries
  id=SQ4;
  ups= 0;
  qs= 4;
  num_commands[id]= ups+qs;

  for (com=ups;com<ups+qs;com++) {
    strcpy(stored_procs[id][com], "select sum(t_%s_param3) from t_%s;");
    num_params[id][com]= 2;
  }

  // 1 short query
  id=SQ1;
  num_commands[id]= 1;
  com=0;
  strcpy(stored_procs[id][com], "select avg(t_%s_param3), sum(t_%s_param3) from t_%s;");
  num_params[id][com]= 3;

  // 8 short updates
  id=UPD5;
  ups = 5;
  qs=0;
  num_commands[id]= ups+qs;

  for (com=0;com<ups;com++) {
    strcpy(stored_procs[id][com], "update t_%s set t_%s_param1 = 'blub%s', t_%s_param2 = t_%s_param2 + 4 where t_%s_id = %s;");
    num_params[id][com]= 7;
  }

  // dcadena
  // generic query
  id=SQG;
  num_commands[id]=1;
  com=0;
  strcpy(stored_procs[id][com], "%s");
  num_params[id][com]=1;

  // generic update
  id=UPDG;
  num_commands[id]=1;
  com=0;
  strcpy(stored_procs[id][com], "%s");
  num_params[id][com]=1;

  // generic change database query
  id=CDB;
  num_commands[id]=1;
  com=0;
  strcpy(stored_procs[id][com], "%s");
  num_params[id][com]=1;

  // begin transaction
  id=BEG;
  num_commands[id]=1;
  com=0;
  strcpy(stored_procs[id][com], "begin");
  num_params[id][com]=0;

  // end transaction
  id=END;
  num_commands[id]=1;
  com=0;
  strcpy(stored_procs[id][com], "end");
  num_params[id][com]=0;

  // abort transaction
  id=ABO;
  num_commands[id]=1;
  com=0;
  strcpy(stored_procs[id][com], "abort");
  num_params[id][com]=0;

  // connection
  id=CON;
  num_commands[id]=1;
  com=0;
  strcpy(stored_procs[id][com], "%s");
  // the param is the name of database
  num_params[id][com]=1;

  // connection
  id=RECON;
  num_commands[id]=1;
  com=0;
  strcpy(stored_procs[id][com], "%s");
  // the param is the name of database
  num_params[id][com]=1;
  
  // connection
  id=CON_RESPONSE;
  num_commands[id]=1;
  com=0;
  strcpy(stored_procs[id][com], "%s");
  // the param is the name of database
  num_params[id][com]=1;


  // disconnection

  id=DISCON;
  num_commands[id]=1;
  com=0;
  strcpy(stored_procs[id][com], "");
  num_params[id][com]=0;

  // disconnection_response

  id=DISCON_RESPONSE;
  num_commands[id]=1;
  com=0;
  strcpy(stored_procs[id][com], "");
  num_params[id][com]=0;
  
  // early disconnection

  id=EARLY_DISCON;
  num_commands[id]=1;
  com=0;
  strcpy(stored_procs[id][com], "");
  num_params[id][com]=0;

  // early delay disconnection
  id=DELAY_EARLY_DISCON;
  num_commands[id]=1;
  com=0;
  strcpy(stored_procs[id][com], "");
  num_params[id][com]=0;
  
  // delay disconnection

  id=DELAY_DISCON;
  num_commands[id]=1;
  com=0;
  strcpy(stored_procs[id][com], "");
  num_params[id][com]=0;

 } //FillStoredProcs

int hasFreeConQM(){
	Dllist_item_ptr qm;
	int stateId;
	
	if (Dllist_isEmpty(freeConQMs)){
		return -1;
	}
	
	qm = Dllist_first(freeConQMs);		
	stateId = *(int *)(qm->item);
	
	return stateId;
}

int hasFreeDBQM(T_Dllist_ptr queue){
	Dllist_item_ptr qm;
	int stateId;
	QMStateLink *link;
	
	if (Dllist_isEmpty(queue)){
		return -1;
	}	
	
	/* Dequeue reuse QM */
	qm = Dllist_first(queue);		
	link = (QMStateLink *)(qm->item);
	stateId = link->stateId;
	
	return stateId;
}

int hasFreeQM(){
	Dllist_item_ptr qm;
	int stateId;
	
	if (Dllist_isEmpty(freeQMs)){
		return -1;
	}
	
	qm = Dllist_first(freeQMs);		
	stateId = *(int *)(qm->item);
	
	return stateId;
}

void GetFreeConQM(char *dbname){
	Dllist_item_ptr qm;
	int stateId;
	
	qm = Dllist_dequeue(freeConQMs);		
	stateId = *(int *)(qm->item);
	
	/* Change State */	    
    stateQMs[stateId].state = BUSY;
    stateQMs[stateId].token = qm;
    strcpy(stateQMs[stateId].dbname, dbname);
    
    /* Remove reuse link? */     
	if (stateQMs[stateId].linkstate != NULL){
		Dllist_extract(stateQMs[stateId].linkstatequeue, stateQMs[stateId].linkstate);		
	}
}

void GetFreeDBQM(T_Dllist_ptr queue, char *dbname){
	Dllist_item_ptr qm;
	int stateId;
	QMStateLink *link;
	
	/* Dequeue reuse QM */
	qm = Dllist_dequeue(queue);		
	link = (QMStateLink *)(qm->item);
	stateId = link->stateId;
	
	stateQMs[stateId].linkstate = qm;  
    stateQMs[stateId].linkstatequeue = queue;
	
	/* Change State */	    
    stateQMs[stateId].state = BUSY;
    strcpy(stateQMs[stateId].dbname, dbname);
    
    /* Dequeue Free Connected QM */
    qm = stateQMs[stateId].token;
    Dllist_extract(freeConQMs, qm);		
}

void GetFreeQM(char *dbname){
	Dllist_item_ptr qm;
	int stateId;
	
	qm = Dllist_dequeue(freeQMs);		
	stateId = *(int *)(qm->item);
	
	/* Change State */	    
    stateQMs[stateId].state = BUSY;
    stateQMs[stateId].token = qm;
    strcpy(stateQMs[stateId].dbname, dbname);
}

void doConnect(hot_uint32 qmId, enum kind_QM_state kind, QM_message *mess){
	QM_message newmess;
	int bytes = 0;
	int stp = 0;
//printf("doConnect(qmId = %d, kind = %d, mess->type = %d, sqlcode = %s)\n", qmId, kind, mess->type, mess->trans.transaction.sqlcode);
	if (kind == FREE){
//printf("doConnect 1\n");	
	    sscanf(&mess->trans.transaction.sqlcode[0], "%d", & stp);	
		if (stp != CON_RESPONSE){
//printf("doConnect 2\n");			
			initQMMessage(&newmess);//TODO remove
			cloneQMMessage(&newmess, mess);
			
			/* Prepare Connection Msg */
			bzero(newmess.trans.transaction.sqlcode, strlen(newmess.trans.transaction.sqlcode));
       		sprintf(newmess.trans.transaction.sqlcode, "%2d ", CON);
       		strcat(newmess.trans.transaction.sqlcode, mess->trans.transaction.dbname);
       		
			newmess.type = QM_execute;
			
			/* Send Connection Msg */
			bytes = sendQMMessage(sock[qmId], &newmess);
   			//printf("doConnect sendQMMessage CON sock[MAXQM]=%d\n", sock[MAXQM]);
   			if (bytes == -1) {
     			perror("send message\n");
   			}
   			
   			//freeQMMessage(newmess);
		}
	}else if (kind == FREECON){
//printf("doConnect 3\n");	
		sscanf(&mess->trans.transaction.sqlcode[0], "%d", & stp);	
		if (stp != CON_RESPONSE){
//printf("doConnect 4\n");			
			initQMMessage(&newmess);//TODO remove
            cloneQMMessage(&newmess, mess);
            
			/* Prepare Re-Connection Msg */
			bzero(newmess.trans.transaction.sqlcode, strlen(newmess.trans.transaction.sqlcode));
       		sprintf(newmess.trans.transaction.sqlcode, "%2d ", RECON);
       		strcat(newmess.trans.transaction.sqlcode, mess->trans.transaction.dbname);
			
			newmess.type=QM_execute;
			
			/* Send Re-Connection Msg */
			bytes = sendQMMessage(sock[qmId], &newmess);
   			//printf("doConnect sendQMMessage RECON sock[MAXQM]=%d\n", sock[MAXQM]);
   			if (bytes == -1) {
     			perror("send message\n");
   			}
   			
   			//freeQMMessage(newmess);
   			
		} else {
//printf("doConnect 5\n");			
			initQMMessage(&newmess);//TODO remove
			cloneQMMessage(&newmess, mess);
			
			/* Prepare Disconnection Msg */
			bzero(newmess.trans.transaction.sqlcode, strlen(newmess.trans.transaction.sqlcode));
       		sprintf(newmess.trans.transaction.sqlcode, "%2d ", DISCON);       		
			
			newmess.type=QM_execute;
			
			/* Send Disconnection Msg */
			bytes = sendQMMessage(sock[qmId], &newmess);
   			//printf("doConnect sendQMMessage DISCON sock[MAXQM]=%d\n", sock[MAXQM]);
   			if (bytes == -1) {
     			perror("send message\n");
   			}
   			
   			//freeQMMessage(&newmess);
		}							
	}
}

/********************************************************************************
Reusable Function.
   void QMSpecial (int sock);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
int GetQM(hot_uint32 qmId, QM_message *mess) {
  int value = -1;
       	 
#ifdef DEBUG_FILES_QUEUE
     char buffer_log[2048];
#endif
//printf("qmId=%d\n", qmId);  	
  //decSemaphore(&QM_mutex);
  /* Get specific QM (For QMSpecial) */
  if (qmId != MAXQM) {
//printf("1\n");  	
    if (qmId == -1){   	
    	struct itemhDBConns *found;
//printf("2\n");
		found = (struct itemhDBConns *)get_hashtable(&hDBConns, mess->trans.transaction.dbname);     	
		//if (found == null){}
    	if ((found != NULL) && ((value = hasFreeDBQM(found->reuseQM)) >= 0)) {
//printf("3\n");    		
    			GetFreeDBQM(found->reuseQM, mess->trans.transaction.dbname);    		
//printf("4\n");    			
    	 		
//printf("5\n");    		
    	} else if ((value = hasFreeQM()) >= 0){	
//printf("6\n");    		
			GetFreeQM(mess->trans.transaction.dbname);
			//Connection      		
			doConnect(value, FREE, mess);
			
    	} else if ((value = hasFreeConQM()) >= 0){
//printf("7\n");    		
    		GetFreeConQM(mess->trans.transaction.dbname); 
    		//Reconnection   		
    		doConnect(value, FREECON, mess);    		
    	} 
//printf("8\n");
#ifdef DEBUG_FILES_QUEUE
      		bzero(buffer_log, sizeof(buffer_log));
      		sprintf(buffer_log, "GetFreeQM <%d>\n", value);
      		write_in_log_qmqueue(&log_queue, buffer_log);
#endif

      	//incSemaphore(&QM_mutex);
     	return value;
    }else{
    	//TODO modificar cuando intervenga auto-commit no activado
    }
//printf("9\n");    
  } else { //TODO cambiar cuando QM Special se comporte como otro QM mas
//printf("10\n");  	
    stateQMs[qmId].state=FREE;
    //tQMThread[qmId]=qmId;
    //incSemaphore(&QM_mutex);
    return qmId;
  }
//printf("11\n");
  /* Get Free QM, search in all minus QMSpecial */
  /*
  for (i=0; i<MAXQM; i++){
    if (freeQMs[i]) {
      freeQMs[i]=0;
      tQMThread[i]=thId;
      incSemaphore(&QM_mutex);
      return i;
    }
  }
  */
  /* No free QM has been found */
  //incSemaphore(&QM_mutex);
#ifdef DEBUG_FILES_QUEUE
  bzero(buffer_log, sizeof(buffer_log));
  sprintf(buffer_log, "No GetFreeQM <%d>\n", thId);
  write_in_log_qmqueue(&log_queue, buffer_log);
#endif
  return -1;
}

/********************************************************************************
Reusable Function.
   void QMSpecial (int sock);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void FreeTQMThread(int qid) {

  decSemaphore(&QM_mutex);

  /* QM is not associated with Thread */
  /*QMID if (tQMThread[qid]==-1) {
    #ifdef FATAL_QMSOCKETS
      printf("Error releasing QM%d that is not associated with Thread\n", qid);
    #endif
    exit(1);
  }*/
  /* Deassociated QM with Thread */
  //QMID tQMThread[qid]= -1;

  incSemaphore(&QM_mutex);
}

/********************************************************************************
Reusable Function.

   void QMSpecial (int sock);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void FreeQM(int qid) {
  if (qid != MAXQM){
  	//printf("FREE QM%d ...\n", qid);
  	FreeQMBlock(qid);
  	//printf("FREE QM%d [OK]\n", qid);
  }

  /*decSemaphore(&QM_mutex);
  if (freeQMs[qid]) {
    //printf("error releasing QM%d that is already free\n", qid);
    //exit(1);
  }
  // Warning :

  // The QM must be marked as free
  // even if a message is taken from
  // the queue, as sendmessagetoqm will
  // search for a free slot
  freeQMs[qid]= 1;
  //incSemaphore(&QM_mutex); C

  //Exist transaction waiting for QM?
  CheckWaitingForQM(waitingforQM[qid], qid);

  incSemaphore(&QM_mutex);*/
}

/********************************************************************************
Reusable Function.
   void QMSpecial (int sock);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void InitTQMThread (){
  int i;

  /*for (i=0; i<MAXQM+1; i++){
    // Thread id = QM id
    tQMThread[i]= i;
  }*/
}


/********************************************************************************
Reusable Function.
   void QMSpecial (int sock);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void InitFreeQMs (){
  int i;
  int *value;

  freeQMs = Dllist_create(free);
  freeConQMs = Dllist_create(free);
  
  /* Initially all QMs are free */
  for (i=0; i<MAXQM+1; i++){  	
    stateQMs[i].stateId = i;
    stateQMs[i].linkstate = NULL;
    stateQMs[i].linkstatequeue = NULL;
    stateQMs[i].state = FREE;
    stateQMs[i].token = NULL;
    bzero(stateQMs[i].dbname, MAXDBNAME);
    
    //value = (int *) malloc (sizeof(struct QMToken));
    //value->qmId = i;
    //value->reuselink = NULL;
    if (i != MAXQM){/*ALWAYS QMSPECIAL IS BUSY */
      value = (int *) malloc (sizeof(int));
      *value = i;
      Dllist_insert(freeQMs, value);
    }
  }
}

/********************************************************************************
Reusable Function.
   void QMSpecial (int sock);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
void StartQMs () {
  // JSalas FALTA 128 y 80 cambiar
  char server[MAXSERVERPATH /*+ EXTRASIZE - RMEXTRASIZE*/];
  char *nodename = NULL;
  char input[80 /*+ EXTRASIZE - RMEXTRASIZE*/];
  //QM_message buffer;
  int i, bytes;
  static struct utsname node_name;

  /* Initialice */
  FillStoredProcs();
  InitFreeQMs();
  InitTQMThread();

  // Initially there no pending
  // messages for QMs
  //TODO mover debajo del switch
  for (i = 0; i < MAXQM+1; i++){
    waitingforQM[i]=QMQ_create();
  }

  switch (createProcess()) {
  case 0:
    QMFactory();
    exit(0);
    break;
  case -1:
    #ifdef FATAL_QMSOCKETS
      printf("Error forking\n");
    #endif
    exit(1);
  }

  // JSalas FALTA ponerlo en una funcio�n
  uname(&node_name);
  //strcpy(server, PATH); //JSalas
  //strcat(server, "/dcadena/bdreplicadasDavid/"); //JSalas
  nodename = strtok(node_name.nodename, ".");
  strcpy(server, getcwd (NULL, MAXSERVERPATH - (1 + strlen(nodename) + EOF_SIZE)));
  strcat(server, "/");
  strcat(server, nodename);

  #ifdef DEBUG_QMSOCKETS
    printf("Trying to connect to server at path %s ...\n", server);
  #endif

  /* Sleep 1 seg */
  sleepThread(1000000);
  /* Connect with socket */
  while ((not_sock = sockconnect(server))  == -1) {
    /* Sleep 1 seg */
    sleepThread(100000);
  }

  /* Nunca ocurre
    if (not_sock == -1) {
    perror("Error in thread  sockconnect\n");
    exit(1);
  }*/

  for (i=0; i<MAXQM+1; i++) {
    /* Connect with socket */
    while ((sock[i] = sockconnect(server))  == -1) {
      sleepThread(100000);
    }
    /* JSalas No es posible
    if (sock[i] == -1) {
      perror("Error in QM sockconnect\n");
      exit(1);
    }
    */
  }
  /* Sleep 1 seg */
  sleepThread(100000);

  /* Create Thread */
  createThread((void*) TransNotificationThread, NULL, NULL);
}

/********************************************************************************
Reusable Function.
   void QMSpecial (int sock);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
/*********************************************/
/* generate the bitmask.                    */
/* Each field of a tuple is represented    */
/* by a bit. This bit had 0 if is null    */
/* and 1 is not is null                  */
/* design of result (1 byte):           */
/*    return   00000000                */
/*      field  12345678               */
/*************************************/
char *makebitmask(struct DBType *db, int tuple, int nfields) {
  int bim = (nfields + 7) / 8; // size of bitmask
  char *bitmask;
  int i;
  int witchbit = 0x80;
  int witchbyte = 0;

  bitmask = malloc (bim+1);
  bzero (bitmask, sizeof(bitmask));
  bitmask[bim] = '\0';
  for (i = 0; i < nfields; i++) {
    if (! isFieldNull(db, tuple, i)){
      bitmask[witchbyte] = bitmask[witchbyte] | witchbit;
      witchbit >>= 1;
      if (witchbit == 0) {
        witchbit = 0x80;
        witchbyte++;
      }
    }
  }
  return bitmask;
}

/********************************************************************************
Reusable Function.
   void QMSpecial (int sock);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
/********************************************/
/* send the fields information to pgserver  */
/********************************************/
int sendFieldsMetadata (int sock, struct DBType *db, T_Transaction trans, int typeSQL) {
  int rval, bytes, numFields;
  int i, j, typeField, longField, modifierField, tamBuffer;
  char *name;
  char buf_JDBC[TAMBUFFER /*+ EXTRASIZE - RMEXTRASIZE*/];
  QM_message msg;

  initQMMessage(&msg); //08092004

  bzero (buf_JDBC, sizeof(buf_JDBC));
  buf_JDBC [0] = 'T';
  tamBuffer = 1;

  // fields number
  // QM
  // Receive field information
  numFields = GetNumberFields(db);
  convertToChar (buf_JDBC, sizeof(int), 1, numFields);
  tamBuffer += sizeof(int);

  if (numFields > 0) {
#ifdef DEBUG_QMSOCKETS
    printf("Number of fields : %d\n", numFields);
#endif
    for (i = 0; i < numFields; i++) {
      // name of field
      name = GetFieldName(db, i);

      j = 0;
      while (name[j] > 0) {
        buf_JDBC[tamBuffer++] =  name[j++];
      }
      tamBuffer = tamBuffer + 1;

      // type of field (Oid = Integer)
      typeField = GetFieldType(db, i);
      convertToChar (buf_JDBC, sizeof(int), tamBuffer, typeField);
      tamBuffer = tamBuffer + sizeof(int);

      // long of field (Integer)
      longField = GetFieldSize(db, i);
      convertToChar (buf_JDBC, sizeof(int), tamBuffer, longField);
      tamBuffer = tamBuffer + sizeof(int);

      // modifier of field (Integer)
      modifierField = GetFieldModifier(db, i);
      convertToChar (buf_JDBC, sizeof(int), tamBuffer, modifierField);
      tamBuffer = tamBuffer + sizeof(int);

#ifdef DEBUG_QMSOCKETS
      printf("   Name of field : %s\n", name);
      printf("   Type of field : %d\n", typeField);
      printf("   Long of field : %d\n", longField);
      printf("   Modifier of field : %d\n\n", modifierField);
#endif
    }
  }

  msg.type = NOT_response;
  msg.size = tamBuffer;
  msg.trans = trans;
  copyBuffer (msg.buffer, buf_JDBC, tamBuffer);
  #ifdef DEBUG_QMSOCKETS_SEND_QMMESSAGE
    printf("(QM%d) (SEND 24) Bytes <%d> Message <%s> (NOT_response|Metadata|QMMESSAGE)\n", msg.trans.qmId, sizeof(msg), msg.buffer);
  #endif
  //bytes = send(notification_sock, (char*) &msg, sizeof(msg), 0);
  bytes = sendQMMessage(notification_sock, &msg);
  if (bytes == -1) {
    #ifdef FATAL_QMSOCKETS
      printf("(QM%d) ERROR sending datas to notification_sock\n", msg.trans.qmId);
    #endif
    return -1;
  }
  //#ifdef DEBUG_QMSOCKETS
    //printf("SendFields: <%s>\n", buf_JDBC);
  //#endif

  return numFields;
}

/********************************************************************************
Reusable Function.
   void QMSpecial (int sock);
   Purpose:
   Limitations: Nothing
   Returns:
*********************************************************************************/
/********************************/
/* send a tuple to pgserver    */
/******************************/
int sendTuple (int bin, int sock, struct DBType *db, T_Transaction trans, int typeSQL, int tuple, int nfields) {
  int i, j, bytes;
  int len, rval, tamBuffer;
  char *bitmask;
  char *data;
  char buf_JDBC[TAMBUFFER /*+ EXTRASIZE - RMEXTRASIZE*/];
  QM_message msg;

  initQMMessage(&msg); //08092004

  bitmask = makebitmask (db, tuple, nfields);

  //#ifdef DEBUG_QM
    //printf("bitmask created\n");
  //#endif

  bzero (buf_JDBC, sizeof(buf_JDBC));
  if (bin) {
    buf_JDBC[0] = 'B';

  } else {
    buf_JDBC[0] = 'D';
  }

  len = (nfields + 7) / 8;
  j = 1;
  for (i = 0; i < len; i++) {
    buf_JDBC[j++] = bitmask[i];
  }
  buf_JDBC[j] = '\0';

  msg.type = NOT_response;
  msg.size = len + 1;
  msg.trans = trans;
  copyBuffer (msg.buffer, buf_JDBC, len+1);
  #ifdef DEBUG_QMSOCKETS_SEND_QMMESSAGE
    printf("(QM%d) (SEND TUPLE 25) Bytes <%d> Message <%s> (NOT_response|QMMESSAGE)\n", msg.trans.qmId, sizeof(msg), msg.buffer);
  #endif
  //bytes = send(notification_sock, (char*) &msg, sizeof(msg), 0);
  bytes = sendQMMessage(notification_sock, &msg);
  if (bytes == -1) {
    #ifdef FATAL_QMSOCKETS
      printf("(QM%d) ERROR sending datas to notification_sock\n", msg.trans.qmId);
    #endif
    exit(1);
  }

  bzero(buf_JDBC,sizeof(buf_JDBC));
  tamBuffer = 0;

  #ifdef DEBUG_QM
    printf("Number Fields: %d\n", nfields);
  #endif
  for (i = 0 ; i < nfields ; i++) {
    if (!isFieldNull(db, tuple, i)) {
      len = GetValueLenght(db, tuple, i);

      if (! bin) {
        convertToChar (buf_JDBC, sizeof(int), tamBuffer, len+sizeof(int));
      } else {
        convertToChar (buf_JDBC, sizeof(int), tamBuffer, len);
      }
      tamBuffer = tamBuffer + sizeof(int);

      data = GetResultValue(db, tuple, i);
      for (j = 0; j < len; j++) {
        buf_JDBC[tamBuffer++] = data[j];
      }

      #ifdef DEBUG_QM
        printf("Field size : %d\n", len);
        printf("Data : %s\n\n", data);
      #endif
    }else{
    	printf("isFieldNull\n");
    }
  }

  #ifdef DEBUG_QM
    printf("buffer size : %d\n", tamBuffer);
  #endif

  msg.type = NOT_response;
  msg.size = tamBuffer;
  msg.trans = trans;
  copyBuffer (msg.buffer, buf_JDBC, tamBuffer);
  #ifdef DEBUG_QMSOCKETS_SEND_QMMESSAGE
    printf("(DATA)(QM%d) (SEND 26) Bytes <%d> Message <%s> (NOT_response|QMMESSAGE)\n", msg.trans.qmId, sizeof(msg), msg.buffer);
  #endif
  //bytes = send(notification_sock, (char*) &msg, sizeof(msg), 0);
  bytes = sendQMMessage(notification_sock, &msg);
  if (bytes == -1) {
    #ifdef ERROR_QMSOCKETS
      printf("(QM%d) ERROR sending datas to notification_sock\n", msg.trans.qmId);
    #endif
    return -1;
  }
  //printf("SendTuples: <%s>\n", buf_JDBC);
  return 0;
}

void StopQMs() {
  int i;

  sleepThread(50000);

#ifdef DEBUG_QMSOCKETS_CLOSE
  printf("Close Socket <%d> File: %s Line: %d\n", not_sock, __FILE__, __LINE__);
#endif
  close(not_sock);

  for (i=0;i<MAXQM+1;i++) {
#ifdef DEBUG_QMSOCKETS_CLOSE
    printf("Close Socket <%d> File: %s Line: %d\n", sock[i], __FILE__, __LINE__);
#endif

    close(sock[i]);
    //if (i!=MAXQM) {
#ifdef DEBUG_QMSOCKETS_CLOSE
      //printf("Close Socket <%d> File: %s Line: %d\n", sockResGC[i], __FILE__, __LINE__);
      //printf("Close Socket <%d> File: %s Line: %d\n", sockResTh[i], __FILE__, __LINE__);
#endif

      //close(sockResGC[i]);
      //close(sockResTh[i]);
    //}
  }
  
  for (i=0;i<MAXCLIENTS;i++) {
#ifdef DEBUG_QMSOCKETS_CLOSE 
    printf("Close Socket <%d> File: %s Line: %d\n", sockResGC[i], __FILE__, __LINE__);     
	printf("Close Socket <%d> File: %s Line: %d\n", sockResTh[i], __FILE__, __LINE__);
#endif
    close(sockResGC[i]);
	close(sockResTh[i]);
  }
  running=0;
  sleepThread(5000);
  yieldThread();
}

/* Test */
/* All QMs */
/*
int main(int argc, char *argv[]) {
  StartQMs();
}
*/

/*int main(int argc, char *argv[]) {
  StartQMs();
  while(1){;;}
  }*/
