[Jiemamy-notify] commit [2147] [SER-6] Swapper で複数回取得した RealObejct 同士は参照が同一であるべき

アーカイブの一覧に戻る

svnno****@sourc***** svnno****@sourc*****
2008年 11月 15日 (土) 18:22:57 JST


Revision: 2147
          http://svn.sourceforge.jp/cgi-bin/viewcvs.cgi?root=jiemamy&view=rev&rev=2147
Author:   ewigkeit1204
Date:     2008-11-15 18:22:57 +0900 (Sat, 15 Nov 2008)

Log Message:
-----------
[SER-6] Swapper で複数回取得した RealObejct 同士は参照が同一であるべき

Modified Paths:
--------------
    artemis/trunk/org.jiemamy.serializer/src/main/java/org/jiemamy/serializer/swap/SwapObject.java
    artemis/trunk/org.jiemamy.serializer/src/main/java/org/jiemamy/serializer/swap/Swapper.java
    artemis/trunk/org.jiemamy.serializer/src/test/java/org/jiemamy/serializer/swap/SwapperTest.java


-------------- next part --------------
Modified: artemis/trunk/org.jiemamy.serializer/src/main/java/org/jiemamy/serializer/swap/SwapObject.java
===================================================================
--- artemis/trunk/org.jiemamy.serializer/src/main/java/org/jiemamy/serializer/swap/SwapObject.java	2008-11-15 07:04:39 UTC (rev 2146)
+++ artemis/trunk/org.jiemamy.serializer/src/main/java/org/jiemamy/serializer/swap/SwapObject.java	2008-11-15 09:22:57 UTC (rev 2147)
@@ -19,12 +19,17 @@
 package org.jiemamy.serializer.swap;
 
 import java.io.Serializable;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
 
 /**
- * あるオブジェクトをスワップの対象とし、管理するクラス。
+ * ある RealObject をスワップの対象とし、管理するクラス。
  * 
  * <p>
- * スワップされたオブジェクトは{@link SwapObject#get() }で取得できる。
+ * スワップされたオブジェクトは{@link SwapObject#get() }で取得できる。<br>
+ * 内部では RealObject への弱参照を保持し、デシリアライズ要求を受けた際、<br>
+ * RealObject へ到達が可能と判断された場合は{@link Swapper }へデシリアライズ<br>
+ * 要求を委譲せず、到達できた RealObject を返す。
  * </p>
  * 
  * @author Keisuke.K
@@ -32,32 +37,52 @@
  */
 public class SwapObject<T extends Serializable> {
 	
-	/** スワップファイル内でのスワップ済みオブジェクトの位置 */
+	/** スワップファイル内でのスワップ済み RealObject の位置 */
 	long position;
 	
-	/** スワップファイル内でのスワップ済みオブジェクトのバイト長 */
+	/** スワップファイル内でのスワップ済み RealObject のバイト長 */
 	int length;
 	
+	/** スワップする RealObject への参照 */
+	Reference<T> ref;
+	
 
 	/**
 	 * コンストラクタ。
 	 * 
+	 * <p>
+	 * {@link Swapper }へシリアライズ要求を行う前に、RealObjectへの弱参照を保持する。
+	 * </p>
+	 * 
 	 * @param obj スワップの対象とするオブジェクト
 	 * @throws SwapException
 	 * @category instance creation
 	 */
 	public SwapObject(T obj) throws SwapException {
+		ref = new WeakReference<T>(obj);
 		Swapper.INSTANCE.serialize(this, obj);
 	}
 	
 	/**
 	 * スワップ済みのオブジェクトを取得する。
 	 * 
+	 * <p>
+	 * RealObject への弱参照が到達可能な場合、到達した RealObject を返す。<br>
+	 * 到達できない場合は{@link Swapper }へ RealObject のデシリアライズ要求を委譲する。
+	 * </p>
+	 * 
 	 * @return スワップ済みのオブジェクト
 	 * @throws SwapException
 	 */
-	public T get() throws SwapException {
-		return Swapper.INSTANCE.deserialize(this);
+	public synchronized T get() throws SwapException {
+		T obj = ref.get();
+		
+		if (obj == null) {
+			obj = Swapper.INSTANCE.deserialize(this);
+			ref = new WeakReference<T>(obj);
+		}
+		
+		return obj;
 	}
 	
 }

Modified: artemis/trunk/org.jiemamy.serializer/src/main/java/org/jiemamy/serializer/swap/Swapper.java
===================================================================
--- artemis/trunk/org.jiemamy.serializer/src/main/java/org/jiemamy/serializer/swap/Swapper.java	2008-11-15 07:04:39 UTC (rev 2146)
+++ artemis/trunk/org.jiemamy.serializer/src/main/java/org/jiemamy/serializer/swap/Swapper.java	2008-11-15 09:22:57 UTC (rev 2147)
@@ -60,10 +60,10 @@
 	FileChannel channel;
 	
 	/** スワップ情報を一元管理する参照TreeSet */
-	TreeSet<Reference<SwapObject<?>>> swapReferenceSet;
+	TreeSet<Reference<SwapObject<?>>> swapRefSet;
 	
 	/** スワップ情報参照キュー */
-	ReferenceQueue<SwapObject<?>> queue;
+	ReferenceQueue<SwapObject<?>> swapRefQueue;
 	
 
 	/**
@@ -81,8 +81,8 @@
 			throw new RuntimeException(e);
 		}
 		
-		swapReferenceSet = (new TreeSet<Reference<SwapObject<?>>>(new SetComparator()));
-		queue = new ReferenceQueue<SwapObject<?>>();
+		swapRefSet = new TreeSet<Reference<SwapObject<?>>>(new SetComparator());
+		swapRefQueue = new ReferenceQueue<SwapObject<?>>();
 	}
 	
 	/**
@@ -95,16 +95,16 @@
 	 * @throws IOException 
 	 */
 	void clean() throws IOException {
-		synchronized (swapReferenceSet) {
+		synchronized (swapRefSet) {
 			// 参照TreeSetのクリーニング
 			Reference<? extends SwapObject<?>> ref;
-			while ((ref = queue.poll()) != null) {
-				swapReferenceSet.remove(ref);
+			while ((ref = swapRefQueue.poll()) != null) {
+				swapRefSet.remove(ref);
 			}
 			
 			// スワップファイルのサイズ調整
-			if (swapReferenceSet.size() > 0) {
-				SwapObject<?> swapObj = swapReferenceSet.last().get();
+			if (swapRefSet.size() > 0) {
+				SwapObject<?> swapObj = swapRefSet.last().get();
 				if (swapObj != null) {
 					synchronized (channel) {
 						channel.truncate(swapObj.position + swapObj.length);
@@ -199,24 +199,8 @@
 	 */
 	<T extends Serializable>void serialize(SwapObject<T> swapObj, T obj) throws SwapException {
 		// オブジェクトのシリアライズを行う
-		ByteArrayOutputStream baos = new ByteArrayOutputStream();
-		ObjectOutputStream oos = null;
+		ByteBuffer buffer = serialize(obj);
 		
-		try {
-			oos = new ObjectOutputStream(baos);
-			oos.writeObject(obj);
-		} catch (IOException e) {
-			throw new SwapException(e);
-		} finally {
-			try {
-				if (oos != null) {
-					oos.close();
-				}
-			} catch (IOException e) {
-				throw new SwapException(e);
-			}
-		}
-		
 		// オブジェクトをスワップする位置を特定する
 		try {
 			clean();
@@ -224,9 +208,9 @@
 			throw new SwapException(e);
 		}
 		
-		synchronized (swapReferenceSet) {
+		synchronized (swapRefSet) {
 			long pos = 0L;
-			for (Reference<SwapObject<?>> ref : swapReferenceSet) {
+			for (Reference<SwapObject<?>> ref : swapRefSet) {
 				SwapObject<? extends Serializable> tmp = ref.get();
 				
 				if (tmp == null) {
@@ -234,7 +218,7 @@
 					continue;
 				}
 				
-				if (tmp.position - pos >= baos.size()) {
+				if (tmp.position - pos >= buffer.limit()) {
 					// 位置決定
 					break;
 				}
@@ -243,25 +227,63 @@
 			}
 			
 			swapObj.position = pos;
-			swapObj.length = baos.size();
+			swapObj.length = buffer.limit();
 			
-			Reference<SwapObject<?>> ref = new WeakReference<SwapObject<?>>(swapObj, queue);
-			swapReferenceSet.add(ref);
+			Reference<SwapObject<?>> ref = new WeakReference<SwapObject<?>>(swapObj, swapRefQueue);
+			swapRefSet.add(ref);
 		}
 		
 		// スワップ
-		ByteBuffer buffer = ByteBuffer.wrap(baos.toByteArray());
+		swap(buffer, swapObj.position);
+	}
+	
+	/**
+	 * オブジェクトをシリアライズして、その結果をByteBufferで取得する。
+	 * 
+	 * @param obj シリアライズするオブジェクト
+	 * @return シリアライズ結果のバイト値を保持するByteBuffer
+	 * @throws SwapException
+	 */
+	private ByteBuffer serialize(Serializable obj) throws SwapException {
+		ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		ObjectOutputStream oos = null;
 		
 		try {
-			synchronized (channel) {
-				channel.write(buffer, swapObj.position);
-			}
+			oos = new ObjectOutputStream(baos);
+			oos.writeObject(obj);
 		} catch (IOException e) {
 			throw new SwapException(e);
+		} finally {
+			try {
+				if (oos != null) {
+					oos.close();
+				}
+			} catch (IOException e) {
+				throw new SwapException(e);
+			}
 		}
+		
+		return ByteBuffer.wrap(baos.toByteArray());
 	}
 	
+	/**
+	 * シリアライズしたオブジェクトをスワップする。
 
+	 * @param buffer シリアライズ結果
+	 * @param position スワップ位置
+	 * @throws SwapException
+	 */
+	private void swap(ByteBuffer buffer, long position) throws SwapException {
+		synchronized (channel) {
+			try {
+				channel.write(buffer, position);
+			} catch (IOException e) {
+				throw new SwapException(e);
+			}
+		}
+	}
+	
+
 	/**
 	 * {@code swapReferenceSet }のための比較クラス。
 	 * 

Modified: artemis/trunk/org.jiemamy.serializer/src/test/java/org/jiemamy/serializer/swap/SwapperTest.java
===================================================================
--- artemis/trunk/org.jiemamy.serializer/src/test/java/org/jiemamy/serializer/swap/SwapperTest.java	2008-11-15 07:04:39 UTC (rev 2146)
+++ artemis/trunk/org.jiemamy.serializer/src/test/java/org/jiemamy/serializer/swap/SwapperTest.java	2008-11-15 09:22:57 UTC (rev 2147)
@@ -19,6 +19,7 @@
 package org.jiemamy.serializer.swap;
 
 import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertSame;
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.fail;
 
@@ -89,6 +90,7 @@
 		String str2 = "fizzbuzz";
 		
 		// スワップ
+		@SuppressWarnings("unused")
 		SwapObject<String> swapObj1 = new SwapObject<String>(str1);
 		@SuppressWarnings("unused")
 		SwapObject<String> swapObj2 = new SwapObject<String>(str2);
@@ -103,13 +105,12 @@
 		// see. http://d.hatena.ne.jp/Ewigkeit/20080823/1219463052
 		Thread.sleep(1000L);
 		
-		// swapObj1の取得を行うことで、スワップファイルの長さを調整させる。
-		String getStr1 = swapObj1.get();
+		// Swapper をクリーニング
+		Swapper.INSTANCE.clean();
 		
 		long newSize = Swapper.INSTANCE.channel.size();
 		
 		// チェック
-		assertEquals(str1, getStr1);
 		assertTrue(currentSize > newSize);
 		
 		// [SER-5] 新しくオブジェクトをスワップさせ、NPE が発生しないことを確認。
@@ -121,4 +122,26 @@
 		}
 	}
 	
+	/**
+	 * 1つのSwapObjectに対して複数回get()を行い、取得できたRealObject同士は参照が同一であるべき。
+	 * 
+	 * @throws Exception
+	 */
+	@Test
+	public void test04_複数回取得したRealObjectの参照同一性() throws Exception {
+		HashMap<String, String> testMap = new HashMap<String, String>();
+		testMap.put("foo", "bar");
+		testMap.put("fizz", "buzz");
+		
+		// スワップ
+		SwapObject<HashMap<String, String>> swapObj = new SwapObject<HashMap<String, String>>(testMap);
+		
+		// 取得
+		HashMap<String, String> map1 = swapObj.get();
+		HashMap<String, String> map2 = swapObj.get();
+		
+		// チェック
+		assertSame(map1, map2);
+	}
+	
 }


Jiemamy-notify メーリングリストの案内
アーカイブの一覧に戻る