view src/main/java/app/bbs/NetworkJungleBulletinBoard.java @ 178:d6944d788121

fit Junglecore
author tatsuki
date Thu, 04 Sep 2014 13:12:25 +0900
parents 6f104ab4eb81
children 2828205bdc3a
line wrap: on
line source

package app.bbs;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicInteger;

import alice.jungle.core.NetworkDefaultJungle;
import alice.jungle.persistent.AliceJournal;
import alice.jungle.persistent.NetworkJournal;
import alice.jungle.persistent.PersistentJournal;
import alice.jungle.transaction.JungleUpdater;
import app.bbs.thinks.getAttributeImp;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.Jungle;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.JungleTree;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.JungleTreeEditor;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.bbs.BoardMessage;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.core.Children;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.persistent.ChangeList;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.persistent.ChangeListReader;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.DefaultNodePath;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.DefaultTreeEditor;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.TreeNode;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.DefaultOperationLog;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.OperationLog;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.operations.PutAttributeOperation;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.trasnformer.NodeEditor;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.traverser.DefaultEvaluator;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.traverser.DefaultTraverser;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.traverser.Traversal;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.DefaultEither;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Either;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Error;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.IterableConverter;
import junit.framework.Assert;

public class NetworkJungleBulletinBoard implements NetworkBulletinBoard {
	private final Jungle jungle;
	private final NetworkJournal journal;
	private final String LOG_DIR;
	private Boolean persistentFlag;
	private AtomicInteger requestCounter;
	private long renewTime;

	private NetworkJungleBulletinBoard(String _uuid, NetworkJournal _journal) {
		journal = _journal;
		jungle = new NetworkDefaultJungle(journal, _uuid,
				new DefaultTreeEditor(new DefaultTraverser()));
		BulletinBoardJungleManager.setJungle(jungle);
		persistentFlag = false;
		requestCounter = BulletinBoardJungleManager.getRequestCounter();
		LOG_DIR = "./log";
		renewTime = 0;
	}

	public NetworkJungleBulletinBoard(String _uuid) {
		this(_uuid, new AliceJournal());
		jungle.createNewTree("boards");
	}

	public static NetworkBulletinBoard NewPersistentJungle(String _uuid) {
		NetworkJungleBulletinBoard board = new NetworkJungleBulletinBoard(
				_uuid, new PersistentJournal());
		board.persistentFlag = true;
		return board;
	}

	public void init() {
		if (!persistentFlag) {
			return;
		}
		checkAndCreateLogDirectory();
		try {
			commitLogRecover();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void checkAndCreateLogDirectory() {
		File logFile = new File(LOG_DIR);
		if (!logFile.exists()) {
			logFile.mkdir();
			return;
		}
		if (logFile.isFile()) {
			logFile.delete();
			logFile.mkdir();
		}
	}

	public void commitLogRecover() throws IOException {
		File[] logFiles = new File(LOG_DIR).listFiles();
		for (File logFile : logFiles) {
			commitLogRecover(logFile);
			logFile.delete();
		}
		if (jungle.getTreeByName("boards") == null) {
			jungle.createNewTree("boards");
		}
	}

	private void commitLogRecover(File logFile) throws IOException {
		journal.setInputFile(logFile);
		ChangeListReader reader = journal.getReader();
		if (reader == null)
			return;
		for (ChangeList chList : reader) {
			String treeName = chList.getTreeName();
			JungleTree tree = jungle.getTreeByName(treeName);
			if (tree == null) {
				tree = jungle.createNewTree(treeName);
			}
			JungleTreeEditor editor = tree.getLocalTreeEditor();
			Either<Error, JungleTreeEditor> either = JungleUpdater.edit(editor,
					chList);
			editor = either.b();
			if (either.isA()) {
				throw new IOException("Failed commit log recovery");
			}
			editor.success();
		}
	}

	public Iterable<String> getBoards() {
		JungleTree tree = jungle.getTreeByName("boards");
		TreeNode node = tree.getRootNode();
		Children chs = node.getChildren();

		IterableConverter.Converter<String, TreeNode> converter = new IterableConverter.Converter<String, TreeNode>() {
			public String conv(TreeNode _b) {
				ByteBuffer e = _b.getAttributes().get("name");
				System.out.println(new String(e.array()));
				return new String(e.array());
			}
		};

		return new IterableConverter<String, TreeNode>(chs, converter);
	}

	public long getRenewTime(String _boardName) {
		return renewTime;
	}

	public void createBoards(final String _name, final String _author, final String _initMessage, final String _editKey) {
		requestCounter.incrementAndGet();
		if (null == jungle.createNewTree(_name)) {
			throw new IllegalStateException();
		}

		JungleTree tree = jungle.getTreeByName("boards");
		JungleTreeEditor editor = tree.getTreeEditor();
		DefaultNodePath root = new DefaultNodePath();
		Either<Error, JungleTreeEditor> either = editor.addNewChildAt(root, 0);
		if (either.isA()) {
			throw new IllegalStateException();
		}
		editor = either.b();

		either = editor.putAttribute(root.add(0), "name",
				ByteBuffer.wrap(_name.getBytes()));
		if (either.isA()) {
			throw new IllegalStateException();
		}
		editor = either.b();
		final long timestamp = System.currentTimeMillis();
		ByteBuffer tBuffer = ByteBuffer.allocate(16);
		tBuffer.putLong(timestamp);
		either = editor.putAttribute(root.add(0), "timestamp", tBuffer);
		if (either.isA()) {
			throw new IllegalStateException();
		}
		either = either.b().success();
		if (either.isA()) {
			throw new IllegalStateException();
		}

		tree = jungle.getTreeByName(_name);
		editor = tree.getTreeEditor();
		either = editor.addNewChildAt(root, 0);
		if (either.isA()) {
			throw new IllegalStateException();
		}
		editor = either.b();

		NodeEditor e = new NodeEditor() {
			ByteBuffer tBuffer2 = ByteBuffer.allocate(16);

			public Either<Error, TreeNode> edit(TreeNode node) {
				node = node.getAttributes().put("author", ByteBuffer.wrap(_author.getBytes())).b();
				node = node.getAttributes().put("mes", ByteBuffer.wrap(_initMessage.getBytes())).b();
				node = node.getAttributes().put("key", ByteBuffer.wrap(_editKey.getBytes())).b();
				tBuffer2.putLong(timestamp);
				node = node.getAttributes().put("timestamp", tBuffer2).b();
				return DefaultEither.newB(node);
			}

		};

		either = editor.edit(root.add(0), e);
		if (either.isA()) {
			throw new IllegalStateException();
		}
		either.b().success();

	}

	public void createFolder(final String _board, final String _author, final String _message, final String _editKey, String _nodeNum) {
		JungleTree tree = jungle.getTreeByName(_board);
		if (tree == null) {
			throw new IllegalStateException();
		}

		DefaultNodePath path = new DefaultNodePath();
		try {
			for (int count = 0; _nodeNum.substring(count, count + 1) != null; count++) {
				if (!_nodeNum.substring(count, count + 1).equals("/"))
					path = path.add(Integer.parseInt(_nodeNum.substring(count,
							count + 1)));
			}
		} catch (Exception _e) {
		}
		requestCounter.incrementAndGet();
		Either<Error, JungleTreeEditor> either;
		final long timestamp = System.currentTimeMillis();
		final ByteBuffer tBuffer = ByteBuffer.allocate(16);
		tBuffer.putLong(timestamp);

		do {
			TreeNode node = tree.getRootNode();
			DefaultTraverser traverser = new DefaultTraverser();
			// TraversableNodeWrapper<Node> traversable = new
			// TraversableNodeWrapper<Node>(node);
			DefaultEvaluator evaluator = new DefaultEvaluator(path);
			Either<Error, Traversal> ret = traverser.traverse(node,
					evaluator);
			if (ret.isA()) {
				Assert.fail();
			}

			Traversal traversal = ret.b();
			TreeNode target = traversal.destination();
			int size = target.getChildren().size();
			JungleTreeEditor editor = tree.getTreeEditor();
			either = editor.addNewChildAt(path, size);
			if (either.isA()) {
				throw new IllegalStateException();
			}
			editor = either.b();

			NodeEditor e = new NodeEditor() {

				public Either<Error, TreeNode> edit(TreeNode node) {
					node = node.getAttributes().put("mes", ByteBuffer.wrap(_message.getBytes())).b();
					node = node.getAttributes().put("timestamp", tBuffer).b();
					return DefaultEither.newB(node);
				}

			};
			path = path.add(size);
			either = editor.edit(path, e);
			if (either.isA()) {
				throw new IllegalStateException();
			}
			editor = either.b();
			either = editor.success();
		} while (either.isA());

	}

	public void createBoardMessage(final String _board, final String _author, final String _message, final String _editKey) {
		requestCounter.incrementAndGet();
		JungleTree tree = jungle.getTreeByName(_board);
		if (tree == null) {
			throw new IllegalStateException();
		}

		Either<Error, JungleTreeEditor> either;
		final long timestamp = System.currentTimeMillis();
		final ByteBuffer tBuffer = ByteBuffer.allocate(16);
		tBuffer.putLong(timestamp);
		do {

			TreeNode node = tree.getRootNode();
			int size = node.getChildren().size();
			DefaultNodePath path = new DefaultNodePath();

			JungleTreeEditor editor = tree.getTreeEditor();
			either = editor.addNewChildAt(path, size);
			if (either.isA()) {
				throw new IllegalStateException();
			}
			editor = either.b();

			NodeEditor e = new NodeEditor() {
				public Either<Error, TreeNode> edit(TreeNode node) {
					node = node.getAttributes().put("author", ByteBuffer.wrap(_author.getBytes())).b();
					node = node.getAttributes().put("mes", ByteBuffer.wrap(_message.getBytes())).b();
					node = node.getAttributes().put("key", ByteBuffer.wrap(_editKey.getBytes())).b();
					node = node.getAttributes().put("timestamp", tBuffer).b();
					return DefaultEither.newB(node);
				}

			};
			path = path.add(size);
			either = editor.edit(path, e);
			if (either.isA()) {
				throw new IllegalStateException();
			}
			editor = either.b();
			either = editor.success();
		} while (either.isA());

	}

	public void editMessage(String _board, String _nodeNum,final String _author, final String _message, final String _editKey) {
		requestCounter.incrementAndGet();
		final long timestamp = System.currentTimeMillis();
		final ByteBuffer tBuffer = ByteBuffer.allocate(16);
		tBuffer.putLong(timestamp);
		JungleTree tree = jungle.getTreeByName(_board);
		Either<Error, JungleTreeEditor> either = null;

		do {
			DefaultNodePath path = new DefaultNodePath();
			try {
				for (int count = 0; _nodeNum.substring(count, count + 1) != null; count++) {
					if (!_nodeNum.substring(count, count + 1).equals("/"))
						path = path.add(Integer.parseInt(_nodeNum.substring(count, count + 1)));
				}
			} catch (Exception _e) {
			}
			JungleTreeEditor editor = tree.getTreeEditor();
			NodeEditor e = new NodeEditor() {
				public Either<Error, TreeNode> edit(TreeNode node) {
					System.out.println(new String(node.getAttributes().get("mes").array()));
					node = node.getAttributes().put("author", ByteBuffer.wrap(_author.getBytes())).b();
					node = node.getAttributes().put("mes", ByteBuffer.wrap(_message.getBytes())).b();
					node = node.getAttributes().put("key", ByteBuffer.wrap(_editKey.getBytes())).b();
					node = node.getAttributes().put("timestamp", tBuffer).b();
					System.out.println(new String(node.getAttributes().get("mes").array()));
					return DefaultEither.newB(node);
				}

			};
			either = editor.edit(path, e);
			if (either.isA()) {
				throw new IllegalStateException();
			}
			editor = either.b();
			either = editor.success();
		} while (either.isA());
		renewTime = timestamp;
	}

	public void createAttribute(String _board, String _uuid, final String _author, final String _message, final String _editKey) {
		requestCounter.incrementAndGet();
		final long timestamp = System.currentTimeMillis();
		final ByteBuffer tBuffer = ByteBuffer.allocate(16);
		tBuffer.putLong(timestamp);
		JungleTree tree = jungle.getTreeByName(_board);
		Either<Error, JungleTreeEditor> either = null;
		DefaultNodePath path = new DefaultNodePath();
		do {
			try {
				for (int count = 0; _uuid.substring(count, count + 1) != null; count++) {
					if (!_uuid.substring(count, count + 1).equals("/"))
						path = path.add(Integer.parseInt(_uuid.substring(count,
								count + 1)));
				}
			} catch (Exception _e) {
			}

			JungleTreeEditor editor = tree.getTreeEditor();
			NodeEditor e = new NodeEditor() {
				String str;

				public Either<Error, TreeNode> edit(TreeNode node) {
					str = "0";
					int count = 0;
					for (; node.getAttributes().get("mes" + String.valueOf(count)) != null; count++) {
					}
					str = String.valueOf(count);
					node = node.getAttributes().put("mes" + str,ByteBuffer.wrap(_message.getBytes())).b();
					node = node.getAttributes().put("timestamp" + str, tBuffer).b();
					return DefaultEither.newB(node);
				}

			};
			either = editor.edit(path, e);
			if (either.isA()) {
				throw new IllegalStateException();
			}
			editor = either.b();
			either = editor.success();
		} while (either.isA());
	}

	public void editAttribute(String boardName, String _path, final String id, final String _message) {
		requestCounter.incrementAndGet();
		final long timestamp = System.currentTimeMillis();
		final ByteBuffer tBuffer = ByteBuffer.allocate(16);
		tBuffer.putLong(timestamp);
		JungleTree tree = jungle.getTreeByName(boardName);
		Either<Error, JungleTreeEditor> either = null;
		DefaultNodePath path = new DefaultNodePath();
		do {
			try {
				for (int count = 0; _path.substring(count, count + 1) != null; count++) {
					if (!_path.substring(count, count + 1).equals("/"))
						path = path.add(Integer.parseInt(_path.substring(count,
								count + 1)));
				}
			} catch (Exception _e) {
			}

			JungleTreeEditor editor = tree.getTreeEditor();
			NodeEditor e = new NodeEditor() {
				public Either<Error, TreeNode> edit(TreeNode node) {
					// EnableNodeWrapper<T> node = _e.getWrap();
					node = node.getAttributes().put("mes" + id,ByteBuffer.wrap(_message.getBytes())).b();
					node = node.getAttributes().put("timestamp" + id, tBuffer).b();
					return DefaultEither.newB(node);
				}

			};
			either = editor.edit(path, e);
			if (either.isA()) {
				throw new IllegalStateException();
			}
			editor = either.b();
			either = editor.success();
		} while (either.isA());
	}

	public void deleteNode(String _board, String _path, String _id) {
		requestCounter.incrementAndGet();
		int id = Integer.parseInt(_id);
		final long timestamp = System.currentTimeMillis();
		final ByteBuffer tBuffer = ByteBuffer.allocate(16);
		tBuffer.putLong(timestamp);
		JungleTree tree = jungle.getTreeByName(_board);
		Either<Error, JungleTreeEditor> either = null;
		DefaultNodePath path = new DefaultNodePath();
		do {
			try {
				for (int count = 0; _path.substring(count, count + 1) != null; count++) {
					if (!_path.substring(count, count + 1).equals("/"))
						path = path.add(Integer.parseInt(_path.substring(count,count + 1)));
				}
			} catch (Exception _e) {
			}

			JungleTreeEditor editor = tree.getTreeEditor();

			either = editor.deleteChildAt(path, id);
			if (either.isA()) {
				throw new IllegalStateException();
			}
			editor = either.b();
			either = editor.success();
		} while (either.isA());

	}

	public void deleteAttribute(String _board, String _path, final String id) {
		requestCounter.incrementAndGet();
		final long timestamp = System.currentTimeMillis();
		final ByteBuffer tBuffer = ByteBuffer.allocate(16);
		tBuffer.putLong(timestamp);
		JungleTree tree = jungle.getTreeByName(_board);
		Either<Error, JungleTreeEditor> either = null;
		DefaultNodePath path = new DefaultNodePath();
		do {
			try {
				for (int count = 0; _path.substring(count, count + 1) != null; count++) {
					if (!_path.substring(count, count + 1).equals("/"))
						path = path.add(Integer.parseInt(_path.substring(count,
								count + 1)));
				}
			} catch (Exception _e) {
				System.out.println("屑");
			}

			JungleTreeEditor editor = tree.getTreeEditor();
			NodeEditor e = new NodeEditor() {
				public Either<Error, TreeNode> edit(TreeNode node) {
					node = node.getAttributes().delete("mes" + id).b();
					node = node.getAttributes().delete("timestamp" + id).b();
					int count = Integer.parseInt(id);
					for (; node.getAttributes().get("mes" + String.valueOf(count + 1)) != null;) {
						node = node.getAttributes().put("mes" + count,node.getAttributes().get("mes"+ String.valueOf(count + 1))).b();
						node = node.getAttributes().put("timestamp" + count, tBuffer).b();
						count++;
					}
					if (count != Integer.parseInt(id)) {
						node = node.getAttributes().delete("timestamp" + count).b();
						node = node.getAttributes().delete("mes" + count).b();
					}

					return DefaultEither.newB(node);
				}

			};
			either = editor.edit(path, e);
			if (either.isA()) {
				throw new IllegalStateException();
			}
			editor = either.b();
			either = editor.success();
		} while (either.isA());
	}

	public void editMatrixMessage(String _board, String _uuid,
			final String _author, final String _message, final String _editKey) {
		requestCounter.incrementAndGet();
		final long timestamp = System.currentTimeMillis();
		final ByteBuffer tBuffer = ByteBuffer.allocate(16);
		tBuffer.putLong(timestamp);
		JungleTree tree = jungle.getTreeByName(_board);
		Either<Error, JungleTreeEditor> either = null;
		do {
			DefaultNodePath path = new DefaultNodePath();
			path = path.add(Integer.parseInt(_uuid));

			JungleTreeEditor editor = tree.getTreeEditor();
			NodeEditor e = new NodeEditor() {
				public Either<Error, TreeNode> edit(TreeNode node) {
					node = node.getAttributes().put("author", ByteBuffer.wrap(_author.getBytes())).b();
					node = node.getAttributes().put("mes", ByteBuffer.wrap(_message.getBytes())).b();
					node = node.getAttributes().put("key", ByteBuffer.wrap(_editKey.getBytes())).b();
					node = node.getAttributes().put("timestamp", tBuffer).b();
					return DefaultEither.newB(node);
				}
			};
			either = editor.edit(path, e);
			if (either.isA()) {
				throw new IllegalStateException();
			}
			editor = either.b();
			either = editor.success();
		} while (either.isA());
		renewTime = timestamp;
	}

	public Iterable<BoardMessage> getMessages(String _boardName) {
		requestCounter.incrementAndGet();
		JungleTree tree = jungle.getTreeByName(_boardName);
		TreeNode node = tree.getRootNode();
		Children chs = node.getChildren();
		final AtomicInteger counter = new AtomicInteger(0);
		IterableConverter.Converter<BoardMessage, TreeNode> converter = new IterableConverter.Converter<BoardMessage, TreeNode>() {
			public BoardMessage conv(TreeNode _b) {
				String uuid = Integer.toString(counter.get());
				String author = new String(_b.getAttributes().get("author").array());
				String message = new String(_b.getAttributes().get("mes").array());
				counter.incrementAndGet();
				return new BoardMessageImpl(author, message, uuid);
			}
		};
		return new IterableConverter<BoardMessage, TreeNode>(chs, converter);
	}

	public Iterable<BoardMessage> getFolder(String _boardName, String _nodeNum) {

		DefaultNodePath path = new DefaultNodePath();
		try {
			for (int count = 0; _nodeNum.substring(count, count + 1) != null; count++) {
				if (!_nodeNum.substring(count, count + 1).equals("/"))
					path = path.add(Integer.parseInt(_nodeNum.substring(count,count + 1)));
			}
		} catch (Exception _e) {
		}
		requestCounter.incrementAndGet();
		JungleTree tree = jungle.getTreeByName(_boardName);
		TreeNode node = tree.getRootNode();

		DefaultTraverser traverser = new DefaultTraverser();
		// TraversableNodeWrapper<Node> traversable = new
		// TraversableNodeWrapper<Node>(node);
		DefaultEvaluator evaluator = new DefaultEvaluator(path);
		Either<Error, Traversal> ret = traverser.traverse(node,
				evaluator);
		if (ret.isA()) {
			Assert.fail();
		}

		Traversal traversal = ret.b();
		TreeNode target = traversal.destination();
		Children chs = target.getChildren();

		final AtomicInteger counter = new AtomicInteger(0);
		IterableConverter.Converter<BoardMessage, TreeNode> converter = new IterableConverter.Converter<BoardMessage, TreeNode>() {
			public BoardMessage conv(TreeNode _b) {
				String uuid = Integer.toString(counter.get());
				String message = new String(_b.getAttributes().get("mes")
						.array());
				counter.incrementAndGet();
				return new BoardMessageImpl(null, message, uuid);
			}
		};
		return new IterableConverter<BoardMessage, TreeNode>(chs, converter);
	}

	public getAttributeImp getAttribute(String _boardName, String _nodeNum) {

		DefaultNodePath path = new DefaultNodePath();
		try {
			for (int count = 0; _nodeNum.substring(count, count + 1) != null; count++) {
				if (!_nodeNum.substring(count, count + 1).equals("/"))
					path = path.add(Integer.parseInt(_nodeNum.substring(count,
							count + 1)));
			}
		} catch (Exception _e) {
		}
		requestCounter.incrementAndGet();
		JungleTree tree = jungle.getTreeByName(_boardName);
		TreeNode node = tree.getRootNode();

		DefaultTraverser traverser = new DefaultTraverser();
		// TraversableNodeWrapper<Node> traversable = new
		// TraversableNodeWrapper<Node>(node);
		DefaultEvaluator evaluator = new DefaultEvaluator(path);
		Either<Error, Traversal> ret = traverser.traverse(node,
				evaluator);
		if (ret.isA()) {
			Assert.fail();
		}

		Traversal traversal = ret.b();
		TreeNode target = traversal.destination();
		return new getAttributeImp(target);
	}

	public int getRequestNum() {
		return requestCounter.get();
	}

	private static class BoardMessageImpl implements BoardMessage {
		private final String author;
		private final String message;
		private final String uuid;

		public BoardMessageImpl(String _author, String _message, String _uuid) {
			author = _author;
			message = _message;
			uuid = _uuid;
		}

		public String getAuthor() {
			return author;
		}

		public String getMessage() {
			return message;
		}

		public String getUUID() {
			return uuid;
		}

	}

	public String sanitize(String str) {
		if (str == null) {
			return str;
		}
		str = str.replaceAll("&", "&amp;");
		str = str.replaceAll("<", "&lt;");
		str = str.replaceAll(">", "&gt;");
		str = str.replaceAll("\"", "&quot;");
		str = str.replaceAll("'", "&#39;");
		return str;
	}

}