perLucene.ZooTiger.java Source code

Java tutorial

Introduction

Here is the source code for perLucene.ZooTiger.java

Source

package perLucene;

/*
 Copyright contributors as noted in the AUTHORS file.
    
 This file is part of PLATANOS.
    
 PLATANOS is free software; you can redistribute it and/or modify it under
 the terms of the GNU Affero General Public License as published by
 the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version.
    
 PLATANOS is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.
    
 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Date;

import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.data.Stat;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.CreateMode;

import java.io.File;

import java.util.List;

//up        1 search
//          2 index + search 

//all replicas should hava 2 as value in case they become leader 
//only the leader can have 1 as value , only the leaders value is checked by the gdd, when it syncs a replica's state

//the existence of up is checked by the leader as well as the gd for all replicas

//the broker object should only be used by the asynchronous thread of the zookeeper

class ZooTiger extends ZooAbstract {

    protected int interval;
    protected int replica;

    protected int leader;
    protected Stat leaderStat = new Stat();

    protected boolean isLeader;
    protected int maximum_size; // only the leader knows these
    protected int split_size;

    protected boolean isSynced = false;

    protected boolean leaderExists;
    protected long lastTimeWorking;

    protected Broker broker;

    // requires a string of 2 size
    ZooTiger() {
        String[] line = Config.readLocalConfig();

        super.initZookeeper(line[0], Integer.parseInt(line[1]), new Watcher() {
            @Override
            public void process(WatchedEvent e) {
                if (!(e.getState().equals(Watcher.Event.KeeperState.SyncConnected))) {
                    System.out.println("Disconnected.. exiting");
                    System.exit(0);
                }
            }
        });

        interval = Integer.parseInt(line[2]);
        replica = Integer.parseInt(line[3]);

        broker = new Broker();

    }

    public void leader(int leader) {
        this.leader = leader;

    }

    public int leader() {
        return leader;

    }

    public int interval() {
        return interval;

    }

    public boolean isLeader() {

        return isLeader;

    }

    public boolean isSynced() {

        return isSynced;

    }

    public void leaderExists(boolean leaderExists) {

        this.leaderExists = leaderExists;
    }

    public void lastTimeWorking(long lastTimeWorking) {

        this.lastTimeWorking = lastTimeWorking;
    }

    // returns true if the leader is alive
    public boolean getLeader() {
        try {
            String path = "/tiger/Servers/" + Integer.toString(interval);

            leader = ByteBuffer.wrap(zoo.getData(path + "/leader", new WatcherLeader(this), leaderStat)).getInt();
            // check the leader is alive
            if (zoo.exists(path + "/replicas/" + Integer.toString(leader) + "/up",
                    new WatcherLeaderAlive(this)) != null) {

                if (leader == replica) {
                    isLeader = true;
                } else {
                    isLeader = false;
                }

                leaderExists = true;
                return true;
            } else {
                this.stoppedWorking();
                return false;
            }

        } catch (KeeperException e) {
            System.out.println("zookeeper client exited with error code " + e.code().toString());
            System.out.println(e.toString());
            System.exit(-1);
        } catch (Exception e) {
            System.out.println("zookeeper client interrupted");
            System.out.println(e.toString());
            System.exit(-1);
        }

        // default value, will never happen
        return false;

    }

    // only done at the beginning, initial value of up is irrelevant
    // goOnline doesnt try to become the Leader since it is assumed that
    // the new replica is unsynced

    // One must manually ask the replica to become leader and it should only be
    // done if all other replicas are down

    public void goOnline(boolean becomeLeader) {

        String path = "/tiger/Servers/" + Integer.toString(interval) + "/replicas/" + Integer.toString(replica)
                + "/up";

        try {
            zoo.create(path, ByteBuffer.allocate(4).putInt(2).array(), acl, CreateMode.EPHEMERAL);

            // any new server is considered unsynched, so unless manually
            // ordered, it never becomes leader

            if (getLeader()) {
                assert (!isLeader);
                sync();
                connect();
            } else {
                if (becomeLeader) {

                    becomeLeader();

                }

            }

        } catch (KeeperException e) {
            if (e.code().equals(KeeperException.Code.NODEEXISTS)) {

                System.out.println("This replica is already online, possible local configuration error");

            } else {

                System.out.println("zookeeper client exited with error code " + e.code().toString());
                System.out.println(e.toString());

            }
            System.exit(-1);
        } catch (Exception e) {
            System.out.println("zookeeper client interrupted");
            System.out.println(e.toString());
            System.exit(-1);
        }

    }

    // if all replicas are offline, then wait for the last leader to go online
    // this way we dont lose documents

    // all till bind should only be used by the asynchronous thread of zookeeper

    protected void sync() {

    }

    public void connect() {
        broker.connect();

    }

    public void bind() {
        broker.bind();

    }

    public void setMode(boolean index) {
        int value = 1;
        if (index) {
            value = 2;
        }

        try {

            String path = "/tiger/Servers/" + Integer.toString(interval);

            zoo.setData(path + "/replicas" + Integer.toString(replica) + "/up",
                    ByteBuffer.allocate(4).putInt(value).array(), -1);

        } catch (KeeperException e) {
            System.out.println("zookeeper client exited with error code " + e.code().toString());
            System.out.println(e.toString());
            System.exit(-1);
        } catch (Exception e) {
            System.out.println("zookeeper client interrupted");
            System.out.println(e.toString());
            System.exit(-1);
        }

    }

    public void becomeLeader() {

        isLeader = true;

        try {
            String path = "/tiger/Servers/" + Integer.toString(interval);

            zoo.setData(path + "/leader", ByteBuffer.allocate(4).putInt(replica).array(), leaderStat.getVersion());

        } catch (KeeperException e) {
            if (e.code().equals(KeeperException.Code.BADVERSION)) {

                isLeader = false;
                // someone else became a leader
            } else {
                // TODO maybe clarify the possible errors
                System.out.println("zookeeper client exited with error code " + e.code().toString());
                System.out.println(e.toString());
                System.exit(-1);
            }
        } catch (Exception e) {
            System.out.println("zookeeper client interrupted");
            System.out.println(e.toString());
            System.exit(-1);
        }

        if (isLeader) {

            String path = "/tiger/Servers/" + Integer.toString(interval);

            try {

                maximum_size = ByteBuffer.wrap(zoo.getData(path + "/maximum_size", new WatcherNotify(this), null))
                        .getInt();

                split_size = ByteBuffer.wrap(zoo.getData(path + "/split_size", new WatcherNotify(this), null))
                        .getInt();

            } catch (KeeperException e) {
                System.out.println("zookeeper client exited with error code " + e.code().toString());
                System.out.println(e.toString());
                System.exit(-1);
            } catch (Exception e) {
                System.out.println("zookeeper client interrupted");
                System.out.println(e.toString());
                System.exit(-1);
            }

            // get which other replicas are online

            findReplicas();

            // inform the IndexThread to bind
            bind();

        }

    }

    // findReplicas should only be executed one at a time

    public void findReplicas() {

        String path = "/tiger/Servers/" + Integer.toString(interval);

        try {
            List<String> children = zoo.getChildren(path + "/replicas", new WatcherReplicas(this));

            List<Integer> aliveReplicas = new ArrayList<Integer>();

            for (int i = 0; i < children.size(); i++) {

                if (zoo.exists(path + "/replicas/" + children.get(i) + "/up",
                        new WatcherReplicaAlive(this)) != null) {
                    aliveReplicas.add(Integer.parseInt(children.get(i)));

                }

            }

            // update the indexerThread
            broker.updateReplicas(aliveReplicas);

        } catch (KeeperException e) {
            System.out.println("zookeeper client exited with error code " + e.code().toString());
            System.out.println(e.toString());
            System.exit(-1);
        } catch (Exception e) {
            System.out.println("zookeeper client interrupted");
            System.out.println(e.toString());
            System.exit(-1);
        }

    }

    public void stoppedWorking() {

        if (leaderExists) {
            this.leaderExists(false);
            this.lastTimeWorking((new Date()).getTime());
        }

    }

    public String getConfig() {

        try {
            Stat stat = new Stat();

            return (new String(zoo.getData(
                    "/tiger/Servers/" + Integer.toString(interval) + "/replicas/" + Integer.toString(replica), null,
                    stat), "UTF-8"));

        } catch (KeeperException e) {

            System.out.println("This replica doesnt exists, or its configuration in zookeeper is corrupt");
            System.exit(0);

        } catch (Exception e) {
            System.out.println("zookeeper client interrupted");
            System.out.println(e.toString());
            System.exit(-1);
        }

        return null;

    }

    // used only when this replica is the leader

    // we assume that each replica has the same index
    // we assume that the index is in its own filesystem

    // 1 need to split notification
    // 2 indexing stopped notification

    public void notifyZoo() {

        assert (isLeader);

        try {
            File file = new File("/mnt/perLucene");

            int free = (int) (file.getFreeSpace() / 1024 ^ 3);
            int total = (int) (file.getTotalSpace() / 1024 ^ 3);
            int used = total - free;

            if (used > split_size) {

                String path = "/tiger/Servers/" + Integer.toString(interval);

                if (used > maximum_size) {
                    // stop indexing until the problem is fixed

                    zoo.setData(path + "/" + Integer.toString(replica) + "/up",
                            ByteBuffer.allocate(4).putInt(1).array(), -1);

                    zoo.setData(path + "/notifications", ByteBuffer.allocate(4).putInt(2).array(), -1);

                } else {

                    zoo.setData(path + "/notifications", ByteBuffer.allocate(4).putInt(1).array(), -1);

                }

            }

        } catch (KeeperException e) {

            System.out.println("zookeeper client exited with error code " + e.code().toString());
            System.out.println(e.toString());
            System.exit(-1);

        } catch (Exception e) {
            System.out.println("zookeeper client interrupted");
            System.out.println(e.toString());
            System.exit(-1);
        }

    }

}