1

I am trying to implement multiple clients and multiple servers using Sun-RPC. However, I am unable to run multiple servers at the same time to begin with.

Here's the IDL

const MAXLEN = 1024;

typedef string filename<MAXLEN>;

typedef int vtimestamp[5];

typedef int sender_id;

typedef int recv_id;

struct request {
    filename name;
    int start;
    vtimestamp ts;
    sender_id sid;
    recv_id rid;
};

typedef struct request request;

typedef opaque filepart[MAXLEN];

struct partreceive {
    filepart data;
    int bytes;
    vtimestamp ts;
    sender_id sid;
    recv_id rid;
};


typedef struct partreceive partreceive;

struct partsend {
    filename name;
    filepart data;
    int bytes;
    vtimestamp ts;
    sender_id sid;
    recv_id rid;
};

typedef struct partsend partsend;

union readfile_res switch (int errno) {
    case 0:
        partreceive part;
    default:
        void;
};

program FTPROG {
    version FTVER {
        readfile_res retrieve_file(request *) = 1;
        int send_file(partsend *) = 2;
    } = 1;
} = 0x31240000;

Here's the server 1's code:

#include <rpc/rpc.h>
#include <stdio.h>
#include "maekawa.h"

extern __thread int errno;

int Id = 1;
char fileLog[50] = "server_1_file_log.txt";
int cur_ts[5] = {0};

readfile_res* retrieve_file_1_svc(request *req, struct svc_req *rqstp)
{
    printf("%d",req->rid);
    if(req->rid == Id)
    {
        FILE *file;
        char data[1024];
        int bytes,i;
        static readfile_res res;
        //update the timestamp
        for(i=0;i<5;i++)
            cur_ts[i] = res.readfile_res_u.part.ts[i];
        char fn[3*MAXLEN] = "storage/";
        strcat(fn,req->name);
        file = fopen(fn, "rb");
        if (file == NULL) 
        {
            res.errno = errno;
            return (&res);
        }
        fseek (file, req->start, SEEK_SET);
        bytes = fread(res.readfile_res_u.part.data, 1, 1024, file);
        res.readfile_res_u.part.bytes = bytes;
        res.readfile_res_u.part.sid = Id;
        res.readfile_res_u.part.rid = req->sid;
        res.errno = 0;
        fclose(file);
        //log the transaction
        FILE *log = NULL;
        log = fopen(fileLog, "a");
        fprintf(log,"R,");
        for(i=0;i<5;i++)
            fprintf(log,"%d,",cur_ts[i]);
        fprintf(log,"%d,",req->sid);
        fprintf(log,"%s,",req->name);
        fprintf(log,"%d\n",req->start);
        fclose(log);
        return (&res);  
    }
}

int* send_file_1_svc(partsend *rec, struct svc_req *rqstp)
{
    int i;
    printf("%d",rec->rid);
    if(rec->rid == Id)
    {
        FILE *file;
        int write_bytes;
        static int result;
        cur_ts[Id]++;
        //update the timestamp
        for(i=0;i<5;i++)
            cur_ts[i] = rec->ts[i];
        char fn[3*MAXLEN] = "storage/";
        strcat(fn,rec->name);
        file = fopen(fn, "a");
        if (file == NULL) {
            result = errno;
            return &result;
        }
        write_bytes = fwrite(rec->data, 1, rec->bytes, file);
        fclose(file);
        result = 0;
        //log the transaction
        FILE *log = NULL;
        log = fopen(fileLog, "a");
        fprintf(log,"S,");
        for(i=0;i<5;i++)
            fprintf(log,"%d,",cur_ts[i]);
        fprintf(log,"%d,",rec->sid);
        fprintf(log,"%s\n",rec->name);
        fclose(log);
        return &result;
    }
}

Here's Server 2 :

#include <rpc/rpc.h>
#include <stdio.h>
#include "maekawa.h"

extern __thread int errno;

int Id = 2;
char fileLog[50] = "server_2_file_log.txt";
int cur_ts[5] = {0};

readfile_res* retrieve_file_1_svc(request *req, struct svc_req *rqstp)
{
    printf("%d",req->rid);
    if(req->rid == Id)
    {
        FILE *file;
        char data[1024];
        int bytes,i;
        static readfile_res res;
        //update the timestamp
        for(i=0;i<5;i++)
            cur_ts[i] = res.readfile_res_u.part.ts[i];
        char fn[3*MAXLEN] = "storage/";
        strcat(fn,req->name);
        file = fopen(fn, "rb");
        if (file == NULL) 
        {
            res.errno = errno;
            return (&res);
        }
        fseek (file, req->start, SEEK_SET);
        bytes = fread(res.readfile_res_u.part.data, 1, 1024, file);
        res.readfile_res_u.part.bytes = bytes;
        res.readfile_res_u.part.sid = Id;
        res.readfile_res_u.part.rid = req->sid;
        res.errno = 0;
        fclose(file);
        //log the transaction
        FILE *log = NULL;
        log = fopen(fileLog, "a");
        fprintf(log,"R,");
        for(i=0;i<5;i++)
            fprintf(log,"%d,",cur_ts[i]);
        fprintf(log,"%d,",req->sid);
        fprintf(log,"%s,",req->name);
        fprintf(log,"%d\n",req->start);
        fclose(log);
        return (&res);  
    }
}

int* send_file_1_svc(partsend *rec, struct svc_req *rqstp)
{
    int i;
    printf("%d",rec->rid);
    if(rec->rid == Id)
    {
        FILE *file;
        int write_bytes;
        static int result;
        cur_ts[Id]++;
        //update the timestamp
        for(i=0;i<5;i++)
            cur_ts[i] = rec->ts[i];
        char fn[3*MAXLEN] = "storage/";
        strcat(fn,rec->name);
        file = fopen(fn, "a");
        if (file == NULL) {
            result = errno;
            return &result;
        }
        write_bytes = fwrite(rec->data, 1, rec->bytes, file);
        fclose(file);
        result = 0;
        //log the transaction
        FILE *log = NULL;
        log = fopen(fileLog, "a");
        fprintf(log,"S,");
        for(i=0;i<5;i++)
            fprintf(log,"%d,",cur_ts[i]);
        fprintf(log,"%d,",rec->sid);
        fprintf(log,"%s\n",rec->name);
        fclose(log);
        return &result;
    }
}

Here's my client 1 code.

#include <rpc/rpc.h>
#include <stdio.h>
#include <string.h>
#include "maekawa.h"

extern __thread int errno;

int Id = 4;
char fileLog[50] = "client_1_file_log.txt";
int cur_ts[5] = {0};
//Explicit Replication due to lack of Active Directory Service in NFS.
int idMap[4] = {0,2,3,1};
char hostMap[4][MAXLEN] = {"","localhost","localhost","localhost"};

int get_file(char *host, char *name, int serverno) //just to ensure all servers are not operating on same domain, we use serverno.
{
    CLIENT *clnt;
    int total_bytes = 0, write_bytes;
    readfile_res *result;
    request req;
    FILE *file;
    req.name = name;
    req.start = 0;
    int i;
    req.sid = Id;
    req.rid = serverno; 
    clnt = clnt_create(host, FTPROG, FTVER, "tcp");
    if (clnt == NULL) 
    {
         clnt_pcreateerror(host);
         exit(1);
    }
    file = fopen(name, "wb");

    FILE *log = NULL;
    log = fopen(fileLog, "a");
    while (1) 
    {
        cur_ts[Id]++;
        for(i=0;i<5;i++)
            req.ts[i] = cur_ts[i];
        req.start = total_bytes;
        result = retrieve_file_1(&req, clnt);

        if (result == NULL) 
        {
            clnt_perror(clnt, host);
            exit(1);
        }
        if (result->errno != 0) 
        {
            errno = result->errno;
            perror(name);
            exit(1);
        }
        write_bytes = fwrite(result->readfile_res_u.part.data, 1, result->readfile_res_u.part.bytes, file);
        total_bytes += result->readfile_res_u.part.bytes;

        //log the transaction
        fprintf(log,"G,");
        for(i=0;i<5;i++)
            fprintf(log,"%d,",cur_ts[i]);
        fprintf(log,"%d,",req.sid);
        fprintf(log,"%s,",req.name);
        fprintf(log,"%d\n",req.start);
        if (result->readfile_res_u.part.bytes < MAXLEN) 
            break;
    }
    fclose(file);       
    fclose(log);
    return 0;
}

int put_file(char *host, char *name, int serverno)//just to ensure all servers are not operating on same domain, we use serverno.
{
    CLIENT *clnt;
    char data[1024];
    int total_bytes = 0, read_bytes;
    int *result;
    partsend part;
    FILE *file;
    int i;
    part.sid = Id;
    part.rid = serverno;
    clnt = clnt_create(host, FTPROG, FTVER, "tcp");
    if (clnt == NULL) 
    {
         clnt_pcreateerror(host);
         exit(1);
    }
    file = fopen(name, "r");
    part.name = name;
    FILE *log = NULL;
    log = fopen(fileLog, "a");
    for(i=0;i<5;i++)
        part.ts[i] = cur_ts[i];
    while (1) 
    {
        part.bytes = total_bytes;

        read_bytes = fread(part.data, 1, MAXLEN, file);
        total_bytes += read_bytes;
        part.bytes = read_bytes;
        result = send_file_1(&part, clnt);
        if (result == NULL) 
        {
            clnt_perror(clnt, host);
            exit(1);
        }
        if (*result != 0) 
        {
            errno = *result;
            perror(name);
            exit(1);
        }
        for(i=0;i<5;i++)
            cur_ts[i] = part.ts[i];
        //log the transaction
        fprintf(log,"P,");
        for(i=0;i<5;i++)
            fprintf(log,"%d,",cur_ts[i]);
        fprintf(log,"%d,",part.sid);
        fprintf(log,"%s,",part.name);
        fprintf(log,"%d\n",part.bytes);
        if (read_bytes < MAXLEN) 
            break;
    }
    fclose(file);
    fclose(log);
    return 0;
}

int read_command(char *host)
{
    char command[MAXLEN], filepath[MAXLEN];
    int serverno;
    printf("> ");
    fflush(stdin);
    scanf("%s",command);
    if(strcmp(command, "exit") == 0)
    {
        exit(0);
    }
    scanf(" %s %d",filepath,&serverno);
    if(serverno<=0 || serverno>=4)
    {
        printf("Choose a server number in [1,2,3].");
    }
    else
    {
        if (strcmp(command, "get") == 0) 
        {
            return get_file(host,filepath,serverno);
        } 
        else if(strcmp(command, "put") == 0)
        {
            int updateResult,replicationResult=-1;
            updateResult = put_file(host,filepath,serverno);
            /*if(updateResult == 0)
            {
                //explicit Replication
                replicationResult = put_file(hostMap[serverno],filepath,idMap[serverno]);
            }
            else if(replicationResult != 0)
            {
                printf("Replication failed.");
            }*/
            return 0;
        } 
        else
        {
            return -1;
        }
    }
}

int main(int argc, char *argv[])
{
    int result;
    if (argc != 2) 
    {
        fprintf(stderr, "usage: %s host\n", argv[0]);
        exit(1);
    }
    while(TRUE) 
    {
        result = read_command(argv[1]);
    }
    return 0;
}

I am trying to use Maekawa algorithm to implement file replication explicitly through my client. However, it's being ridiculously impossible to run multiple servers on RPC on same localhost. Is it even possible? If I run the code on different computers, would that work? Currently I am receiving segmentation fault from the server that is run after the first server. The client just blurts out Connection reset by peer. Is there anyway I can make this work?

  • Can you elaborate your problem? You can't serve multiple clients in parallel or you want a different functionality for different clients? – kofemann Nov 13 '17 at 10:33

0 Answers0