#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include "common.h"
#include "Config.h"
#include "List.h"
#include "net.h"
#include "Net.h"
#include "Packet.h"
#define MAXRETRY 3
char * programName;
bool flag_v = false; // verbose command switch
bool flag_d = false; // dummy sending mode
bool flag_bind = true; // readdisk(), writenet() bind mode
bool last_stop = false; // a flag show that the last node is finished.
Config *config=0;
List *hosts=0;
ListIte *hostIte=0;
FileList *files=0;
CntlIn *cntlin=0;
CntlOut *cntlout=0;
DataIn *datain=0;
DataOut *dataout=0;
void data_transfer();
//*******************
// Parse Config File
//******************
int configure(char * configfile)
{
config = new Config();
hosts = new List();
files = new FileList();
config->open(configfile);
config->parse(hosts,files);
if (flag_v) {
fprintf(stderr,"HOSTs\n");
hosts->print();
fprintf(stderr,"FILEs\n");
files->print();
}
return 0;
}
//*********************
// Building A host ring
//*********************
int buildring()
{
int retry;
Net::sr_retval srret;
hostIte =new ListIte(hosts);
hostIte->pop_entry(); // first entry was servername (it's me!)
datain =new DataIn();
// connect cannot wait for long time. So server have to issue
// connect command last
dataout =new DataOut(hostIte->get_name());
//*** 1st Step: Sending a Ring host list Packet
RingPacket *ring_packet;
if (flag_v) printf("Start sending RING Packet \n");
ring_packet = new RingPacket();
hosts->packetfill(ring_packet);
// CALL_HOST flag set to the first candidate of host is done
// in Config.cpp
// connection retry loop; upto MAXRETRY hosts are tried.
for (retry=0;retry<MAXRETRY;retry++) {
if (dataout->open_connect()!=Net::SUCCESS) {
hostIte->set_flag(NOAVIL_HOST);
dataout->close_sock();
delete dataout;
if (!hostIte->pop_entry()) {
fprintf(stderr,"host list is reached to the end(1)\n");
hosts->print();
exit(1);
}
hostIte->set_flag(CALL_HOST);
delete ring_packet;
ring_packet = new RingPacket();
hosts->packetfill(ring_packet);
dataout=new DataOut(hostIte->get_name());
continue;
}
srret=dataout->send_packet(ring_packet);
if (srret==Net::SR_success) /* success */ {
break; // <------------ retry break!
} else if (srret==Net::SR_connectionlost) /*send timeout*/{
hostIte->set_flag(NOAVIL_HOST);
delete dataout;
if (!hostIte->pop_entry()) {
fprintf(stderr,"host list is reached to the end(2)\n");
hosts->print(); exit(1);
} else {
hostIte->set_flag(CALL_HOST);
delete ring_packet;
ring_packet = new RingPacket();
hosts->packetfill(ring_packet);
dataout = new DataOut(hostIte->get_name());
continue; // <------------ retry !!
}
} else /*send error*/ {
fprintf(stderr,"Server.cpp::building(1) \n");
exit(1);
}
}
if (retry==MAXRETRY) {
fprintf(stderr,"send retry exceed a limit(<%d times)\n",retry);
exit(1); }
delete ring_packet;
if (flag_v) {
fprintf(stderr,"Sending Ring packet succeeded. try to recieve the "
"return.\n");
}
//*** 2nd Step: Recieving the Ring packet
if (flag_v) printf("Start recieving RING Packet back \n");
if (datain->open_accept()!=Net::SUCCESS) {
fprintf(stderr,"fail to accept connection in recieving RING packet.\n");
exit(2);
}
RingPacket *recv_ring_packet;
recv_ring_packet = new RingPacket();
srret=datain->recv_packet(recv_ring_packet);
if (srret!=Net::SR_success) /* error or timeout*/ {
fprintf(stderr,"Ring packet cannot be recieved (ret=%d) \n",srret);
exit(1); }
if (flag_v) {
fprintf(stderr,"Sent/Recieved Ring Packet\n"); }
if (!hosts->flag_sync(recv_ring_packet)) {
fprintf(stderr,"RING information isnot agree. (send!=recv)");
exit(1); }
delete recv_ring_packet;
//*** 3rd Step: Sending a Host list packet.
HostPacket *host_packet;
if (flag_v) printf("Start sending Host Packet\n");
host_packet = new HostPacket();
hosts->packetfill(host_packet);
srret=dataout->send_packet(host_packet);
if (srret!=Net::SR_success) {
fprintf(stderr,"fail to send HOST packet. "
"buildring()@Server.cpp \n"); exit(1); }
delete host_packet;
//*** 4th Step: Recieving the Host list packet.
HostPacket *recv_host_packet;
if (flag_v) printf("Start recieving Host Packet back\n");
recv_host_packet = new HostPacket();
srret=datain->recv_packet(recv_host_packet);
if (srret!=Net::SR_success) /*error or timeout*/ {
fprintf(stderr,"Host Packet cannot be recieved (ret=%d).\n",srret);
exit(1); }
if(!hosts->flag_sync(recv_host_packet)) {
fprintf(stderr,"HOST information isnot agree. (send!=recv)");
exit(1); }
if(flag_v) {
fprintf(stderr,"sent/recieved HOST Packet. \n"); }
hostIte->all_print();
fprintf(stderr,"******************************************\n");
fprintf(stderr,"* Host marked with flag=3 has a trouble. *\n");
fprintf(stderr,"******************************************\n");
delete recv_host_packet;
return 0;
}
//**************************
// Sending Files information
//**************************
int file_info()
{
Net::sr_retval srret;
FilePacket *file_packet = new FilePacket();
files->packetfill(file_packet);
srret=dataout->send_packet(file_packet);
if (srret!=Net::SR_success) /*error or timeout*/ {
fprintf(stderr,"File Packet cannot be recieved (timeout) \n");
exit(1); }
delete file_packet;
FilePacket *recv_file_packet = new FilePacket();
srret=datain->recv_packet(recv_file_packet);
if (srret!=Net::SR_success) /*error or timeout*/ {
fprintf(stderr,"File Packet cannot be recieved (ret=%d).\n",srret);
exit(1); }
if (!files->flag_sync(recv_file_packet)) {
fprintf(stderr,"RING information isnot agree. (send!=recv)");
exit(1); }
delete recv_file_packet;
return 0;
}
///////////////////
// err_ttyopen() //
///////////////////
/*
void err_ttyopen(char* dev) {
if ( dev == NULL ) {
ty_err = stderr;
} else {
if ( (ty_err = fopen(dev)) == NULL ) {
perror("error output stream(%s) open",dev);
exit(1);
}
}
}
*/
//////////////
// usage() //
//////////////
void usage(char * progname)
{
fprintf(stderr," %s [-v] [-d] [-B] -f dollytab ] \n"
,progname);
fprintf(stderr," :-v verbose -d dummy \n");
fprintf(stderr," :-f dollytab \n");
fprintf(stderr,
" :-B switch off binding of writenet() and readnet().\n"
" With this option, you may get faster transfer "
"and less ability\n"
" for recovery \n");
fprintf(stderr,
" :-L switch off unblocking write mode in sending network"
" packet.\n"
" With this option, you may get faster transfer "
"and less ability \n"
" for recovery \n");
}
//***************
// MAIN routine *
//***************
main(int argc, char** argv)
{
char * configfile="dolly.tab";
int c;
programName=argv[0];
/* Parse arguments */
while (1) {
c = getopt(argc, argv, "f:vdbBL");
if (c==(-1)) break;
switch (c) {
case 'f':
/* Only the server should need this in the final version. */
if (strlen(optarg) > 255) {
fprintf(stderr, "Name of config-file too long.\n");
exit(1);
}
configfile = optarg;
break;
case 'v':
/* Verbose */
flag_v = true;
break;
case 'd':
/* Dummy disk read/write for debugging */
flag_d = true;
break;
case 'B':
/* Stop readdisk(), writenet() binding */
fprintf(stderr,"unbinde mode . \n");
flag_bind = false;
break;
case 'L':
/* stop unblocking write in Net.cpp:send_packet() */
fprintf(stderr,"block write mode.(does not work connection recorvery\n");
NetSend::set_block_write();
break;
default:
fprintf(stderr, "Unknown option '%c'.\n", c);
usage(programName);
exit(1);
}
}
if (flag_d) {
fprintf(stderr,"Dolly will send dummy data and never stop \n");
}
signal(SIGPIPE, SIG_IGN);
// err_ttyopen(NULL);
if (flag_v) {
if (strcmp(configfile,"-") == 0) {
fprintf(stderr, "Read configuration from STDIN... \n",configfile);
} else {
fprintf(stderr, "Read config file(%s)... \n",configfile);
}
Net::set_verbose();
}
configure(configfile);
if (flag_v) {
fprintf(stderr,"Trying to build ring... \n"); }
buildring();
file_info();
data_transfer();
}
syntax highlighted by Code2HTML, v. 0.9.1