fix a memory recycle issue in sorter's memory manager

git-svn-id: https://hyracks.googlecode.com/svn/branches/hyracks_sort_join_opts@1135 123451ca-8445-de46-9d55-352943316053
diff --git a/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/BSTMemMgr.java b/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/BSTMemMgr.java
index 7454523..eda567a 100644
--- a/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/BSTMemMgr.java
+++ b/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/BSTMemMgr.java
@@ -8,14 +8,13 @@
 import edu.uci.ics.hyracks.dataflow.common.comm.io.FrameTupleAppender;
 
 /**
- * @author pouria
- *         Implements Memory Manager based on creating Binary Search Tree (BST)
- *         while Free slot size is the key for the BST nodes. Each node in BST
- *         shows a class of free slots, while all the free slots within a class
- *         have same lengths. Slots in a class are stored as a LinkedList, whose
- *         head is the BST node, corresponding to that class. BST is not stored
- *         as a separate data structure, but the free slots in the memory are
- *         used to hold BST nodes. Each BST node has the logical structure,
+ * @author pouria Implements Memory Manager based on creating Binary Search Tree
+ *         (BST) while Free slot size is the key for the BST nodes. Each node in
+ *         BST shows a class of free slots, while all the free slots within a
+ *         class have same lengths. Slots in a class are stored as a LinkedList,
+ *         whose head is the BST node, corresponding to that class. BST is not
+ *         stored as a separate data structure, but the free slots in the memory
+ *         are used to hold BST nodes. Each BST node has the logical structure,
  *         defined in the BSTNodeUtil class.
  */
 public class BSTMemMgr implements IMemoryManager {
@@ -26,11 +25,13 @@
     private ByteBuffer[] frames;
     private ByteBuffer convertBuffer;
     private Slot root;
-    private Slot result; // A reusable object to hold one node returned as method result
-    private Slot insertSlot; // A reusable object to hold one node within insert process
-    private Slot lastLeftParent; //A reusable object for the search process
-    private Slot lastLeft; //A reusable object for the search process
-    private Slot parent; //A reusable object for the search process 
+    private Slot result; // A reusable object to hold one node returned as
+                         // method result
+    private Slot insertSlot; // A reusable object to hold one node within insert
+                             // process
+    private Slot lastLeftParent; // A reusable object for the search process
+    private Slot lastLeft; // A reusable object for the search process
+    private Slot parent; // A reusable object for the search process
 
     private Slot[] parentRes;
     private int lastFrame;
@@ -68,7 +69,8 @@
         if (shouldSplit(sl, acLen)) {
             int[] s = split(parentRes[1], parentRes[0], acLen);
             int insertLen = BSTNodeUtil.getLength(s[2], s[3], frames, convertBuffer);
-            insert(s[2], s[3], insertLen); // inserting second half of the split slot
+            insert(s[2], s[3], insertLen); // inserting second half of the split
+                                           // slot
             BSTNodeUtil.setHeaderFooter(s[0], s[1], length, false, frames);
             result.set(s[0], s[1]);
             return;
@@ -87,7 +89,8 @@
                 : BSTNodeUtil.INVALID_INDEX);
         int t = off + 2 * BSTNodeUtil.HEADER_SIZE + actualLen;
         int nextMemSlotHeaderOffset = (t < frameSize ? t : BSTNodeUtil.INVALID_INDEX);
-        // Remember: next and prev memory slots have the same frame index as the unallocated slot
+        // Remember: next and prev memory slots have the same frame index as the
+        // unallocated slot
         if (!isNodeNull(fix, prevMemSlotFooterOffset) && BSTNodeUtil.isFree(fix, prevMemSlotFooterOffset, frames)) {
             int leftLength = BSTNodeUtil.getLength(fix, prevMemSlotFooterOffset, frames, convertBuffer);
             removeFromList(fix, prevMemSlotFooterOffset - leftLength - BSTNodeUtil.HEADER_SIZE);
@@ -145,6 +148,14 @@
         return frames[frameIndex];
     }
 
+    @Override
+    public void close() {
+        //clean up all frames
+        for (int i = 0; i < frames.length; i++)
+            frames[i] = null;
+        System.gc();
+    }
+
     /**
      * @param parentResult
      *            is the container passed by the caller to contain the results
diff --git a/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/IMemoryManager.java b/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/IMemoryManager.java
index 1447fa6..418b4ad 100644
--- a/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/IMemoryManager.java
+++ b/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/IMemoryManager.java
@@ -7,9 +7,9 @@
 import edu.uci.ics.hyracks.dataflow.common.comm.io.FrameTupleAppender;
 
 /**
- * @author pouria
- *         Defines the required operations, needed for any memory manager, used
- *         in sorting with replacement selection, to manage the free spaces
+ * @author pouria Defines the required operations, needed for any memory
+ *         manager, used in sorting with replacement selection, to manage the
+ *         free spaces
  */
 
 public interface IMemoryManager {
@@ -66,4 +66,9 @@
      */
     boolean readTuple(int frameIx, int offset, FrameTupleAppender dest);
 
+    /**
+     * close and cleanup the memory manager
+     */
+    void close();
+
 }
\ No newline at end of file
diff --git a/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/OptimizedExternalSortRunGenerator.java b/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/OptimizedExternalSortRunGenerator.java
index f04365d..8e1e3a7 100644
--- a/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/OptimizedExternalSortRunGenerator.java
+++ b/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/OptimizedExternalSortRunGenerator.java
@@ -157,6 +157,7 @@
         outputAppender.reset(outputBuffer, true);
         writer.close();
         runs.add(writer.createReader());
+        memMgr.close();
     }
 
     public List<IFrameReader> getRuns() {
diff --git a/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/OptimizedExternalSortRunGeneratorWithLimit.java b/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/OptimizedExternalSortRunGeneratorWithLimit.java
index 50c9c9c..3ccba02 100644
--- a/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/OptimizedExternalSortRunGeneratorWithLimit.java
+++ b/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/sort/OptimizedExternalSortRunGeneratorWithLimit.java
@@ -224,6 +224,7 @@
 
         writer.close();
         runs.add(writer.createReader());
+        memMgr.close();
     }
 
     public List<IFrameReader> getRuns() {