Package org.xtreemfs.babudb.config

Source Code of org.xtreemfs.babudb.config.ReplicationConfig

/*
* Copyright (c) 2009 - 2011, Jan Stender, Bjoern Kolbeck, Mikael Hoegqvist,
*                     Felix Hupfeld, Felix Langner, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package org.xtreemfs.babudb.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

import org.xtreemfs.babudb.log.DiskLogger.SyncMode;
import org.xtreemfs.babudb.replication.control.FleaseHolder;
import org.xtreemfs.babudb.replication.policy.Policy;
import org.xtreemfs.foundation.SSLOptions;
import org.xtreemfs.foundation.flease.FleaseConfig;

/**
* Reading configurations from the replication-config-file.
*
* @since 05/02/2009
* @author flangner
*
*/

public class ReplicationConfig extends PluginConfig {
   
    private final static String POLICY_PACKAGE = "org.xtreemfs.babudb.replication.policy.";
   
    protected final BabuDBConfig     babuDBConfig;
   
    protected InetSocketAddress      address;
   
    protected SSLOptions             sslOptions;
   
    /**
     * List of participants without the local instance.
     */
    protected Set<InetSocketAddress> participants;
   
    protected int                    localTimeRenew;
   
    protected int                    timeSyncInterval;
   
    protected final FleaseConfig     fleaseConfig;
   
    protected String                 policyName;
    protected final Policy           replicationPolicy;
   
    /**
     * longest duration a message can live on the wire, before it becomes void (one-way)
     */
    public static final int         MESSAGE_TIMEOUT        = 5 * 1000;
   
    /**
     * longest duration a connection can be established without getting closed
     */
    public static final int          LEASE_TIMEOUT          = 60 * 1000;
       
    /**
     * longest duration before an RPC-Call is timed out for the client (RTT)
     */
    public static final int          REQUEST_TIMEOUT        = 2 * MESSAGE_TIMEOUT;
   
    /**
     * longest duration before an idle connection is closed
     */
    public static final int          CONNECTION_TIMEOUT     = 5 * 60 * 1000;
   
    /**
     * the maximal delay to wait for an valid lease to become available
     */
    public static final int         DELAY_TO_WAIT_FOR_LEASE_MS = REQUEST_TIMEOUT;
   
    // for master usage only
   
    protected int                    syncN;
   
    /**
     * Chunk size, for initial load of file chunks
     */
    protected int                    chunkSize;
   
    private final static int         DEFAULT_MAX_CHUNK_SIZE = 5 * 1024 * 1024;
   
    // for slave usage only
   
    protected String                 backupDir;
       
    /**
     * maximal retries per failure
     */
    public static final int          MAX_RETRIES            = 3;
   
    public ReplicationConfig(Properties prop, BabuDBConfig babuConf)
            throws IOException {
        super(prop);
        this.babuDBConfig = babuConf;
        read();
       
        this.fleaseConfig = new FleaseConfig(LEASE_TIMEOUT, this.localTimeRenew,
                MESSAGE_TIMEOUT, this.address,
                FleaseHolder.getIdentity(this.address), MAX_RETRIES);
       
        // get the replication policy
        try {
            this.replicationPolicy = (Policy) Policy.class.getClassLoader().
                        loadClass(POLICY_PACKAGE + policyName).newInstance();
           
        } catch (Exception e) {
            throw new IOException("ReplicationPolicy could not be " +
                "instantiated, because: " + e.getMessage());
        }
    }
   
    public ReplicationConfig(String filename, BabuDBConfig babuConf)
            throws IOException {
        super(filename);
        this.babuDBConfig = babuConf;
        read();
       
        this.fleaseConfig = new FleaseConfig(LEASE_TIMEOUT, this.localTimeRenew,
                MESSAGE_TIMEOUT, this.address,
                FleaseHolder.getIdentity(this.address), MAX_RETRIES);
       
        // get the replication policy
        try {
            this.replicationPolicy = (Policy) Policy.class.getClassLoader().
                        loadClass(POLICY_PACKAGE + policyName).newInstance();
           
        } catch (Exception e) {
            throw new IOException("ReplicationPolicy could not be " +
                        "instantiated, because: " + e.getMessage());
        }
    }
   
    public ReplicationConfig(Set<InetSocketAddress> participants,
            int localTimeRenew, SSLOptions sslOptions, int syncN,
            String tempDir, BabuDBConfig babuConf) throws IOException {
       
        this.babuDBConfig = babuConf;
        this.participants = new HashSet<InetSocketAddress>();
        this.localTimeRenew = localTimeRenew;
        Socket s;
        for (InetSocketAddress participant : participants) {
            s = new Socket();
            try {
                s.bind(participant);
                if (address == null) {
                    address = participant;
                } else if (!address.equals(participant)) {
                    participants.add(participant);
                }
            } catch (Exception e) {
                participants.add(participant);
            } finally {
                try {
                    s.close();
                } catch (IOException e) { /* ignored */
                }
            }
        }
       
        this.sslOptions = sslOptions;
        this.syncN = syncN;
        this.chunkSize = DEFAULT_MAX_CHUNK_SIZE;
        this.backupDir = tempDir;
               
        this.fleaseConfig = new FleaseConfig(LEASE_TIMEOUT, this.localTimeRenew,
                MESSAGE_TIMEOUT, address,
                FleaseHolder.getIdentity(address), MAX_RETRIES);
       
        checkArgs(babuDBConfig, address, sslOptions, participants,
                localTimeRenew, timeSyncInterval, syncN, chunkSize,
                this.backupDir, policyName);
       
        // get the replication policy
        try {
            replicationPolicy = (Policy) Policy.class.getClassLoader().
                        loadClass(POLICY_PACKAGE + policyName).newInstance();
           
        } catch (Exception e) {
            throw new IOException("ReplicationPolicy could not be " +
                        "instantiated, because: " + e.getMessage());
        }
    }
   
    private void read() throws IOException {
       
        String tempDir = this.readRequiredString("babudb.repl.backupDir");
        if (tempDir.endsWith("/") || tempDir.endsWith("\\")) {
            backupDir = tempDir;
        } else if (tempDir.contains("/")) {
            backupDir = tempDir + "/";
        } else if (tempDir.contains("\\")) {
            backupDir = tempDir + "\\";
        } else {
            backupDir = tempDir + File.separator;
        }
       
        this.localTimeRenew = this.readOptionalInt("babudb.localTimeRenew",
                                                   3000);
        this.timeSyncInterval = this.readOptionalInt("babudb.timeSync", 20000);
       
        if (this.readOptionalBoolean("babudb.ssl.enabled", false)) {
            this.sslOptions = new SSLOptions(new FileInputStream(this
                    .readRequiredString("babudb.ssl.service_creds")), this
                    .readRequiredString("babudb.ssl.service_creds.pw"), this
                    .readRequiredString("babudb.ssl.service_creds.container"),
                            new FileInputStream(this
                    .readRequiredString("babudb.ssl.trusted_certs")), this
                    .readRequiredString("babudb.ssl.trusted_certs.pw"), this
                    .readRequiredString("babudb.ssl.trusted_certs.container"),
                            this
                    .readRequiredBoolean(
                            "babudb.ssl.authenticationWithoutEncryption"));
        }
       
        this.chunkSize = this.readOptionalInt("babudb.repl.chunkSize",
                DEFAULT_MAX_CHUNK_SIZE);
       
        this.syncN = this.readOptionalInt("babudb.repl.sync.n", 0);
       
        // read the participants
        this.participants = new HashSet<InetSocketAddress>();
       
        this.address = this.readOptionalInetSocketAddr("babudb.repl.localhost",
                "babudb.repl.localport", null);
       
        int number = 0;
        Socket s;
        InetSocketAddress addrs;
        while ((addrs = readOptionalInetSocketAddr("babudb.repl.participant." + number,
                        "babudb.repl.participant." + number + ".port", null)) != null) {
           
            if (address == null) {
                s = new Socket();
                try {
                    s.bind(addrs);
                    address = addrs;
                } catch (Throwable t) {
                    // even if a participant's address is not reachable, or cannot
                    // be resolved, it never will be ignored completely, because
                    // it may become available later
                    participants.add(addrs);
                } finally {
                    try {
                        s.close();
                    } catch (IOException e) { /* ignored */ }
                }
            } else if (!address.equals(addrs)) {
                participants.add(addrs);
            }
            number++;
        }
       
        policyName = readOptionalString("babudb.repl.policy", "MasterOnly");
       
        checkArgs(babuDBConfig, address, sslOptions, participants, localTimeRenew, timeSyncInterval,
                  syncN, chunkSize, backupDir, policyName);
    }
   
    public InetSocketAddress getInetSocketAddress() {
        return address;
    }
   
    public int getPort() {
        return address.getPort();
    }
   
    public InetAddress getAddress() {
        return address.getAddress();
    }
   
    public SSLOptions getSSLOptions() {
        return sslOptions;
    }
   
    /**
     * @return a set of addresses for participants of the replication setup without the address
     *         of the local instance.
     */
    public Set<InetSocketAddress> getParticipants() {
        return participants;
    }
   
    public int getLocalTimeRenew() {
        return localTimeRenew;
    }
   
    public int getTimeSyncInterval() {
        return timeSyncInterval;
    }
   
    public int getSyncN() {
        return syncN;
    }
   
    public int getChunkSize() {
        return chunkSize;
    }
   
    public String getTempDir() {
        return backupDir;
    }
   
    public FleaseConfig getFleaseConfig() {
        return fleaseConfig;
    }
   
    public BabuDBConfig getBabuDBConfig() {
        return babuDBConfig;
    }
   
    public Policy getReplicationPolicy() {
        return replicationPolicy;
    }
   
    @Override
    public String toString() {
        StringBuffer buf = new StringBuffer();
        buf.append("############# Replication CONFIGURATION #############\n");
        buf.append("#             local address: " + address.toString() + "\n");
       
        if (this.sslOptions != null) {
            buf.append("#         ssl options: " + sslOptions.toString()+ "\n");
        }
       
        int i = 0;
        for (InetSocketAddress participant : this.participants) {
            buf.append("#                participant " + (i++) + ": " +
                    participant.toString() + "\n");
        }
        buf.append("#        sync N: " + syncN + "\n");
        buf.append("#        policy: " + policyName + "\n");
        buf.append("#        local time renew: " + localTimeRenew + "\n");
        buf.append("#        time sync interval: " + timeSyncInterval + "\n");
        buf.append("#        temporary directory: " + backupDir + "\n");
        buf.append("#        chunk size: " + chunkSize + "\n");
        return buf.toString();
    }
   
    private static void checkArgs(BabuDBConfig conf, InetSocketAddress address,
            SSLOptions options, Set<InetSocketAddress> participants,
            int localTimeRenew, int timeSyncInterval, int syncN, int chunkSize,
            String tempDir, String policyName) {
       
        File base = new File(conf.getBaseDir());
        File log = new File(conf.getDbLogDir());
       
        if (conf.getSyncMode() == SyncMode.ASYNC) {
            throw new IllegalArgumentException("Replication will not work properly if BabuDB " +
                "instances run in ASYNC mode. Please change the SyncMode of your BabuDB " +
                "setup.");
        }
       
        if (log.equals(base)) {
            throw new IllegalArgumentException("It is not permitted by the replication plugin to" +
                " stored log and base files within the same directory. Please move either" +
                "log (" + conf.getDbLogDir() + ") or base (" + conf.getBaseDir() + ").");
        }
       
        File tmp = new File(tempDir);
        while (tmp != null) {
            if (tmp.equals(base) || tmp.equals(log)) {
                throw new IllegalArgumentException("The backup-directory (" + tempDir
                        + ") may not be a sub-directory of the dbLog-directory ("
                        + conf.getDbLogDir() + ") and the base-directory (" + conf.getBaseDir()
                        + ")!");
            }
           
            tmp = tmp.getParentFile();
        }
       
        if (address == null)
            throw new IllegalArgumentException(
                    "None of the given participants described the localhost!");
       
        if (syncN < 0 || syncN > (participants.size() + 1))
            throw new IllegalArgumentException(
                    "Wrong Sync-N! It has to be at least 0 and #of " +
                    "participants ("+(participants.size() + 1)+") at the maximum!");
       
        if (syncN != 0 && syncN <= participants.size() / 2)
            throw new IllegalArgumentException(
                    "The requested N-sync-mode (N=" + syncN + ") may cause " +
                    "inconsistent behavior, because there are '" +
                    participants.size() + "' participants. The sync-N " +
                    "has to be at least '" + (participants.size() / 2) + "'!");
       
        if (policyName != null && policyName != "") {
            try {
                Policy.class.getClassLoader().loadClass(
                        POLICY_PACKAGE + policyName);
            } catch (Exception e) {
                throw new IllegalArgumentException("Policy with name '" +
                        policyName + "' could not be found at classpath.");
            }
        } else {
            throw new IllegalArgumentException("It is not possible to use " +
                "replication without replication policy. The policy " +
                "has at least to be set to default (MasterOnly)!");
        }
    }
}
TOP

Related Classes of org.xtreemfs.babudb.config.ReplicationConfig

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.