view rep/SessionManager.java @ 38:de8638eb0edd

*** empty log message ***
author pin
date Sat, 10 Nov 2007 18:51:09 +0900
parents 593f915dd6ff
children c873ee0318f8
line wrap: on
line source

package rep;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.StringTokenizer;

//+-------+--------+--------+-------+--------+---------+------+
//| cmd   | session| editor | seqid | lineno | textsiz | text |
//|       | id     | id     |       |        |         |      |
//+-------+--------+--------+-------+--------+---------+------+
//o-------header section (network order)-------------o
/*int cmd;	// command
int sid;	// session ID
int eid;	// editor ID
int seqno;	// Sequence number
int lineno;	// line number
int textsize;   // textsize
byte[] text;*/

public class SessionManager implements ConnectionListener, REPActionListener{
	
	
	private SessionList sessionlist;
	//SocketChannel sessionchannel;
	private SessionManagerGUI sessionmanagerGUI;
	private Selector selector;
	private SessionManagerList smList;
	private String myHost;
	private boolean isMaster = true;
	private EditorList  editorList;
	//private SocketChannel sessionchannel;
	//private boolean co;
	public SessionManager(int port) {
		sessionmanagerGUI = new SessionManagerGUI();
	}
	
	public void openSelector() throws IOException{
		selector = Selector.open();
	}
	
	public void sessionManagerNet(int port) throws InterruptedException, IOException {
		/**
	 * @param args
	 * @throws IOException 
	 * @throws InterruptedException 
	 * @throws IOException 
	 * @throws InterruptedException 
	 */
		System.out.println("sessionManagerNet()");
	
		ServerSocketChannel ssc = ServerSocketChannel.open();
		ssc.configureBlocking(false);	
		ssc.socket().bind(new InetSocketAddress(port));
		ssc.register(selector, SelectionKey.OP_ACCEPT);

		
		sessionlist = new SessionList();
		smList = new SessionManagerList();
		editorList = new EditorList();
		
		while(true){
			selector.select();
			for(SelectionKey key : selector.selectedKeys()){
				if(key.isAcceptable()){
					/*** serverChannelはenableになったSelectionKeyのchannel ***/
					ServerSocketChannel serverChannel = (ServerSocketChannel)key.channel();
					/*** EditorChannel を用いない記述 ***/
					SocketChannel channel = serverChannel.accept();	//keyからchannelを取って、accept 
					registerChannel (selector, channel, SelectionKey.OP_READ);
					channel = null;
					
					/*** EditorChannel を用いた記述 ****/
					//EditorChannel echannel = (EditorChannel) ssc.accept();
					//echannel.setIO();
					//registerChannel(selector, echannel, SelectionKey.OP_READ);
					//echannel = null;
					
					/*** SelectableEditorChannel ***/
					//SocketChannel channel = ssc.accept();
					//SelectableEditorChannel echannel2 = new SelectableEditorChannel(channel);
					//registerChannel(selector, echannel2, SelectionKey.OP_READ);
					//channel = null;
					//echannel2 = null;
					
				}else if(key.isReadable()){
					
					/*** EditorChannel を用いない記述 ***/
					SocketChannel channel = (SocketChannel)key.channel();
					REPPacketReceive repRec = new REPPacketReceive(channel); //getPacket(), putPacket() にする。
					repRec.setkey(key);
					REPCommand repCom = repRec.unpack();
					manager(channel, repCom);
					
					/*** EditorChannel を用いた記述 ****/
					//EditorChannel echannel = (EditorChannel) key.channel();
					//REPCommand command = echannel.getPacket();
					//manager(echannel, command);
					
				}else if(key.isConnectable()){
					System.out.println("Connectable");
				}
			}
		}
	}
	
	private synchronized void registerChannel(Selector selector, SelectableChannel channel, int ops) throws IOException {
		if(channel == null) {
			return;
		}
		//System.out.println("registerChannel()");
		channel.configureBlocking(false);
		selector.wakeup();
		channel.register(selector, ops);
	}

	private void manager(SocketChannel channel, REPCommand repCmd) {
		if(repCmd == null) return;
		switch(repCmd.cmd){
		
		case REP.SMCMD_JOIN:
			if(isMaster){
				int eid = editorList.addEditor(channel, repCmd);
				repCmd.setEID(eid);
				editorList.sendJoinAck(channel, repCmd);
				sessionmanagerGUI.setComboEditor(eid, channel);
			}else{
				editorList.addEditor(channel);
				smList.sendJoin(repCmd);
				//sessionmanagerGUI.setComboEditor(repCmd.eid, channel);
			}
			break;
			
		case REP.SMCMD_JOIN_ACK:
//				editorList.setEID(repCmd);
//				editorList.sendJoinAck(repCmd);
//				sessionmanagerGUI.setComboEditor(repCmd.eid, channel);
			break;
			
		case REP.SMCMD_PUT:
			if(repCmd.string.length() == 0){
				sessionlist.addEditor(channel, 0, 0);
			}else if(repCmd.string.length() > 0){
				int sid = sessionlist.addSession(channel, repCmd.string);
				sessionlist.addEditor(channel, sid, 0);
			}
			break;
			
//		case REP.SMCMD_PUT_ACK:
//			break;
			
		case REP.SMCMD_SELECT:
			sessionlist.addEditor(channel, repCmd.sid, repCmd);	//sessionlistへ追加
			repCmd.setCMD(repCmd.cmd + 1);
			REPPacketSend repSend3 = new REPPacketSend(channel);
			repSend3.send(repCmd);		//ACKを返す
			break;
			
		case REP.SMCMD_SELECT_ACK:
			break;
			
		case REP.SMCMD_SESSION:
			break;
			
		case REP.SMCMD_SM_JOIN:
			if(isMaster){
				smList.add(channel);
				repCmd.setCMD(REP.SMCMD_SM_JOIN_ACK);
				smList.sendSessionList(sessionlist, repCmd);
			}
			break;
			
		case REP.SMCMD_SM_JOIN_ACK:
			if(isMaster){
				smList.send(channel, repCmd);
			}
			
			break;
			
		case REP.SMCMD_UPDATE:
			int sessionID2 = sessionlist.addSession(channel, repCmd.string);	//Sessionを作成
			sessionlist.addEditor(channel, sessionID2, repCmd);
			sessionmanagerGUI.setComboSession(sessionID2, repCmd.string);	//ComboBoxにSessionを追加
			break;
			
		case REP.SMCMD_UPDATE_ACK:
			break;
			
		case REP.REPCMD_READ:
			//sessionlist.sendCmd(channel, repCmd);
			break;
			
		default:
			//sessionlist.sendCmd(channel, repCmd);
			sessionlist.sendToNextEditor(channel, repCmd);
			break;
		}
	}

//	private void sendJoin(REPCommand repCmd) {
//		smList.sendJoin(repCmd);
//	}

	private void sendSessionManagerJoinAck(SocketChannel channel, REPCommand repCmd) {
		String socketstring = getSocketString(channel);
		System.out.println(socketstring);
		smList.add(channel);								//SessionManagerのリストへ追加
		repCmd.setCMD(REP.SMCMD_SM_JOIN_ACK);
		repCmd.setString(repCmd.string + ":" + socketstring);
		REPPacketSend repSend4 = new REPPacketSend(channel);
		repSend4.send(repCmd);								//ACK
	}
	
	private void sendJoinAck(REPCommand repCmd) {
		
	}

	private void sendJoinAck(SocketChannel channel, REPCommand repCmd) {
		//int eid = sessionlist.getNumberOfEditor();	//eidを取得
		int eid = editorList.addEditor(channel, repCmd);
		sessionmanagerGUI.setComboEditor(eid, channel);		//ComboBoxにEditorを追加
		repCmd.setEID(eid);							//eidを決定して、
		repCmd.setCMD(REP.SMCMD_JOIN_ACK);
		repCmd.string = sessionlist.getSessionList();		//Session一覧を
		
		String string = getSocketString(channel);
		StringTokenizer stn = new StringTokenizer(string, ":");
		String host = stn.nextToken();
		String port = stn.nextToken();
		repCmd.setString(repCmd.string + ":" + myHost + ":" + port);
		
		REPPacketSend repSend = new REPPacketSend(channel);	//Editor側へ送信
		repSend.send(repCmd);
	}

	public static void main(String[] args) throws InterruptedException, IOException {
		int port = 8766;
		
		if(args.length == 1){
			port = Integer.parseInt(args[1]);
		}
		SessionManager sm = new SessionManager(port);
		sm.openSelector();
		sm.openWindow();
		sm.sessionManagerNet(port);
	}

	private void openWindow() {
		Thread th = new Thread( sessionmanagerGUI ); 
		th.start();
		System.out.println(sessionmanagerGUI.toString());
		sessionmanagerGUI.addConnectionListener(this);
		sessionmanagerGUI.addREPActionListener(this);
	}

	private void connectSession(String host) {
		int port = 8766;
		//SocketChannel sessionchannel;
		//int port = Integer.parseInt(args[2]);
		InetSocketAddress addr = new InetSocketAddress(host, port);
		try {
			SocketChannel sessionchannel = SocketChannel.open();
			sessionchannel.configureBlocking(true);
			sessionchannel.connect(addr);
			REPPacketSend send = new REPPacketSend(sessionchannel);
			while(!sessionchannel.finishConnect()){
				System.out.print(".");
			}
			System.out.println("");
			registerChannel(selector, sessionchannel, SelectionKey.OP_READ);
			//REPCommand sm_join_com = REPCommand.SMCMD_SESSION_JOIN;
			//String socketString = getSocketString(sessionchannel);
			//sm_join_com.setString(sm_join_com.string + ":" + socketString);
			send.send(REPCommand.SMCMD_SESSION_JOIN);
			smList.add(sessionchannel);
			smList.setMaster(sessionchannel);
		}catch (IOException e) {
			e.printStackTrace();
		}
	}

	private String getSocketString(SocketChannel sessionchannel) {
		SocketAddress socket = sessionchannel.socket().getRemoteSocketAddress();
		//String inetAddressString = sessionchannel.socket().getInetAddress().toString();
		StringTokenizer stn = new StringTokenizer(socket.toString(), "/");
		String socketString = null;
		while(stn.hasMoreTokens()){
			socketString = stn.nextToken();
			//System.out.println(socketString);
		}
		return socketString;
	}

	public void connectionOccured(ConnectionEvent event) {
		connectSession(event.getHost());
	}

	public void ActionOccured(REPActionEvent event) {
		System.out.println("Action!");
		SocketChannel editorChannel = event.getEditorChannel();
		int sid = event.getSID();
		int eid = event.getEID(); 
		sessionlist.addEditor(editorChannel, sid, eid);
		REPPacketSend send = new REPPacketSend(editorChannel);
		send.send(new REPCommand(REP.SMCMD_SELECT_ACK, sid, eid, 0,0,0,""));
		sessionlist.sendSelect(sid);
	}
}