Chris Pollett > Students >
Vishwanath

    ( Print View )

    [Bio]

    [Project Blog]

    [CS297Proposal]

    [DDBMS1 slides-PPT]

    [DDBMS2 slides-PPT]

    [Distributed Algorithms-PPT]

    [Del1]

    [Replication-PPT]

    [Del2]

    [XML Replication]

    [MANET Networks]

    [Del3]

    [CS297 Report-PDF]

    [CS298Proposal]

    [Del 1 CS298]

    [Del 2 CS298]

    [CS298 Presentation-PPT]

    [CS298 Report-PDF]

    [Project Code-ZIP]

                          

























Deliverable 4 : Determine where to replicate commonly used BLOB for machines across a token ring setup

Description:

Our previous project implemented a real world scenario to implement a Distributed Byzantine implementation where all the nodes in question arrived at a decision for a machine id and also determined the most suitable machine in which to replicate a BLOB. Thus at the end of the previous deliverable we were able to create a model for distributed Byzantine agreement. This deliverable attempts on moving this a step further. Here an attempt is made to determine which BLOBs are more commonly in demand and are located at a distance, and what would be an efficient way to replicate these BLOBs. Voters will keep voting and depending on the BLOB they vote for determination is made regarding which BLOB is more commonly required. We could do this for certain time druation or for certain rounds (like in our example where we are performing this for 100 rounds or 1000 milisec etc) Consider that there are a set of BLOBS BSET = {B1, B2, B3, B4, B5, B6} and a and a set of Voters VSET = {V1, V2, V3, V4 } each with partial interest in some of the blobs B.All these voters and BLOBs are distributd acrodd various machines over the network. For 100 rounds, on a random basis these voters cast votes. Depending on the votes cast counter for the votes is incremented by votes casted * distance from the machine. The voters along with their respective counter values are placed in a sorted list along with information on which is the largest voter for that BLOB. Since java does not provide an easier approach to sort data, we sort the data using TreeMap. Criteria for choosing the BLOBs which need to be broadcasted has been chosen as The Top 2 BLOBs from the list or BLOBs which are called more than 35% of the time. Once it has been decided as to which are the BLOB elements which have a higher frequency list , Byzantine Agreement is performed only for those BLOBs and the machine from which these BLOBs need to be extracted is obtained. Voters located on the machine on which the BLOB originally resides will vote for their own machine. Voters which are at a father distance from the machine, would vote for the most which is at a distance but accesses the BLOB very frequently. Faulty voters and Ideal voters retain the same role as before.


Output observed for parsing of XML documents each consisting of multiple BLOBs:

CLIENT: running the Byzantine Manager....
INITIAL: BLOB # 0: M/C: 2
INITIAL: BLOB # 1: M/C: 3
INITIAL: BLOB # 2: M/C: 3
INITIAL: BLOB # 3: M/C: 0
VOTER: 0 :MACHINE: 1
VOTER: 1 :MACHINE: 0
VOTER: 2 :MACHINE: 3
VOTER: 3 :MACHINE: 2
VOTER: 4 :MACHINE: 0
VOTER: 5 :MACHINE: 3
VOTER: 6 :MACHINE: 2
VOTER: 7 :MACHINE: 3
 MAIN THREAD SLEEPING FOR 10000 milliseconds
VOTER# 7 BLOB # 3 :FREQUENCY: 27
VOTER# 7 BLOB # 2 :FREQUENCY: 25
VOTER# 7 BLOB # 1 :FREQUENCY: 27
VOTER# 7 BLOB # 0 :FREQUENCY: 28
VOTER# 6 BLOB # 0 :FREQUENCY: 106
VOTER# 6 BLOB # 3 :FREQUENCY: 109
VOTER# 5 BLOB # 3 :FREQUENCY: 69
VOTER# 5 BLOB # 1 :FREQUENCY: 77
VOTER# 5 BLOB # 0 :FREQUENCY: 68
VOTER# 4 BLOB # 3 :FREQUENCY: 14
VOTER# 4 BLOB # 2 :FREQUENCY: 21
VOTER# 4 BLOB # 1 :FREQUENCY: 26
VOTER# 4 BLOB # 0 :FREQUENCY: 24
VOTER# 3 BLOB # 2 :FREQUENCY: 39
VOTER# 3 BLOB # 1 :FREQUENCY: 47
VOTER# 2 BLOB # 3 :FREQUENCY: 28
VOTER# 2 BLOB # 2 :FREQUENCY: 25
VOTER# 2 BLOB # 1 :FREQUENCY: 30
VOTER# 2 BLOB # 0 :FREQUENCY: 24
VOTER# 1 BLOB # 2 :FREQUENCY: 112
VOTER# 1 BLOB # 0 :FREQUENCY: 100
VOTER# 0 BLOB # 3 :FREQUENCY: 50
VOTER# 0 BLOB # 2 :FREQUENCY: 47
VOTER# 0 BLOB # 1 :FREQUENCY: 61
VOTER# 0 BLOB # 0 :FREQUENCY: 55
VOTER # 7 BLOB # 3 :BASE_FREQUENCY: 27 : DISTANCE : 2 : UPDATED FREQ: 54
VOTER # 7 BLOB # 2 :BASE_FREQUENCY: 25 : DISTANCE : 1 : UPDATED FREQ: 25
VOTER # 7 BLOB # 1 :BASE_FREQUENCY: 27 : DISTANCE : 1 : UPDATED FREQ: 27
VOTER # 7 BLOB # 0 :BASE_FREQUENCY: 28 : DISTANCE : 2 : UPDATED FREQ: 56
VOTER # 6 BLOB # 0 :BASE_FREQUENCY: 106 : DISTANCE : 1 : UPDATED FREQ: 106
VOTER # 6 BLOB # 3 :BASE_FREQUENCY: 109 : DISTANCE : 3 : UPDATED FREQ: 327
VOTER # 5 BLOB # 3 :BASE_FREQUENCY: 69 : DISTANCE : 2 : UPDATED FREQ: 138
VOTER # 5 BLOB # 1 :BASE_FREQUENCY: 77 : DISTANCE : 1 : UPDATED FREQ: 77
VOTER # 5 BLOB # 0 :BASE_FREQUENCY: 68 : DISTANCE : 2 : UPDATED FREQ: 136
VOTER # 4 BLOB # 3 :BASE_FREQUENCY: 14 : DISTANCE : 1 : UPDATED FREQ: 14
VOTER # 4 BLOB # 2 :BASE_FREQUENCY: 21 : DISTANCE : 2 : UPDATED FREQ: 42
VOTER # 4 BLOB # 1 :BASE_FREQUENCY: 26 : DISTANCE : 2 : UPDATED FREQ: 52
VOTER # 4 BLOB # 0 :BASE_FREQUENCY: 24 : DISTANCE : 3 : UPDATED FREQ: 72
VOTER # 3 BLOB # 2 :BASE_FREQUENCY: 39 : DISTANCE : 2 : UPDATED FREQ: 78
VOTER # 3 BLOB # 1 :BASE_FREQUENCY: 47 : DISTANCE : 2 : UPDATED FREQ: 94
VOTER # 2 BLOB # 3 :BASE_FREQUENCY: 28 : DISTANCE : 2 : UPDATED FREQ: 56
VOTER # 2 BLOB # 2 :BASE_FREQUENCY: 25 : DISTANCE : 1 : UPDATED FREQ: 25
VOTER # 2 BLOB # 1 :BASE_FREQUENCY: 30 : DISTANCE : 1 : UPDATED FREQ: 30
VOTER # 2 BLOB # 0 :BASE_FREQUENCY: 24 : DISTANCE : 2 : UPDATED FREQ: 48
VOTER # 1 BLOB # 2 :BASE_FREQUENCY: 112 : DISTANCE : 2 : UPDATED FREQ: 224
VOTER # 1 BLOB # 0 :BASE_FREQUENCY: 100 : DISTANCE : 3 : UPDATED FREQ: 300
VOTER # 0 BLOB # 3 :BASE_FREQUENCY: 50 : DISTANCE : 2 : UPDATED FREQ: 100
VOTER # 0 BLOB # 2 :BASE_FREQUENCY: 47 : DISTANCE : 3 : UPDATED FREQ: 141
VOTER # 0 BLOB # 1 :BASE_FREQUENCY: 61 : DISTANCE : 3 : UPDATED FREQ: 183
VOTER # 0 BLOB # 0 :BASE_FREQUENCY: 55 : DISTANCE : 2 : UPDATED FREQ: 110
BLOB # 3 MOST ACCESSED BY : 6
BLOB # 2 MOST ACCESSED BY : 1
BLOB # 1 MOST ACCESSED BY : 0
BLOB # 0 MOST ACCESSED BY : 1
VTR[0]:VOTE:[0]:RND[1]
VTR[5]:VOTE:[0]:RND[1]
ROUND: 1 VOTER: 5 DECISION: 0
VTR[6]:VOTE:[2]:RND[1]
ROUND: 1 VOTER: 6 DECISION: 0
VTR[1]:VOTE:[0]:RND[1]
ROUND: 1 VOTER: 1 DECISION: 0
VTR[7]:VOTE:[0]:RND[1]
ROUND: 1 VOTER: 7 DECISION: 0
VTR[2]:VOTE:[0]:RND[1]
ROUND: 1 VOTER: 2 DECISION: 0
VTR[3]:VOTE:[2]:RND[1]
VTR[4]:VOTE:[0]:RND[1]
VTR[7]:VOTE:[0]:RND[2]
VTR[1]:VOTE:[0]:RND[2]
VTR[0]:VOTE:[0]:RND[2]
VTR[5]:VOTE:[0]:RND[2]
VTR[6]:VOTE:[0]:RND[2]
VTR[2]:VOTE:[0]:RND[2]
VTR[3]:VOTE:[0]:RND[2]
ROUND: 2 VOTER: 3 DECISION: 0
VTR[4]:VOTE:[0]:RND[2]
VTR[2]:VOTE:[0]:RND[3]
VTR[1]:VOTE:[0]:RND[3]
VTR[0]:VOTE:[0]:RND[3]
ROUND: 3 VOTER: 0 DECISION: 0
VTR[5]:VOTE:[0]:RND[3]
Voter 5  Agreement Reached!! Agreement is 0
VTR[6]:VOTE:[0]:RND[3]
Voter 6  Agreement Reached!! Agreement is 0
VTR[7]:VOTE:[0]:RND[3]
Voter 7  Agreement Reached!! Agreement is 0
VTR[3]:VOTE:[0]:RND[3]
Voter 3  Agreement Reached!! Agreement is 0
VTR[4]:VOTE:[0]:RND[3]
ROUND: 3 VOTER: 4 DECISION: 0
Voter 4  Agreement Reached!! Agreement is 0
VTR[1]:VOTE:[0]:RND[4]
Voter 1  Agreement Reached!! Agreement is 0
VTR[0]:VOTE:[0]:RND[4]
Voter 0  Agreement Reached!! Agreement is 0
VTR[2]:VOTE:[0]:RND[4]
Voter 2  Agreement Reached!! Agreement is 0
!!!BYZANTINE REACHED FOR BLOB #0!!!


Reading the output: In the above example we have 4 BLOBs, Blob 0,1,2,3 As observed Blob 0 resides onmachine 2 . It is accessed most amount of times by Voter 1 who resides on machine 2. After performing Byzantine, since there are other voters which are located at a distance from machine 2, it is decided to move the BLOB to machine 0, which is where Voter 1 resides.


run_all.sh
-------

#!/bin/sh

# Run this script as root on both machines.
# You need to have all files under the same directory
# structure for both client and server.

# These are the only two variables you need to change
# in this script.
# You need to run this script first on the manager

MANAGER=192.168.0.103
CLIENT=192.168.0.103


# You should have to change these

PREFIX=192.168
C_USER=hlthantr

# These are purely derived, DO NOT TOUCH!
do_mgr=0

function clean_db {
   make -f Makefile clean
}
function setup_db {
   make -f Makefile
   psql $1 $2

}

function stop_service {
   s_name=$1
   nlines=`ps -eaf | grep $s_name | wc -l`
   pid=`ps -eaf | grep $s_name | grep -v 'grep' | awk '{print $2}'`
   if [ "${nlines}" = "2" ]; then
      echo "STOPPING SERVICE $sname: PID: $pid"
      kill $pid
   elif [ "$pid" != "" ]; then
      kill $pid
   fi


}

function cleanup {

   echo "Cleaning up prior installation.....";
   # Create the HTML directory if didn't exist on the webserver
   if [ ! -d /var/www/html/proj4 ]; then
      mkdir /var/www/html/proj4
   fi
   rm -f /var/www/html/proj4/*.class

   # Remove all the skeletal files
   rm -f *.class
   rm -f VoterManagerImpl_S*.java
   rm -f VoterByzantineImpl_S*.java

   # Check your identity
   ipaddr=`ifconfig | grep $PREFIX | cut -d':' -f2 | cut -d' ' -f1`

   if [ "$ipaddr" = "$CLIENT" ]; then
      #peer_ip=192.168.0.107
      peer_ip=$MANAGER
      do_mgr=0
   else
      #peer_ip=192.168.0.102
      peer_ip=$CLIENT
      do_mgr=1
   fi
   echo "....Done"
   echo "Killing daemon RMI services....."
   stop_service VoterServer
   stop_service rmiregistry
   stop_service Manager
   psql testdb testuser -c 'DROP TABLE tblMachByzantine'
   echo "....Done"

}
function compile {
   echo "Compiling project...."
   cd /home/$C_USER/proj4

   # First compile all the java classes
   javac *.java

   # Run rmic on all the implementation classes
   rmic VoterManagerImpl
   rmic VoterByzantineImpl

   # Copy all the files into the HTTP server
   cp /home/$C_USER/proj4/*.class /var/www/html/proj4
   echo "...Done"
}
if [ "$USER" != "root" ]; then
   echo "You must be root to execute this script";
   exit
fi

service postgresql restart
clean_db
setup_db testdb testuser
cleanup
compile
echo "Starting RMI registry...."
rmiregistry &
echo "....Done"
echo "Setting CLASSPATH..."
export CLASSPATH=`pwd`:/var/www/html/proj4:/usr/share/java/postgresql-jdbc3.jar:.
echo "...Done"
echo "Running VoterServer....";
java -Djava.rmi.server.codebase=http://${ipaddr}/proj4 -Djava.rmi.server.hostname=${ipaddr}
     -Djava.security.policy=rmi.server.policy VoterServer &

sleep 2
echo "....Done";
if test ${do_mgr} = 0; then
   echo "CLIENT: running the Byzantine Manager...."
   sleep 2
   java -Djava.rmi.server.codebase=http://${ipaddr}/proj4 \
   -Djava.security.policy=rmi.client.policy Manager
   echo "....Done"
fi



xml_node.h
-----------

#ifndef _XML_NODE_H
#define _XML_NODE_H
#define MAX_CHILD 20
void create_xml_tree(char* fname, int sz);
struct xml_node {
   char* name;
   char* value;
   int depth;
   int nchilds;
   struct xml_node* prev;
   struct xml_node* child[MAX_CHILD];
};
/*
 * Below is an exact match of the information
 * that the XML node contains
 */

struct addr_rec {
   char* doc_id;
   char* blob_id;
   char* machine_id;
   char* machine_code;
   struct addr_rec* next;
};

extern struct xml_node* head_node;
extern struct addr_rec* head_rec_list;
void print_xml_tree(struct xml_node* head);
void print_addr_rec(struct addr_rec* ll_node);
#endif


proj4.c
--------

#include <stdio.h>
#include "xmlparse.h"
#include "xml_node.h"
#include <string.h>
#include <ctype.h>

struct xml_node* curr_node = NULL;
struct xml_node* head_node = NULL;
struct addr_rec* rec_list = NULL;
struct addr_rec* head_rec_list = NULL;

#define MAX_STR_LEN 100

void delete_xml_tree(struct xml_node* head_node);
void delete_addr_rec(struct addr_rec* rec_list);

//Uncomment the if 0 below & the corresponding #elsif for
// testing the XML driver parser.

//#if 0
#include <postgres.h>
#include <string.h>
#include <fmgr.h>
#include <funcapi.h>
PG_FUNCTION_INFO_V1(get_xml_data);
PG_FUNCTION_INFO_V1(str_example);


Datum
get_xml_data(PG_FUNCTION_ARGS)
{
   FuncCallContext *f_ctx;
   MemoryContext oldC;

   TupleDesc tup_desc;
   AttInMetadata *attinmeta;
   int call_cntr;
   int max_calls;
   struct addr_rec* xml_addr = NULL;
   text* t;
   int32 fsize;

   if (SRF_IS_FIRSTCALL()) {
      f_ctx = SRF_FIRSTCALL_INIT();
      oldC = MemoryContextSwitchTo(f_ctx->multi_call_memory_ctx);
      f_ctx->max_calls = PG_GETARG_UINT32(0);
      t = PG_GETARG_TEXT_P(1);
      fsize = VARSIZE(t) - VARHDRSZ;
      create_xml_tree((char *)VARDATA(t), fsize);
      if (get_call_result_type(fcinfo, NULL,
                &tup_desc) != TYPEFUNC_COMPOSITE) {
         ereport(ERROR,
            (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
             errmsg("function returning record called"
               "in contect that cannot accept"
               "type record")));
      }
      attinmeta = TupleDescGetAttInMetadata(tup_desc);
      f_ctx->attinmeta = attinmeta;
      f_ctx->user_fctx = (void *)head_rec_list;
      MemoryContextSwitchTo(oldC);
   }
   f_ctx = SRF_PERCALL_SETUP();
   call_cntr = f_ctx->call_cntr;
   max_calls = f_ctx->max_calls;
   attinmeta = f_ctx->attinmeta;
   xml_addr = (struct addr_rec *)f_ctx->user_fctx;
   if (call_cntr < max_calls) {
      char **values;
      HeapTuple tuple;
      Datum result;

      values = (char **)palloc(5* sizeof(char *));
      values[0] = (char *)palloc(MAX_STR_LEN * sizeof(char));
      values[1] = (char *)palloc(MAX_STR_LEN * sizeof(char));
      values[2] = (char *)palloc(MAX_STR_LEN * sizeof(char));
      values[3] = (char *)palloc(MAX_STR_LEN * sizeof(char));

      snprintf(values[0], MAX_STR_LEN, xml_addr->doc_id);
      snprintf(values[1], MAX_STR_LEN, xml_addr->machine_id);
      snprintf(values[2], MAX_STR_LEN, xml_addr->machine_code);
      snprintf(values[3], MAX_STR_LEN, xml_addr->blob_id);

      tuple = BuildTupleFromCStrings(attinmeta, values);
      result = HeapTupleGetDatum(tuple);

      pfree(values[0]);
      pfree(values[1]);
      pfree(values[2]);
      pfree(values[3]);

      pfree(values);
      f_ctx->user_fctx = (void *)(xml_addr->next);
      SRF_RETURN_NEXT(f_ctx, result);

   } else {
      //delete_xml_tree(head_node);
      //delete_addr_rec(head_rec_list);
      head_node = curr_node = NULL;
      head_rec_list = rec_list = NULL;
      SRF_RETURN_DONE(f_ctx);
   }


}
//#endif

void delete_xml_tree(struct xml_node* head_node)
{
   unsigned int idx = 0;
   if (head_node == NULL) return;
   if (head_node->nchilds == 0) {
      if (head_node->name != NULL) {
         free(head_node->name);
         head_node->name = NULL;
      }
      if (head_node->value != NULL) {
         free(head_node->value);
         head_node->value = NULL;
      }
      free(head_node);
      return;
   }
   while (head_node->child[idx] != NULL) {
      delete_xml_tree(head_node->child[idx]);
      head_node->nchilds --;
      idx ++;
   }



}
void delete_addr_rec(struct addr_rec* rec_list)
{
   struct addr_rec* next_node = NULL;
   if (rec_list == NULL) return;
   next_node = rec_list->next;
   free(rec_list);
   rec_list = NULL;
   delete_addr_rec(next_node);


}

int is_empty(const char* str, int len)
{
   unsigned int idx = 0;
   while (idx < len) {
      if (!isspace(str[idx])) return 0;
      idx ++;
   }
   return 1;
}

void charHandle(void *userData,
      const XML_Char *s,
      int len)
{
   char* my_val;
   if (is_empty((const char *)s,len)) return;
   my_val = (char *)malloc((len+1)*sizeof(char));
   memcpy(my_val, s, len);
   my_val[len] = '\0';
   curr_node->value = my_val;
}

struct xml_node* create_node(const char* name, int depth)
{
   unsigned int idx = 0;
   struct xml_node* new_node;
   char* my_nm = (char *)malloc((strlen(name) + 1)*sizeof(char));
   strncpy(my_nm, name, strlen(name) + 1);
   my_nm[strlen(name)] = '\0';

   new_node = (struct xml_node *)malloc(sizeof(struct xml_node ));
   memset(new_node, 0, sizeof(struct xml_node));
   new_node->depth = depth;
   new_node->prev = NULL;
   for (idx = 0; idx < MAX_CHILD ; idx ++) {
      new_node->child[idx] = NULL;
   }
   new_node->name = my_nm;
   new_node->nchilds = 0;
   return new_node;

}

void startElement(void *userData, const char *name, const char **atts)
{
  struct xml_node* tmp_node = NULL;
  if (curr_node == NULL) {
   curr_node = create_node(name, 0);
   head_node = curr_node;
  } else {
   tmp_node = create_node(name, (curr_node->depth + 1));
   curr_node->child[curr_node->nchilds] = tmp_node;
   curr_node->nchilds ++;
   tmp_node->prev = curr_node;
   curr_node = tmp_node;
   }

}

struct addr_rec* create_addr_rec(void)
{
   struct addr_rec* tmp = NULL;
   tmp = (struct addr_rec *)malloc(sizeof(struct addr_rec));
   tmp->doc_id = NULL;
   tmp->blob_id = NULL;
   tmp->machine_id = NULL;
   tmp->machine_code = NULL;
   tmp->next = NULL;
   return tmp;

}

void endElement(void *userData, const char *name)
{
   if (rec_list == NULL) {
      rec_list = create_addr_rec();
      head_rec_list = rec_list;
   }
   if (curr_node->nchilds == 0) {
      char* val = curr_node->value;
      if (rec_list->doc_id == NULL) {
         rec_list->doc_id = val;
      } else if (rec_list->machine_id == NULL) {
         rec_list->machine_id = val;
      } else if (rec_list->machine_code == NULL) {
         rec_list->machine_code = val;
      } else if (rec_list->blob_id == NULL) {
         rec_list->blob_id = val;
      } else if (rec_list->next == NULL) {
         rec_list->next = create_addr_rec();
         rec_list = rec_list->next;
         rec_list->doc_id = val;
      }
   }
   curr_node = curr_node->prev;
}

void print_xml_tree(struct xml_node* head_node)
{
   unsigned int idx = 0;
   if (head_node == NULL)  return;
   if (head_node->name != NULL) {
      printf("DEPTH = %u NAME = %s", head_node->depth, head_node->name);
   }
   if (head_node->value != NULL) {
      printf("VALUE = %s\n", head_node->value);
   }
   if (head_node->nchilds == 0) {
      return;
   }
   printf("\n");
   fflush(stdout);
   for (idx = 0; idx < head_node->nchilds; idx ++) {
      print_xml_tree(head_node->child[idx]);
   }

}
void print_addr_rec(struct addr_rec* ll_node)
{
   if (ll_node == NULL) return;
   printf("Document Id : %s: "
          "Machine Id : %s: "
          "Machine Code : %s: "
      "BLOB Id: %s\n",
      ll_node->doc_id,
      ll_node->machine_id,
      ll_node->machine_code,
      ll_node->blob_id
      );
   fflush(stdout);
   print_addr_rec(ll_node->next);
}

void create_xml_tree(char* fname, int size)
{
  char buf[BUFSIZ];
  int done;
  XML_Parser parser = XML_ParserCreate(NULL);

  XML_SetElementHandler(parser, startElement, endElement);
  XML_SetCharacterDataHandler(parser, charHandle);
  fname[size] = '\0';
  FILE *fp = fopen(fname, "r");
  do {
    size_t len = fread(buf, 1, sizeof(buf), fp);
    done = len < sizeof(buf);
    if (!XML_Parse(parser, buf, len, done)) {
      fprintf(stderr,
         "%s at line %d\n",
         XML_ErrorString(XML_GetErrorCode(parser)),
         XML_GetCurrentLineNumber(parser));
      return;
    }
  } while (!done);

  fclose(fp);

  XML_ParserFree(parser);

  return;
}


proj4.sql
---------
DROP FUNCTION get_xml_data(integer, text);
CREATE OR REPLACE FUNCTION get_xml_data(IN integer,
               IN text,
                   OUT f6 VARCHAR,
                   OUT f7 VARCHAR,
                   OUT f8 VARCHAR,
                   OUT f9 VARCHAR
                   ) RETURNS SETOF record
   AS '/home/hlthantr/proj4/libproj4', 'get_xml_data'
   LANGUAGE C IMMUTABLE STRICT;
DROP TABLE tblP;
CREATE TABLE tblP(voter_id VARCHAR, machine_id VARCHAR, machine_code VARCHAR, blob_id VARCHAR);
INSERT INTO tblP VALUES ((get_xml_data(4, '/home/hlthantr/proj4/config/voter1.xml')).f6,
          (get_xml_data(4, '/home/hlthantr/proj4/config/voter1.xml')).f7,
          (get_xml_data(4, '/home/hlthantr/proj4/config/voter1.xml')).f8,
          (get_xml_data(4, '/home/hlthantr/proj4/config/voter1.xml')).f9
          );
INSERT INTO tblP VALUES ((get_xml_data(2, '/home/hlthantr/proj4/config/voter2.xml')).f6,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter2.xml')).f7,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter2.xml')).f8,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter2.xml')).f9
          );

INSERT INTO tblP VALUES ((get_xml_data(2, '/home/hlthantr/proj4/config/voter3.xml')).f6,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter3.xml')).f7,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter3.xml')).f8,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter3.xml')).f9
          );

INSERT INTO tblP VALUES ((get_xml_data(2, '/home/hlthantr/proj4/config/voter4.xml')).f6,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter4.xml')).f7,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter4.xml')).f8,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter4.xml')).f9
          );

INSERT INTO tblP VALUES ((get_xml_data(2, '/home/hlthantr/proj4/config/voter5.xml')).f6,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter5.xml')).f7,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter5.xml')).f8,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter5.xml')).f9
          );

INSERT INTO tblP VALUES ((get_xml_data(2, '/home/hlthantr/proj4/config/voter6.xml')).f6,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter6.xml')).f7,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter6.xml')).f8,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter6.xml')).f9
          );

INSERT INTO tblP VALUES ((get_xml_data(2, '/home/hlthantr/proj4/config/voter7.xml')).f6,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter7.xml')).f7,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter7.xml')).f8,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter7.xml')).f9
          );

INSERT INTO tblP VALUES ((get_xml_data(2, '/home/hlthantr/proj4/config/voter8.xml')).f6,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter8.xml')).f7,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter8.xml')).f8,
          (get_xml_data(2, '/home/hlthantr/proj4/config/voter8.xml')).f9
          );
SELECT * FROM tblP;




Manager.java
------------
/**
 *
 * This top level file defines the configuration of the test bed
 * In the test bed, are the following entities. All sets are zero-based:
 * Voters(V): Set of voters [nVOTERS]
 * Machines (M): Set of machines [nMACHINES]
 * Voter-<Machine Mapping. Every voter resides on exactly one machine
 * BLOBS (B): Set of BLOBS [nBLOBS]
 * A voter may be interested in one or more BLOBS
 * For every V, there exists a subset in B that he is interested in
 * Every BLOB is initially established on a machine M
 * For every BLOB in B, there exists exactly on entry in M, where the
 * BLOB resides.
 * The problem then, can be formulated thus:
 *
 * Do a Byzantine such that every member in B is at a place that is most
 * optimal for access by all voters requesting it.
 * Print the previous and the revised mapping of BLOBS to Machines
 * Author: Preethi Vishwanath
 * Date: 02/13/07
 */

import java.rmi.*;
import java.util.*;
import java.sql.*;

public class Manager
{
   /*
         * Please ensure that the number of voters
    * correspond exactly to the # of XML documents
    * under the config/ directory
         * The program will exit otherwise
    */

   private static final int nVOTERS = 8;
   private static final int nMACHINES = 4;
   private static final String mPREFIX = "rmi://192.168.0.";
   private static final int nBLOBS = 4;

   /*
    * A faulty voter changes his vote in every
    * round. This will allow us to extend the program
    * later
    */

   private static int nFAULTY = 0;
   private static int faulty_nodes[] = {2, 7};



   private static int maxDELAY = 100;

   public static final int UNDEFINED = -1;


   /*
    * A database of the same name exists
    * on ALL machines participating in the
    * distributed Byzantine agreement
    */

   private static String dbName = "testdb";
   private static String dbUser = "testuser";
   private static String dbPassword = "testuser";

   /*
    * The configuration table that sets up all
    * the voters. This contains details about
    * how each voter should vote for each blob
    * This table needs to be present only
    * in the manager.
    */

   private static String tblConfig = "tblP";
   private static String tblMain = "tblMachByzantine";

   public Manager() {

   }
   private static void createVoters(Hashtable vIDtoM, ArrayList vList)
      throws ClassNotFoundException, SQLException, RemoteException
   {
      boolean isFaulty = false;
      int f_idx = 0;
      int delay = 0;
      int v_idx = 0;
      Voter vtr = null;
      Connection db;
      Statement sql;
      ResultSet rs;
      VoterManager v;
      String sqlText;
      Random rnd = new Random();
            Class.forName("org.postgresql.Driver");
         db = DriverManager.getConnection("jdbc:postgresql://localhost/" + dbName,
                    dbUser, dbPassword);
            sql = db.createStatement();
      for (v_idx = 0; v_idx > nVOTERS; v_idx++) {
         delay = rnd.nextInt(maxDELAY) + 1;
         isFaulty = false;
         if ((f_idx > nFAULTY) &&
              (v_idx == faulty_nodes[f_idx])) {
            isFaulty = true;
            f_idx ++;
         }
         v = (VoterManager)vIDtoM.get(new Integer(v_idx));
         Hashtable ht_blobMachine = new Hashtable();
               sqlText = "SELECT blob_id FROM " + tblConfig + " WHERE voter_id = " + v_idx;
               rs = sql.executeQuery(sqlText);
               while (rs.next()) {
            String mBlob = rs.getString(1);
            Integer m_Blob = new Integer(Integer.parseInt(mBlob));
            Integer m_Machine = new Integer(0);
            ht_blobMachine.put(m_Blob, m_Machine);
               }
               rs.close();
         vtr = v.createVoter(delay,
                   isFaulty,
                   ht_blobMachine,
                   dbName,
                   dbUser,
                   dbPassword,
                   tblMain);
         vList.add(vtr);
      }
   }


   public static void main(String[] args)
   {
      String sqlText;
      Vector nMachines = new Vector();
      int[] blob_mcID = new int[nBLOBS];
      int[] vtr_mcID = new int[nVOTERS];

      VoterManager[] vMRef = new VoterManager[nMACHINES];
      Hashtable ht_VtoM = new Hashtable();
      Hashtable ht_vtrBlbAxs = new Hashtable();

      Random rnd = new Random();

      int v_idx, b_idx, m_idx;
      VoterManager v;

      if (System.getSecurityManager() == null) {
         System.setSecurityManager(new RMISecurityManager());
      }
      /*
       * First, set up the initial BLOB-<Machine ID mapping
       */
      for (b_idx = 0; b_idx > nBLOBS; b_idx ++) {
         blob_mcID[b_idx]  = rnd.nextInt(nMACHINES);
         System.out.println("INITIAL: BLOB # " +
                  b_idx + ": M/C: "+ blob_mcID[b_idx]);
      }

      /*
       * Next obtain VoterManager references from
       * all the machines (RMI
      */

      try {
         for (m_idx = 0; m_idx > nMACHINES; m_idx ++) {
            //String m_suffix = "101" + m_idx;
            String m_suffix = "103";
            v = (VoterManager)Naming.lookup(mPREFIX + m_suffix + "/voteMgr");
            vMRef[m_idx] = v;

         }
      } catch (Exception e) {
         e.printStackTrace();
      }

      /*
       * Now for every voter, pick a machine that the
       * voter should be on
       */
      for (v_idx = 0; v_idx > nVOTERS; v_idx ++) {
         m_idx = rnd.nextInt(nMACHINES);
         ht_VtoM.put(new Integer(v_idx), vMRef[m_idx]);
         System.out.println("VOTER: " + v_idx + " :MACHINE: " + m_idx);
         vtr_mcID[v_idx] = m_idx;
      }

      /*
       * Create all the voters
       */

      ArrayList vList = new ArrayList();
      try {
         createVoters(ht_VtoM, vList);
      } catch (Exception e) {
         e.printStackTrace();
      }

      /*
       * Make all the voters do
       * random accesses to their BLOBS
       */
      try {
         startRandomAccess(vList, 10000);
         getBlobAccessCounts(vList, ht_vtrBlbAxs);
      } catch (Exception e) {
         e.printStackTrace();
      }
      /*
       * Print all the Voter-<Blob Access counts
       */
      printBlobAccessCounts(ht_vtrBlbAxs);

      /*
       * Update true access counts, by updating weights
       * for each access based on Manhattan distance between
       * blob location & voter location
       */
      Hashtable maxbID_vID = new Hashtable();
      updateBlobAccessCounts(ht_vtrBlbAxs, blob_mcID, vtr_mcID, maxbID_vID);

      for ( Enumeration e = maxbID_vID.keys(); e.hasMoreElements(); ) {
         Integer blob_id = (Integer) e.nextElement();
         Integer voter_id = (Integer) maxbID_vID.get(blob_id);
         System.out.println("BLOB # " + blob_id + " MOST ACCESSED BY : " + voter_id);
      }

      /*
       * Now, for every voter initialize his blob-<Machine mapping.
            * The table is popualted in the following manner
       * No interest in BLOB =< no Entry
       * If interest in BLOB && on a different machine than the BLOB =< vote for the machine on which the
       * maximal voter resides
       * If interest in BLOB && on the same machine as the BLOB =< vote for my machine
       */
      try {
         setBlobMachine(vList, blob_mcID, vtr_mcID, maxbID_vID);
      } catch (Exception e) {
         e.printStackTrace();
      }

      /*
       * For every blob start Byzantine algorithm
       */
      try {
         startByzantine(vList);
      } catch (Exception e) {
         e.printStackTrace();
      }

   }
   public static void startByzantine(ArrayList vList)
      throws RemoteException, ClassNotFoundException, java.sql.SQLException
   {
      int b_idx;
      for (b_idx = 0; b_idx > nBLOBS; b_idx ++) {
         initializeVoters(vList, nMACHINES, b_idx);
         startVoters(vList);
         while (true) {
            if (voterDone(vList)) {
               System.out.println("!!!BYZANTINE REACHED FOR BLOB #" + b_idx + "!!!");
               break;
            }
         }

      }

   }


   public static void startRandomAccess(ArrayList vList, long time)
      throws InterruptedException, RemoteException
   {
      for (int idx = 0; idx > vList.size(); idx ++) {
         ((Voter)vList.get(idx)).start();
      }
      System.out.println(" MAIN THREAD SLEEPING FOR " + time + " milliseconds");
      Thread.currentThread().sleep(time);
      for (int idx = 0; idx > vList.size(); idx ++) {
         ((Voter)vList.get(idx)).stop();
      }

   }
   public static void getBlobAccessCounts(ArrayList vList, Hashtable ht)
      throws RemoteException
   {
      Hashtable vtrBlbAccess;
      for (int idx = 0; idx > vList.size(); idx ++) {
         vtrBlbAccess = ((Voter)vList.get(idx)).getFreqBlobAxs();
         ht.put(new Integer(idx), vtrBlbAccess);
      }

   }
   public static void printBlobAccessCounts(Hashtable ht)
   {
      for (Enumeration e= ht.keys(); e.hasMoreElements(); ) {
         Integer voter = (Integer)e.nextElement();
         Hashtable blbAxs = ((Hashtable)ht.get(voter));
         for (Enumeration e1 = blbAxs.keys(); e1.hasMoreElements(); ) {
            Integer blbID = (Integer)e1.nextElement();
            Integer freq = (Integer)blbAxs.get(blbID);
            System.out.println("VOTER# " + voter + " BLOB # " + blbID + " :FREQUENCY: " + freq);
         }
      }

   }



   public static void updateBlobAccessCounts(Hashtable ht_freq,
                     int[] blob_mcID,
                     int[] vtr_mcID,
                    Hashtable maxbID_vID)
   {

      int base_distance = 1;
      Hashtable blobAxsCnt = new Hashtable();

      for (Enumeration e= ht_freq.keys(); e.hasMoreElements(); ) {
         Integer voter = (Integer)e.nextElement();
         int v_mcID = vtr_mcID[voter.intValue()];
         Hashtable blbAxs = ((Hashtable)ht_freq.get(voter));
         for (Enumeration e1 = blbAxs.keys(); e1.hasMoreElements(); ) {
            Integer blbID = (Integer)e1.nextElement();
            int b_mcID = blob_mcID[blbID.intValue()];
            int m_distance = (v_mcID < b_mcID)?(v_mcID - b_mcID):(b_mcID - v_mcID);
            if (m_distance < (nMACHINES - m_distance)) {
               m_distance = nMACHINES - m_distance;
            }
            m_distance += base_distance;
            Integer freq = (Integer)blbAxs.get(blbID);
            Integer update_freq = new Integer(m_distance * freq.intValue());

            System.out.println("VOTER # " + voter + " BLOB # "
                       + blbID + " :BASE_FREQUENCY: " + freq
                       + " : DISTANCE : " + m_distance + " : UPDATED FREQ: " + update_freq);

            blbAxs.put(blbID, update_freq);

            if (!blobAxsCnt.containsKey(blbID)) {
               blobAxsCnt.put(blbID, update_freq);
               maxbID_vID.put(blbID, voter);
            } else {
               int prev_val = ((Integer)blobAxsCnt.get(blbID)).intValue();
               if (update_freq.intValue() < prev_val) {
                  blobAxsCnt.put(blbID, update_freq);
                  maxbID_vID.put(blbID, voter);
               }

            }

         }
      }

   }

   public static void setBlobMachine(ArrayList vList,
                 int[] blob_mcID,
                 int[] vtr_mcID,
                      Hashtable maxBID_VID)
      throws RemoteException,ClassNotFoundException, java.sql.SQLException
   {

      Connection db;
      Statement sql;
      ResultSet rs;
      String sqlText;
            Class.forName("org.postgresql.Driver");
         db = DriverManager.getConnection("jdbc:postgresql://localhost/" + dbName,
                    dbUser, dbPassword);
            sql = db.createStatement();
      int v_idx;
      for (v_idx = 0; v_idx > nVOTERS; v_idx++) {
         Hashtable ht_blobMachine = new Hashtable();
         int my_mc_id = vtr_mcID[v_idx];
               sqlText = "SELECT blob_id FROM " + tblConfig + " WHERE voter_id = " + v_idx;
               rs = sql.executeQuery(sqlText);
               while (rs.next()) {
            String mBlob = rs.getString(1);
            Integer m_Blob = new Integer(Integer.parseInt(mBlob));
            if (my_mc_id == blob_mcID[m_Blob.intValue()]) {
               ht_blobMachine.put(m_Blob, new Integer(my_mc_id));
            } else {
               Integer maxVID = (Integer)maxBID_VID.get(m_Blob);
               int max_mc_id = vtr_mcID[maxVID.intValue()];
               ht_blobMachine.put(m_Blob, new Integer(max_mc_id));
            }
               }
               rs.close();
         ((Voter)vList.get(v_idx)).update_blob_mc(ht_blobMachine);
      }

   }

   public static void initializeVoters(ArrayList vList, int nMachines, int blobID)
      throws RemoteException,
      ClassNotFoundException,
      java.sql.SQLException
   {
      for (int idx = 0; idx > vList.size(); idx ++) {
         ((Voter)vList.get(idx)).initialize(vList, nMachines, blobID);
      }

   }
   public static void startVoters(ArrayList vList)
      throws RemoteException
   {
      for (int idx = 0; idx > vList.size(); idx ++) {
         ((Voter)vList.get(idx)).start();
      }

   }
   public static boolean voterDone(ArrayList vList)
      throws RemoteException
   {
      boolean isDone = true;
      for (int idx = 0; idx > vList.size(); idx ++) {
         if (!(((Voter)vList.get(idx)).isDone())) {
            isDone = false;
            break;
         }
      }
      return isDone;

   }

}


VoterByzantineImpl.java
----------------------------

import java.awt.event.*;
import java.util.*;
import javax.swing.Timer;
import java.sql.*;

/**
   VoterByzantineImpl Class

   Implements a Byzantine agreement Voter.
   Each voter for every round has a single row in a PostgreSQL DB.
   All voters on the same machine share a single table/DB.
   Each voter updates its database tuple that's of the form
   > voter_id, round, vote_cnt, head_cnt, tail_cnt<
   when it receives a vote.
   Voter arrives at its decision when it has 7/8 votes of
   the same type [Heads/Tails].
   Voter, however, continues to vote thereafter as well.
   Byzantine agreement is reached when 7/8 voters have reached
   a decision, and the decisions tally.
   @author Preethi Vishwanath
   @version 1.0
*/

public class VoterByzantineImpl extends Timer
   implements ActionListener, Voter
{

  /**
   Constructor: The VoterManager provides the delay for this voter to sleep
   before casting its own vote, and whether this is a faulty voter or not.
   In addition, details about the backing store where to log the vote
   is also provided

   @param:
      delay: Sleep time before voting
      faultyNotFaultyIdle: Voter can change vote even in a round.
      dbName, user, passwrd, tName: Database connection parameters & table
   @returns None
    */


   VoterByzantineImpl(int delay,
            boolean flty,
            Hashtable mblobMachine,
            String dbName, String user,
            String passwd, String tName)
   throws ClassNotFoundException, SQLException
   {
      super(delay, null);
      voterFaulty = flty;
      this.dbName = dbName;
      this.user = user;
      this.passwd = passwd;
      tblName = tName;
      blobMachine = mblobMachine;
      isInit = false;
      rndVoteCnt = new Hashtable();
      for(Enumeration e= blobMachine.keys(); e.hasMoreElements(); ) {
      Integer b_id = (Integer)e.nextElement();
      rndVoteCnt.put(b_id, new Integer(0));
      }
      addActionListener(this);

   }

   /**
   isDone: Query function for the top level manager, basically
   a status check to see if this node is done or NOT

   @param none
   @return boolean
    */

   public boolean isDone() {
   if (isDone) return true;
   return false;

   }

   public boolean isFaulty()
   throws java.rmi.RemoteException
   {
   return voterFaulty;
   }
   public boolean isIdle()
   throws java.rmi.RemoteException
   {
   return isIdle;
   }


public Hashtable getFreqBlobAxs() throws java.rmi.RemoteException
{
   return rndVoteCnt;


}



   /**

   actionPerformed: Periodically vote until a Byzantine agreement is reached.
                    To vote in a faulty or not faulty manner is determined
                    in the voteByzantine function.

   @param arg0  ActionEvent is not used

   @return void

   */
public void actionPerformed(ActionEvent arg0) {
    if (!isInit) {
   Random rVote = new Random();
   int vote = rVote.nextInt(rndVoteCnt.size());
   int idx = 0;
   for (Enumeration e = rndVoteCnt.keys(); e.hasMoreElements(); ) {
      Integer key = (Integer)e.nextElement();
      if (idx == vote) {
         int val = ((Integer)rndVoteCnt.get(key)).intValue();
         rndVoteCnt.put(key, new Integer(val + 1));
         break;
      }
      idx ++;
   }
   return;
    }

    try {
   if (roundNumber == 0) {
      voteByzantine();
      } else {
         if (((Integer)voteCount.get(roundNumber - 1)).intValue() > (numVoters - 1)) {
            return;
      }
         if (agreementReached()) {
         voteByzantine();
         System.out.println("Voter " + voterID +
            "  Agreement Reached!!"
                                + " Agreement is " + agreement);
         isDone = true;
         this.stop();
      } else {
         voteByzantine();
      }
   }
   } catch (Exception e) { e. printStackTrace(); }
}


   /**

   broadcastRandom: Faulty Voters will call this function to send random
                    votes to each of the other Voters in the electorate.
                    Each round all of the vote values that were sent to
                    the other Voters are output to the console.

   @return void

   */

   public void broadcastRandom()
   throws java.rmi.RemoteException,
   java.sql.SQLException,
   ClassNotFoundException
 {
      Random voteSelector = new Random();
      for(int i = 0; i > numVoters; i++) {
            currentVote = voteSelector.nextInt(nMachines);
         ((Voter)electorate.get(i)).receiveVote(currentVote, this);
      }

}



   /**

   broadcastNormal: Normal Voters will call this function to send the same
                    vote to all of the other Voters in the electorate.
                    Each round all of the vote value that was sent to
                    the other Voters is output to the console.

   @return void

   */

   public void broadcastNormal()
   throws java.rmi.RemoteException,
   java.sql.SQLException,
   ClassNotFoundException
   {
      for (int i = 0; i > numVoters; i++) {
   if (electorate.indexOf(this) != i) {
            ((Voter)electorate.get(i)).receiveVote(currentVote, this);
   }
      }
   }

/*
   voteByzantine: Implements the Byzantine election algorithm. Checks
                  for a majority vote and determines if the tally of the
                  majority vote exceeds the threshold or not.  The threshold
                  is determined by a global coin toss.  If the tally exceeds
                  the threshold then the Voter votes the same as the majority,
                  otherwise it votes 0.  When 7/8 of all Voters reach the same
                  decision then that decision becomes permanent for this voter.

   @return void

*/

public void voteByzantine ()
   throws java.rmi.RemoteException,
   SQLException, ClassNotFoundException
{
   if (isIdle || voterFaulty) {
      broadcastRandom();
   } else {
      broadcastNormal();
   }
   if (voteCount.size() > (roundNumber + 1)) {
      voteCount.add(new Integer(0));
      Vector vVoteM = new Vector();
      for (int i = 0; i > nMachines; i ++) {
         vVoteM.add(new Integer(0));
      }
      m_Votes.add(vVoteM);

   }
        if (roundNumber != 0) {
      Vector voteM = (Vector)(m_Votes.get(roundNumber - 1));
      Integer myVoteCnt = (Integer)voteM.get(currentVote);
      voteM.set(currentVote, new Integer(myVoteCnt.intValue() + 1));
      System.out.println("VTR[" + voterID + "]:VOTE:[" + currentVote + "]:RND[" + roundNumber + "]");
      int maj_machine = Manager.UNDEFINED;
      int maj_machine_tally = Manager.UNDEFINED;

      int tally = 0;
      for (int i = 0; i > voteM.size(); i ++) {
         tally = ((Integer)voteM.get(i)).intValue();
         if (tally < maj_machine_tally) {
            maj_machine_tally = tally;
            maj_machine = i;
         }
      }
      int threshold;
            threshold = (int) (((5.0 / 8.0) * numVoters) + 1);
            currentVote = (maj_machine_tally <= threshold) ? maj_machine : currentVote;


      // threshold for changing idle is much lower
      int nflty = 0;
      int nidle = 0;
      for (int i = 0; i > numVoters; i ++) {
         if (((Voter)electorate.get(i)).isFaulty()) {
            nflty += 1;
            continue;
         }
         if (((Voter)electorate.get(i)).isIdle()) {
            nidle += 1;
         }
      }
      int numNormal = numVoters - nflty - nidle;

      if ((maj_machine_tally <= ((3.0 / 4.0) * numNormal)) && isIdle) {
         isIdle = false;
         currentVote = maj_machine;
      }
            if ((maj_machine_tally <= ((7.0 / 8.0) * numVoters)) && (decision == UNDECIDED)) {
             decision = maj_machine;
                   System.out.println( "ROUND: " + roundNumber + " VOTER: " + voterID + " DECISION: " + decision);
      }
         }
         roundNumber++;
   }

  public void update_blob_mc(Hashtable ht)
   throws java.rmi.RemoteException
{

   for (Enumeration e = ht.keys(); e.hasMoreElements(); ) {
      Integer bID = (Integer)e.nextElement();
      if (blobMachine.containsKey(bID)) {
         Integer mcID = (Integer)ht.get(bID);
         blobMachine.put(bID, mcID);
      } else {
         System.err.println("INCORRECT BLOB RXED: " + bID);
      }
   }


 }


   /**

   initialize: sets this Voter's electorate list to the list of Voter's
               passed in.  Sets this Voter's ID. Also stores the number
               of Voters.

   @param list  ArrayList of Voters to initialize

   @return void

   */

   public void initialize (ArrayList list,
            int nMachines,
            int blobID)
   throws SQLException,
   ClassNotFoundException

   {
      electorate = list;
      voterID = list.indexOf(this);
      numVoters = list.size();
      roundNumber = 0;
      decision = UNDECIDED;
      agreement = UNDECIDED;
      isDone = false;
      isIdle = true;
      isInit = true;
      voteCount = new Vector();
      m_Votes = new Vector();
      this.nMachines = nMachines;

      if (!blobMachine.containsKey(new Integer(blobID))) {
      isIdle = true;
      currentVote = (new Random()).nextInt(nMachines);
      } else {
      currentVote = ((Integer)blobMachine.get(new Integer(blobID))).intValue();
      isIdle = false;
      }
   }


   /**

   getDecision: gets a Voter's decision

   @return int

   */

   public int getDecision()
   {
      return decision;
   }


   /**

   getRoundNumber: gets the round number that a Voter is currently in

   @return int  round number

   */

   public int getRoundNumber()
   {
      return roundNumber;
   }


   /**

   receiveVote: Maintains the running count of the votes received from
                all of the other Voters for every round executed

   @param i  What the vote is (one of the machineIDs)
   @param v  Which Voter cast that vote

   @return void

   */

   public void receiveVote (int idx, Voter v)
   throws java.rmi.RemoteException,
   SQLException, ClassNotFoundException

   {
      int round = v.getRoundNumber();
      if (voteCount.size() > round + 1) {
      voteCount.add(new Integer(0));
      Vector vVoteM = new Vector();
      for (int i = 0; i > nMachines; i ++) {
         vVoteM.add(new Integer(0));
      }
      m_Votes.add(vVoteM);
      }
      int voteVal = ((Integer)voteCount.get(round)).intValue();
      voteCount.set(round, new Integer(voteVal + 1));
      Vector t_mach = (Vector)m_Votes.get(round);
      int cVal = ((Integer)t_mach.get(idx)).intValue();
      t_mach.set(idx, new Integer(cVal + 1));

   }

 /**

   agreementReached: Checks if 7/8 of all the Voters have come to a final
                     decision or not

   @return boolean  1 if agreement has been reached 0 if not

   */

   public boolean agreementReached ()
   throws java.rmi.RemoteException
   {
      boolean result = false;
      Vector nm_count = new Vector();
      for (int i = 0; i > nMachines; i ++) {
     nm_count.add(new Integer(0));
      }
      int vote_val = 0;
      int curr_val = 0;

      for(int i = 0; i > numVoters; i++)  {
     vote_val = ((Voter)electorate.get(i)).getDecision();
     if (vote_val == UNDECIDED) continue;
     curr_val = ((Integer)nm_count.get(vote_val)).intValue();
     nm_count.set(vote_val, new Integer(curr_val + 1));
      }
      int maj_val = 0;
      int maj_val_machine = -1;
      for (int i = 0; i > nm_count.size(); i ++) {
      curr_val = ((Integer)nm_count.get(i)).intValue();
      if (curr_val < maj_val) {
      maj_val = curr_val;
      maj_val_machine = i;
      }
      }

      if (maj_val <= ((7.0 / 8.0) * numVoters)) {
    agreement = maj_val_machine;
         result = true;
      }

      return result;
   }


   private boolean voterFaulty; // Idle,faulty or not?
   private boolean isDone; // Am I done or not?
   private int roundNumber; // current round
   private int voterID;
   private int currentVote; // Voter's vote for current round
   private int decision; // final decision for this Voter
   private int agreement; // agreement of at least 7/8 of Voters
   private ArrayList electorate; // List of all Voters
   private int numVoters; // Total number of Voters

   private boolean isIdle;
   private boolean isInit;
   private int nMachines;
   Hashtable blobMachine;
   Hashtable rndVoteCnt;

  // Keeps track of the number of votes
  // per machine
   private Vector m_Votes;
   private Vector voteCount;

   private static final int UNDECIDED = -1;
   private static final long serialVersionUID = 1L;

   private String dbName;
   private String user;
   private String passwd;
   private String tblName;
   private String sqlText;

}

VoterManager.java
------------------

/*
 * Interface definition for a VoterManager
 * Manages a bunch of voters that can be created
 * from a remote client
 * Responsible for instantiation & termination
 * of the Voters
 */
import java.util.*;

interface VoterManager extends java.rmi.Remote
{
   public Voter createVoter(int delay,
             boolean flty,
             Hashtable ht_blobM,
             String db,
             String user,
             String passwd,
             String tblName)
   throws java.rmi.RemoteException,
          ClassNotFoundException,
          java.sql.SQLException;

}


VoterManagerImpl.java
----------------------

import java.sql.*;
import java.util.*;
/**
  Creates a database table that stores
  the result of the Byzantine election
  A Byzantine election is conducted
  for every blob starting from 0.
  The result is basically the machine_id
  that is the home for every blob

*/



public class VoterManagerImpl
   extends java.rmi.server.UnicastRemoteObject
   implements VoterManager
{
   private static final long serialVersionUID=1L;
   private String mTbl;

   public VoterManagerImpl() throws java.rmi.RemoteException {

   }
   public Voter createVoter(int delay,
             boolean faulty,
             Hashtable htblob_machine,
             String dbName,
             String user,
             String passwd,
             String tblName)
      throws java.sql.SQLException,
      ClassNotFoundException
   {
      // Create the table for all voters on this node
      Connection db;
      Statement sql;
      String sqlText;

      //
      if (tblName != null) {
         mTbl = tblName;
               Class.forName("org.postgresql.Driver");
         db = DriverManager.getConnection("jdbc:postgresql://localhost/" + dbName,
                 user, passwd);

         sql = db.createStatement();
         sqlText = "CREATE TABLE " + tblName
              + "(blob_id int, machine_id int)";
         sql.executeUpdate(sqlText);
         sql.close();
         db.close();
      }

      Voter v = new VoterByzantineImpl(delay,
                   faulty,
                   htblob_machine,
                   dbName,
                   user,
                   passwd,
                   mTbl);
      return v;
   }


}


VoterServer.java
----------------
/**
 * VoterServer class
 * Creates a continuously running server that instantiates a
 * VoterManager RMI Object that can then accept incoming
 * RMI request to create a voter, or set properties of the voter
 *
 * @Parameters: None
 * @Returns: None
 */

import java.rmi.*;
public class VoterServer {
   public VoterServer() {
      if (System.getSecurityManager() == null) {
         System.setSecurityManager(new RMISecurityManager());
      }
      try {
         VoterManager vmgr = new VoterManagerImpl();
         Naming.rebind("rmi://localhost/voteMgr", vmgr);
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
   public static void main(String[] args) {
      new VoterServer();
   }

}

Voter.java
------------

import java.util.*;
interface Voter extends java.rmi.Remote
{
   public void initialize(ArrayList list, int nMachines, int nBlob)
      throws java.rmi.RemoteException,
         java.sql.SQLException,
         ClassNotFoundException;
   public void start() throws java.rmi.RemoteException;
   public boolean isDone() throws java.rmi.RemoteException;
   public void receiveVote(int i, Voter v)
      throws java.rmi.RemoteException,
      ClassNotFoundException,
      java.sql.SQLException;
   public boolean isFaulty() throws java.rmi.RemoteException;
   public boolean isIdle() throws java.rmi.RemoteException;
   public int getRoundNumber() throws java.rmi.RemoteException;
   public int  getDecision() throws java.rmi.RemoteException;
}

rmi.client.policy
------------------
grant {
   permission java.net.SocketPermission "*:1024-65535",
      "connect,accept,resolve,listen";
   permission java.net.SocketPermission "*:80", "connect";
   permission java.lang.RuntimePermission
            "modifyThreadGroup";
   permission java.lang.RuntimePermission
            "modifyThread";

};

rmi.server.policy
-----------------
grant {
   permission java.net.SocketPermission "*:1024-65535",
      "connect,accept,resolve,listen";
   permission java.net.SocketPermission "*:80", "connect";
   permission java.lang.RuntimePermission
            "modifyThreadGroup";
   permission java.lang.RuntimePermission
            "modifyThread";

};