view rep/Forwarder.java @ 376:c4ffdac26132

*** empty log message ***
author kono
date Wed, 22 Oct 2008 03:19:57 +0900
parents ab4405cd3351
children c78569ab5fce
line wrap: on
line source

package rep;

import java.io.IOException;
import rep.channel.REPLogger;
import rep.channel.REPSelectionKey;
import rep.channel.REPSocketChannel;
import rep.handler.PacketSet;
import rep.handler.REPHandler;

public class Forwarder extends EditorPlus implements REPHandler {
	int seq = 0;
	Forwarder next;
	// REPCommands we sent to the next editor
	final int limit=100;
	REPLogger ns = REPLogger.singleton();
	SessionManager manager;
	public REP mode = null;
	
	public Forwarder(SessionManager manager) {
		this.manager = manager;
	}

	public int seq() {
		return seq++;
	}
	
	public void send(REPCommand command) {
		assert(command!=null);
		assert(channel!=null);
		REPCommand c = new REPCommand(command);
		manager.addWriteQueue(new PacketSet(channel,null,  c));
	}
	
	public REPSocketChannel<REPCommand> getChannel() {
		return channel;
	}
	
	public void setChannel(REPSocketChannel<REPCommand> channel) {
		this.channel = channel;
	}

	public void setQuit2(REPCommand cmd) {
		send(cmd);
	}

	public void setNext(Forwarder next) {
		this.next = next;
	}
	
	public Forwarder getNextForwarder() {
		return next;
	}

	public boolean manage(REPCommand command) {
		next.send(command);
		return true;
	}

	public String toString(){
		return ("Forwarder:" + channel);
	}
	
	public String getLocalHostName() {
		return channel.getLocalHostName();
	}

	public void cancel(REPSocketChannel<REPCommand> socketChannel) {
		manager.remove(socketChannel);
	}

	public void handle(REPSelectionKey<REPCommand> key) throws IOException {
		/*
		 * SessionManagerから来たコマンドは、Editor関係のコマンドは、
		 * sessionとeidを判定して、そのeditorにforwardしてやれば良い。
		 * 残りは、manager.manage() で処理する。
		 */
		REPSocketChannel<REPCommand> channel = key.channel1();
		REPCommand command = channel.read();
		SessionManager.logger.writeLog("REPHandlerImpl.handle() : command = " + command);
		if (manager.sessionManage(this, command)) return;
		
		distpatchToEditor(channel, command);
	}

	private void distpatchToEditor(REPSocketChannel<REPCommand> channel,
			REPCommand command) throws IOException {
		Session s = manager.getSession(command.sid);
		if (s==null) throw new IOException();
		Forwarder editor = s.getForwarder(channel);
		if (editor==null) throw new IOException();
		if (!editor.isDirect()) {
			editor.send(command); 
			return;
		}
		/*
		 * local editor case. Handle special case first, usually these cases
		 * are handled in the next Editor in a session manager, but 
		 * it is forwarded here.
		 */
		if (command.cmd==REP.SMCMD_QUIT_2) {
			// we have to wait next editor's finishing before sending this.
			// this is odd, but the editor itself does not know it's merging
			// state. Only this session manager knows it.
			editor.setQuit2(command);
		} else if (command.eid==editor.eid) {
			// if we handle in editor.manage(), this editor cannot distinguish this
			// and user input command from the editor.
			((Editor)editor).checkReturnedCommand(command);
		} else {
			editor.manage(command);
		}
	}

	public void setMode(REP cmd) {
		mode = cmd;
	}

	public boolean isEditor() {
		return mode==REP.SMCMD_JOIN||mode==REP.SMCMD_PUT;
	}
	
	public boolean isForwarder() {
		return mode==REP.SMCMD_SM_JOIN||mode==REP.SMCMD_SM_JOIN_ACK;
	}

	public boolean isDirect() {
		return isEditor();
	}


}