/*
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2005 satoshi akabane(akabane@logical-paradox.org)
 * $Id: ExpandDatafCommand.java,v 1.2 2005/09/07 13:38:06 rampil Exp $
 */
package org.logical_paradox.vsan.dac.command.handler;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.logical_paradox.common.session.IllegalSessionStateException;
import org.logical_paradox.common.session.Session;
import org.logical_paradox.vsan.dac.DacConstant;
import org.logical_paradox.vsan.dac.NodeContext;
import org.logical_paradox.vsan.dac.Response;
import org.logical_paradox.vsan.dac.ResponseCode;
import org.logical_paradox.vsan.dac.command.exception.CommandExecutionException;
import org.logical_paradox.vsan.dac.command.exception.SessionTerminationException;
import org.logical_paradox.vsan.node.Database;

/**
 * 領域拡張コマンド
 * 新しいデータファイルを追加します
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.2 $
 */
public class ExpandDatafCommand implements DacCommand {
	/** ロガー */
	private static final Log log = LogFactory.getLog(ExpandDatafCommand.class);

	/**
	 * コマンドを実行する
	 * @param session 実行するセッション
	 * @return 更新されたセッション
	 * @throws CommandExecutionException コマンド実行中に発生した例外
	 * @throws SessionTerminationException 接続終了時に発生する例外
	 */
	public Session execute(Session session) throws CommandExecutionException, SessionTerminationException {
		try {
			NodeContext ctx = (NodeContext) session.getAttribute(DacConstant.SKEY_NODE_CONTEXT);
			Database db = ctx.getDatabase();

			// 引数の受信
			byte[] data = new byte[8+8];

			InputStream in = (InputStream)session.getAttribute(DacConstant.SKEY_SOCKET_INPUT_STREAM);
			int received = in.read(data);

			if(received != data.length) {
				log.warn("本来[" + data.length + "]バイト送信されてくるデータが、[" + received + "]バイトしか受信できませんでした");
				throw new CommandExecutionException();
			}

			ByteBuffer b = ByteBuffer.allocate(data.length).order(ByteOrder.BIG_ENDIAN);
			b.put(data);
			b.rewind();

			long recordBegin = b.getLong();
			long recordEnd = b.getLong();

			if(recordBegin <= 0 || recordEnd <= 0 || recordBegin >= recordEnd) {
				throw new CommandExecutionException("illegal argument");
			}

			// データファイルの追加
			db.expand(recordBegin, recordEnd);

			// レスポンスの作成
			session.setAttribute(DacConstant.SKEY_DAC_RESPONSE, new Response(ResponseCode.OK, new byte[0]));

			return session;

		} catch (IllegalSessionStateException e) {
			// セッションが継続可能な状態でない場合，当該セッションを終了する
			log.warn("データファイルの追加が要求されましたが、セッションが持続可能な状態ではありませんでした。");
			log.warn("セッションを破棄します。");
			throw new SessionTerminationException(e);
		} catch (IOException e) {
			log.warn("コマンド受信中にI/O例外が発生しました");
			throw new CommandExecutionException(e);
		}
	}

}
