Skip to content

Changing the coordinator of a cluster

belaban edited this page Jan 1, 2015 · 3 revisions

Here’s code to change the coordinator of a cluster programmatically. The coordinator moves to the end of the view. Replace the ref to "/home/bela/fast.xml" with your own configuration. Note that delta views cannot be used, so I’m turning this off in GMS before connecting the channel.

The code works by taking the current view at the coordinator ({A,B,C}), removing the coordinator (A) and adding it at the end, so we now have {B,C,A}. The current coordinator A then mcasts this new view to all members and the new coordinator is now B.

/**
 * @author Bela Ban
 * @since x.y
 */
public class bla2 extends ReceiverAdapter {
    protected JChannel ch;
    protected int count=0;

    protected void start(String name) throws Exception {
        ch=new JChannel("/home/bela/fast.xml").name(name);
        ch.setReceiver(this);
        GMS gms=(GMS)ch.getProtocolStack().findProtocol(GMS.class);
        gms.setValue("use_delta_views", false);
        ch.connect("demo");
        loop();
        Util.close(ch);
    }

    protected void loop() {
        boolean looping=true;
        while(looping) {
            int key=Util.keyPress("[1] mcast message [2] change coord [3] print view [x] exit");
            switch(key) {
                case '1':
                    try {
                        ch.send(null, "msg-" + ++count);
                    }
                    catch(Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case '2':
                    changeView();
                    break;
                case '3':
                    System.out.println("view: " + ch.getView());
                    break;
                case 'x':
                    looping=false;
                    break;
            }
        }
    }

    protected void changeView() {
        View view=ch.getView();
        Address local_addr=ch.getAddress();
        Address coord=view.getMembersRaw()[0];
        if(!local_addr.equals(coord)) {
            System.err.println("View can only be changed on coordinator");
            return;
        }
        if(view.size() == 1) {
            System.err.println("Coordinator cannot change as view only has a single member");
            return;
        }
        List<Address> mbrs=new ArrayList<>(view.getMembers());
        long new_id=view.getViewId().getId() + 1;

        Address tmp_coord=mbrs.remove(0);
        mbrs.add(tmp_coord);
        View new_view=new View(mbrs.get(0), new_id, mbrs);
        GMS gms=(GMS)ch.getProtocolStack().findProtocol(GMS.class);
        gms.castViewChange(new_view, null, mbrs);
    }

    public void viewAccepted(View view) {
        System.out.println("-- view = " + view);
    }

    public void receive(Message msg) {
        System.out.println("-- msg from " + msg.src() + ": " + msg.getObject());
    }

    public static void main(String[] args) throws Exception {
        new bla2().start(args[0]);
    }
}