/*
                 S y n c h r o n i z e

 Synchronize parameters in this server with parameters from another
 SICS server.

 Mark Koennecke, March 2001

 Use internal connection.
 Mark Koennecke, July 2002

*/
#include "sics.h"
#include "network.h"
#include "status.h"
#include "synchronize.h"


/*-----------------------------------------------------------------------
 Some file statics which hold the connection parameters
 ------------------------------------------------------------------------*/
static char *hostname, *looser, *password;
static int  port;
static mkChannel *connection = NULL; 
/*-----------------------------------------------------------------------*/
static void syncLogin(void)
{
  int test, i;
  char pBueffel[1024], pRead[80];

  /*
   connect
  */
  connection = NETConnect(hostname, port);
  NETRead(connection,pBueffel,1020,10*1000);
  if(connection != NULL)
  {
    /* 
     try a login
    */
    sprintf(pBueffel,"%s %s\n", looser, password);
    test = NETWrite(connection,pBueffel,strlen(pBueffel));
    if(test != 1)
    {
      printf("Failed at writing user/password\n");
      NETClosePort(connection);
      free(connection);
      connection = NULL;
    }

    pBueffel[0] = '\0';
    for(i = 0; i < 10; i++)
    {    
      test = NETRead(connection,pRead,70,10*1000);
      if(test < 0)
      {
         NETClosePort(connection);
         free(connection);
         connection = NULL;
      }
      else
      {
	strcat(pBueffel,pRead);
      }
      if(strstr(pBueffel,"Login OK") == NULL)
      {
	test = 0;
      }
      else
      {
	test = 1;
      }
      SicsWait(1);  
    }
    if(!test)
    {
      printf("Bad reply to login: %s\n",pBueffel);
      NETClosePort(connection);
      free(connection);
      connection = NULL;
    }
  }
}
/*---------------------------------------------------------------------*/
static void killSync(void *pData)
{
  if(connection)
  {
    NETClosePort(connection);
    free(connection);
  }
  if(hostname)
    free(hostname);
  if(looser)
    free(looser);
  if(password)
    free(password);
}
/*----------------------------------------------------------------------*/
int MakeSync(SConnection *pCon, SicsInterp *pSics, void *pData,
                    int argc, char *argv[])
{
  char pBueffel[256];
  int iRet;

  /*
   check arguments: we need host, port, user and passwd 
  */
  if(argc < 5)
  {
    SCWrite(pCon,
	   "ERROR: need parameters: host port user passwd : for sync creation",
	    eError);
    return 0;
  }
  /*
   copy parameters
  */
  hostname = strdup(argv[1]);
  port = atof(argv[2]);
  looser = strdup(argv[3]);
  password = strdup(argv[4]);
  pServ->simMode = 1;

  /*
   add the command to the Interpreter
  */
  iRet = AddCommand(pSics,"sync",Synchronize,killSync,NULL);
  if(!iRet)
  {
     sprintf(pBueffel,"ERROR: duplicate command sync not created");
     killSync(NULL);
     SCWrite(pCon,pBueffel,eError);
     return 0;
  }

  return 1;
}
/*----------------------------------------------------------------------*/
int Synchronize(SConnection *pCon, SicsInterp *pSics, void *pData,
                    int argc, char *argv[])
{
  char pBueffel[1024];
  char pRead[80];
  int test,i;
  SConnection *internalCon = NULL;

  /*
    check for connection
  */
  if(connection == NULL)
  {
    syncLogin();
    if(connection == NULL)
    {
      sprintf(pBueffel,"ERROR: failed to connect to %s, %d for sync 'ing", 
            hostname, port);
      SCWrite(pCon,pBueffel, eError);
      return 0;
    }  
  }

  /*
   first tell the remote server to backup
  */
  SetStatusFixed(eBatch);
  strcpy(pBueffel,"transact backup\n");
  test = NETWrite(connection,pBueffel,strlen(pBueffel));
  if(test != 1)
  {
    NETClosePort(connection);
    free(connection);
    connection = NULL;
    SCWrite(pCon,"ERROR: Failed to contact sync server",eError);
    SCWrite(pCon,"Try again in order to reconnect before giving up",eWarning);
    ClearFixedStatus(eEager);
    return 0;
  }
  /*
    wait 10 seconds for correct message
  */
  pBueffel[0] = '\0';
  for(i = 0; i < 10; i++)
  {
      test = NETRead(connection,pRead,75,20*1000);
      if(test < 0)
      {
        NETClosePort(connection);
        free(connection);
        connection = NULL;
        SCWrite(pCon,"ERROR: Failed to contact sync server",eError);
        SCWrite(pCon,
           "Try again in order to reconnect before giving up",eWarning);
	ClearFixedStatus(eEager);
        return 0;
      }
      else
      {
	strcat(pBueffel,pRead);
      }
      if(strstr(pBueffel,"TRANSACTIONFINISHED") == NULL)
      {
	test = 1;
        break;
      }
      else
      {
        test = 0;
      }
      SicsWait(1);
  }
  if(!test)
  {
    SCWrite(pCon,"WARNING: sync server may not have exectued backup",
            eWarning);
  }
 
  /*
   now read the backup file and we are done
  */
  internalCon = SCCreateDummyConnection(pSics);
  if(internalCon == NULL)
  {
    SCWrite(pCon,"ERROR: out of memory in sync",
            eError);
    ClearFixedStatus(eEager);
    return 0;
    
  }
  test = InterpExecute(pSics,internalCon,"restore");
  SCDeleteConnection(internalCon);
  ClearFixedStatus(eEager);
  if(test != 1)
  {
    SCWrite(pCon,"ERROR: Failed to read sync information",eError);
    return 0;
  }

  /*
    tell everybody that we have sync'ed
  */
  ServerWriteGlobal("Simulation Server has SYNCHRONIZED!",eWarning);

  return 1;
}

