/*
  * Implementation of 2Phase Commit first make request to all other replicas.
  * If "ACCEPT" is received from all the replicas then proceed to second phase, which is to commit changes.
  * Used by the PUT and DELETE methods as they are the only ones that make write operations.
  */
 public boolean TwoPCommit(String command, String key, String value) {
   int accept = 0;
   String result = "";
   String host = "";
   int portNumber = 0;
   // ASK proxies at other servers in cluster
   for (int a = 0; a < numReplicas; a++) {
     result = "";
     try {
       host = InetAddress.getByName(hostPorts[a][0]).getHostAddress();
       portNumber = Integer.parseInt(hostPorts[a][1]);
       RMIServerInterface remoteImpl =
           (RMIServerInterface)
               Naming.lookup("rmi://" + host.trim() + ":" + portNumber + "/Calls");
       long startTime = System.currentTimeMillis(); // Timeout after 10s
       while (result.isEmpty()) {
         if ((System.currentTimeMillis() - startTime) > 10000) {
           log.error("Unable to ASK " + host + ":" + portNumber + "Timed-out!");
           break;
         }
         result = remoteImpl.ASK(command, key, value);
       }
     } catch (Exception e) {
       // TODO Auto-generated catch block
       log.error("Connection to " + host + ":" + portNumber + " met error with " + e.getMessage());
     }
     log.info(result + " for " + host + ":" + portNumber);
     if (result.trim().toUpperCase().equals(ACCEPT)) ++accept;
   }
   /*
    * If all the replicas have accepted the requested command via the ASK method, then make commit.
    */
   if (accept == numReplicas) {
     for (int a = 0; a < numReplicas; a++) {
       result = "";
       try {
         host = InetAddress.getByName(hostPorts[a][0]).getHostAddress();
         portNumber = Integer.parseInt(hostPorts[a][1]);
         RMIServerInterface remoteImpl =
             (RMIServerInterface)
                 Naming.lookup("rmi://" + host.trim() + ":" + portNumber + "/Calls");
         long startTime = System.currentTimeMillis(); // Timeout after 10s
         while (!result.equals(ACK)) {
           if ((System.currentTimeMillis() - startTime) > 10000) {
             log.error("Unable to commit update to " + host + ":" + portNumber + "Timed-out!");
             break;
           }
           if (command.toUpperCase().equals("PUT"))
             result = (remoteImpl.PUT(true, host + ":" + port, key, value));
           else if (command.toUpperCase().equals("DELETE"))
             result = (remoteImpl.DELETE(true, host + ":" + port, key));
         }
       } catch (Exception e) {
         log.error(
             "Connection to " + host + ":" + portNumber + " met error with " + e.getMessage());
       }
     }
     return true;
   }
   return false;
 }
Example #2
0
  public static void main(String[] args) throws IOException {

    /** max number of elements to import */
    final long max = (int) 1e6;

    /** Open database in temporary directory */
    File dbFile = File.createTempFile("mapdb", "temp");
    DB db =
        DBMaker.newFileDB(dbFile)
            /** disabling Write Ahead Log makes import much faster */
            .transactionDisable()
            .make();

    long time = System.currentTimeMillis();

    /**
     * Source of data which randomly generates strings. In real world this would return data from
     * file.
     */
    Iterator<String> source =
        new Iterator<String>() {

          long counter = 0;

          @Override
          public boolean hasNext() {
            return counter < max;
          }

          @Override
          public String next() {
            counter++;
            return randomString(10);
          }

          @Override
          public void remove() {}
        };

    /**
     * BTreeMap Data Pump requires data source to be presorted in reverse order (highest to lowest).
     * There is method in Data Pump we can use to sort data. It uses temporarly files and can handle
     * fairly large data sets.
     */
    source =
        Pump.sort(
            source,
            true,
            100000,
            Collections.reverseOrder(BTreeMap.COMPARABLE_COMPARATOR), // reverse  order comparator
            db.getDefaultSerializer());

    /**
     * Disk space used by serialized keys should be minimised. Keys are sorted, so only difference
     * between consequential keys is stored. This method is called delta-packing and typically saves
     * 60% of disk space.
     */
    BTreeKeySerializer<String> keySerializer = BTreeKeySerializer.STRING;

    /** Translates Map Key into Map Value. */
    Fun.Function1<Integer, String> valueExtractor =
        new Fun.Function1<Integer, String>() {
          @Override
          public Integer run(String s) {
            return s.hashCode();
          }
        };

    /** Create BTreeMap and fill it with data */
    Map<String, Integer> map =
        db.createTreeMap("map")
            .pumpSource(source, valueExtractor)
            // .pumpPresort(100000) // for presorting data we could also use this method
            .keySerializer(keySerializer)
            .make();

    System.out.println(
        "Finished; total time: "
            + (System.currentTimeMillis() - time) / 1000
            + "s; there are "
            + map.size()
            + " items in map");
    db.close();
  }