#include <stdio.h>
#include <sys/param.h>
#include <rpc/rpc.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>     /* Added by Satish for gettimeofday & atof */

#include "LockList.h"
#include "LockReqList.h"
#include "extnDefn.h"

extern TimeStamp	timestamp;	/* Added by Satish */
extern LockList*        localLockList;
extern LockReqList*     requestedList;
LockArr  	        lockList;
LockRequest             lockPerm;
MagicNumber             *num = NULL;
void*  junk;


extern TimeStamp StoreLoad();

/*

  Function to calculate local magic number 

 */

MagicNumber*
Calculate_cur_magicnum()
{                               
    float loadfactor=0.0;
    struct timeval tv;
    int i;

	//PrintInResult("I am in old Calculate_cur_magicnum, for local magic num \n");
    if( num == NULL)
    {
        num = ( MagicNumber* ) malloc( sizeof( MagicNumber));
    }
	    
	    //--- I have made these changes to the following three set of lines.

		timestamp = StoreLoad();  
	/*	if((tv.tv_sec - timestamp.Tv.tv_sec) > 60) 
		{
			timestamp = StoreLoad();  
			printf("StoreLoad executed 2 time");	
    } */
    
	/*	for(i =  0; i < 3; i++) 
			loadfactor += atof(timestamp.load[i]);

    loadfactor /= 3;	
    loadfactor+=1; 
	
	*/

	printf("Load in the past 1 minute %lf ...\n",atof(timestamp.load[0]));
	loadfactor = atof(timestamp.load[0]);
    loadfactor+=1; 
	PrintInResult("Load factor on local is .............%lf \n",loadfactor);
    num->hpf = globNodeArr.NodeArr_val[globMyId].Capacity / loadfactor;
    printf("hpf value on local is .........%lf \n", num->hpf); 
		
		return(num);
}



/*

        calculate_cur_magicnum_4()
        ---------------------------
                
               returns the local magic number;

This function is used to calculate the current magic number of a particular
machine lock.

*/
/*

#ifdef NEW_VER_RPC

MagicNumber*
calculate_cur_magicnum_4_svc(void* junk, struct svc_req *junk2)

#else
    
MagicNumber*
calculate_cur_magicnum_4(void* junk)
    
#endif
    
{                               /* calculate the Horse power factor 
    FILE* fp;
    char  tp[250];
    char* tok;
    
    system("uptime > MN_tmp");

    fp = fopen( "MN_tmp", "r");
    fscanf(fp, "%[^\n]", tp);
    
    tok = strtok( tp, " ,:\t");
    while( (tok = strtok( NULL, " ,:\t")) != NULL)
    {
        if( !strcmp( tok, "average"))
        {
            break;
        }
    }
    tok = strtok( NULL, " :,\t");

    if( num == NULL)
    {
        num = ( MagicNumber* ) malloc( sizeof( MagicNumber));
    }

    num->hpf = globNodeArr.NodeArr_val[globMyId].Capacity / 
        (1 + atof( tok) / 256.0);

    fclose(fp);
    system("rm MN_tmp");
    return(num);
}
*/			/* Commented by Satish & ver2 is written */

/*

        calculate_cur_magicnum_ver2__4()
        ---------------------------
                
               returns the local magic number;

This function is used to calculate the current magic number of a particular
machine lock.

*/

#ifdef NEW_VER_RPC

MagicNumber*
calculate_cur_magicnum_ver2_4_svc(void* junk, struct svc_req *junk2)

#else
    
MagicNumber*
calculate_cur_magicnum_ver2_4(void* junk)
    
#endif
    
{                               /* calculate the Horse power factor */
    int i;
    char *tok;
    float loadfactor=0.0;	
    struct timeval tv;

	//PrintInResult("I am in calculate_cur_magicnum_ver2_4 \n");
    if( num == NULL)
    {
        num = ( MagicNumber* ) malloc( sizeof( MagicNumber));
    }
	gettimeofday(&tv,NULL);
	//if((tv.tv_sec - timestamp.Tv.tv_sec) > 120) { 
	    timestamp = StoreLoad();  
/*	    printf("StoreLoad executed locally 2");		*/
	//} 
    /* 
	   for(i =  0; i < 3; i++) 
	       loadfactor += atof(timestamp.load[i]);
           loadfactor /= 3;	
	*/

	printf("Load in the past 1 minute %lf ...\n",atof(timestamp.load[0]));
	loadfactor = atof(timestamp.load[0]);
    loadfactor+=1;
	PrintInResult("Load factor is .............%lf \n",loadfactor);
    num->hpf = globNodeArr.NodeArr_val[globMyId].Capacity / loadfactor;
    printf("Hpf value is ...............%lf \n", num->hpf); 
  return(num);
}

/*
    request_lock_info_4()
    ------------------------
    
                Arguments:

                     NodeId of the node requesting for lock information;

                     return the array of currently available locks;

This function is invoked to get information of the locks available at a remote
machine.

*/

#ifdef NEW_VER_RPC

LockArr*
request_lock_info_4_svc(int* id, struct svc_req *junk2)

#else
    
LockArr*
request_lock_info_4(int* id)
    
#endif
    
{                               
    LockList*       current;
    Lock            *lock;
    int 	    i;
    int 	    j;
    int		    len = 0;
    float	    hpf = 10.9;
    MagicNumber* num;

    lockList.LockArr_len =  LockListLength(localLockList);
    
    if(lockList.LockArr_len == 0)
    {
        lockList.LockArr_val =  NULL;
	    return &lockList;
    }   

    if(  lockList.LockArr_val != NULL)
    {
	    free( lockList.LockArr_val);
    }
	
    lockList.LockArr_val = (Lock*) calloc(lockList.LockArr_len,
                                            sizeof(Lock));
    num = Calculate_cur_magicnum();


    PrintInLogFile( "Yes Hpf %f \n", num->hpf);
    PrintInResult( "Hpf on the requested remote machine %lf \n", num->hpf);


    current = localLockList;
    lock = (Lock *) malloc( sizeof(Lock));
    
    for ( i = 0; i < lockList.LockArr_len; i++)
    {
        if ((current->Data).Status == FREE )
        {
            lock->NodeId = globMyId;
            lock->LockId = (current->Data).LockId;
            CopyMagicNum(&(lock->MagicNum), num);

            CopyLock( &(lockList.LockArr_val[len]), lock);
            len++;
        }
        current = current->Next;
    }
    
    if( len == 0)
    {
        lockList.LockArr_len = len;
        lockList.LockArr_val =  NULL;
        return &lockList;
    }
    lockList.LockArr_len = len;

    PrintLockArr( &lockList);
    return &lockList;
}


/*

        acquire_locks_4()
        -----------------------

                Arguments:

                    LockRequest, containg the list of locks intended to 
                    be acquired;

                returns LockPerms, its permissions for the list of locks
                requested.

This function is used to get the access permissions of a remote node for
a particular lock request. 

*/

#ifdef NEW_VER_RPC

LockRequest*
acquire_locks_4_svc(LockRequest* req, struct svc_req *junk2)

#else
    
LockRequest*
acquire_locks_4(LockRequest* req)

#endif

{
    int                 i;
    int                 pos;
    LockReqList*        request;

#ifdef PRINT

PrintInLogFile ( "Beginning of func \n");

#endif
    
    if(  lockPerm.LockList.LockArr_val != NULL)
    {
	    free( lockPerm.LockList.LockArr_val);
    }

    if(  lockPerm.Perm.IntArr_val != NULL)
    {
	    free( lockPerm.Perm.IntArr_val);
    }
	
    lockPerm.LockList.LockArr_len = req->LockList.LockArr_len;
    lockPerm.Perm.IntArr_len      = req->Perm.IntArr_len;
    
    lockPerm.LockList.LockArr_val = (Lock*) calloc
                    (lockPerm.LockList.LockArr_len, sizeof(Lock));

    lockPerm.Perm.IntArr_val = (int*) calloc
                    (lockPerm.Perm.IntArr_len, sizeof(int));

    lockPerm.NodeId = globMyId;
    lockPerm.SeqNum = req->SeqNum;

    for( i= 0; i < lockPerm.LockList.LockArr_len; i++)
    {
        CopyLock( &(lockPerm.LockList.LockArr_val[i]),
                    &(req->LockList.LockArr_val[i]));
        lockPerm.Perm.IntArr_val[i] = NOACCESS;
    }

   /*  compare seq number and send ACCESS or NOACCESS */

    for( i = 0; i < req->LockList.LockArr_len ; i++)
    {
        if((request =  GetLockReqLink( requestedList, &pos,
                 req->LockList.LockArr_val[i].NodeId,
                 req->LockList.LockArr_val[i].LockId,
                 req->SeqNum)) != NULL )
        {
            if( req->SeqNum < request->Data.SeqNum)
            {
                lockPerm.Perm.IntArr_val[i] = ACCESS;
                DeleteLockReqInfLink( requestedList, pos);
            }
            else              
            if(( req->SeqNum == request->Data.SeqNum) && 
                            (req->NodeId < globMyId))
            {
                lockPerm.Perm.IntArr_val[i] = ACCESS;
                DeleteLockInfLink( requestedList, pos);
            }
        }
        else
        {
                lockPerm.Perm.IntArr_val[i] = ACCESS;
        }
    }
    return &lockPerm;
}


