#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <rpc/rpc.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#include "extnDefn.h"
#include "LockList.h"
#include "LockReqList.h"
#include "../commonIncludes/msgq.h"

//#define PRINT

IntArr              pidArr;
extern int          clntFlag ;

LockArr             tmpLockArr;  
//LocalLockArr        *locksAvailable = NULL;  
LockRequest         lockRequest;
extern LockRequest  lockPerm;
extern LockList*    localLockList;
extern LockReqList*        requestedList;
String              localStr;
extern int          msgQueueId;  
extern long         GetProgNum();
extern void         ExecuteFile();
extern MagicNumber* Calculate_cur_magicnum();

static struct timeval TIMEOUT = { 50, 0 };
int     retVal;
u_long  progNum;
u_long*  progNum1;

int PostFile( String filename, CLIENT* cl);

/*

        result_intimation_5()
        ------------------------

                Arguments:
                    LongArr, info regarding the results arrived;

          Put the result intimation in the message queue;

This function is invoked by the ARC function server to send result ready
intimation to the sender coordinator server.

*/

#ifdef NEW_VER_RPC

void* result_intimation_5_svc( LongArr* longArr, struct svc_req *junk)

#else
    
void* result_intimation_5( LongArr* longArr)

#endif
{
    ResultMesg      resmsg;
    int             len;

    /* PrintInLogFile( " In result intimation \n"); */ /* Comment by Satish */
    resmsg.mtype = longArr->LongArr_val[1];
    resmsg.msubtype = RESULT;
    resmsg.ribId    = longArr->LongArr_val[0];
    resmsg.prognum  = longArr->LongArr_val[2];
    len = 2 * sizeof( int) + sizeof(u_long);

  /*  PrintInLogFile(" \nmessage send to queue 1 %d %d %x \n",
            resmsg.ribId, resmsg.mtype, resmsg.prognum ); 
*/

   if(msgsnd( msgQueueId, (char *)&resmsg.mtype, len, 0) != 0) {
        PrintInLogFile(" server can't send message queue 1 \n"); 
    }
}

/*

        error_in_execution_5()
        -------------------------

                Arguments:
                     strArr, info regarding the error encountered
                     during remote execution;

           Put the error initmation in the message queue to be read by
           the user program;

This function is invoked by the ARC function server to intimate the error
during the execution of ARC function to the sender coordinator server.

*/                    

#ifdef NEW_VER_RPC

void* error_in_execution_5_svc( StrArr* strArr, struct svc_req *junk2)

#else

void* error_in_execution_5( StrArr* strArr)

#endif

{
}

/*

        register_program_5()
        ----------------------

                Arguments:
                    pid, process id of the user program;

Ths function is used to register a user program to the
local coordinator. This is required for the communication of results/ error
and node failures from the coordinator to the user program.

*/


#ifdef NEW_VER_RPC

void* register_program_5_svc( int* pid, struct svc_req* junk)

#else

void* register_program_5( int* pid)

#endif

{
    int i;

    for( i = 0; i < pidArr.IntArr_len; i++) {
        if( pidArr.IntArr_val[i] == -1) {
            break;
        }
    }

    pidArr.IntArr_val[i] = *pid;

#ifdef PRINT

    PrintInLogFile( "registering program %d %d \n", *pid, i); 

#endif

}

/*

        unregister_program_5()
        ----------------------

                Arguments:
                    pid, process id of the user program;

Ths function is used to unregister a user program to the
local coordinator. 

*/

#ifdef NEW_VER_RPC

void* unregister_program_5_svc( int* pid, struct svc_req* junk)

#else

void* unregister_program_5( int* pid)

#endif

{

    int i;

    for( i = 0; i < pidArr.IntArr_len; i++) {
        if( pidArr.IntArr_val[i] == *pid) {
            break;
        }
    }

    pidArr.IntArr_val[i] = -1;
}

/*

        unlock_5()
        ------------

            Arguments:
        LocalLockArr, array of locks to be unlocked;

        set locks free, which are reserved by a user program;

		This function is used to unlock the locks acquired.

*/

#ifdef NEW_VER_RPC

void* unlock_5_svc( LocalLockArr* lockList, struct svc_req *junk2)

#else

void* unlock_5( LocalLockArr* lockList)

#endif

{                           
  CLIENT* cl;
  int i;
  int clntFlag = 1;
  int *position = (int *) malloc( sizeof(int));
  LockList*       temp1;
  LockReqList*    result;

  for( i = 0; i < lockList->LocalLockArr_len; i++) {

    if( lockList->LocalLockArr_val[i].LockInf.NodeId == globMyId) {
			
        if ((temp1 = GetLockLink( localLockList, position, 
            lockList->LocalLockArr_val[i].LockInf.LockId)) == NULL) {
            error(" set_lock_free: lock non exixting");
        }
        else {
            (temp1->Data).Status = FREE; 
        }
        continue;
    }
    
    if ((cl = clnt_create(lockList->LocalLockArr_val[i].IPAddress.String_val,
        COORDINATOR, ADMINISTRATION, "tcp")) == NULL) {

        clnt_pcreateerror(lockList->LocalLockArr_val[i].IPAddress.String_val);
        clntFlag = 0;
    }

    if( clntFlag == 0) {
        clntFlag = 1;
        continue;
    }

    if (clnt_call(cl, SET_LOCK_FREE, xdr_Lock, 
            &lockList->LocalLockArr_val[i].LockInf,
            xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
        clnt_perror(cl, lockList->LocalLockArr_val[i].IPAddress.String_val);
    }
    clnt_destroy(cl);

    GetLockReqLink(requestedList, position,
                lockList->LocalLockArr_val[i].LockInf.NodeId, 
                lockList->LocalLockArr_val[i].LockInf.LockId, 
                lockList->LocalLockArr_val[i].SeqNum);

  	DeleteLockReqInfLink( requestedList, *position);
  }
}

