Allon Mureinik has uploaded a new change for review.

Change subject: core, restapi: Remove double ReapedMaps
......................................................................

core, restapi: Remove double ReapedMaps

There are two almost identical (except for whitespaces and the
occasional formatting difference) classes called ReadpedMap in oVirt
Engine:
1. org.ovirt.engine.api.common.util.ReapedMap
2. org.ovirt.engine.core.utils.ReapedMap

This patch removes the api class, and leaves only the core one.
It includes:
1. Removal of the redundant class and deferring all usages to the
   correct class.
2. Moving the test from the rest package to the core package.
3. Translating the test from EasyMock to Mockito, as used in the rest of
   the core package tests.

Change-Id: I924355a495945a063b8e15f233188fc236df2432
Signed-off-by: Allon Mureinik <amure...@redhat.com>
---
M backend/manager/modules/restapi/interface/common/jaxrs/pom.xml
M 
backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/resource/AbstractActionableResource.java
D 
backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/ReapedMap.java
R 
backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/ReapedMapTest.java
4 files changed, 43 insertions(+), 301 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/22/12722/1

diff --git a/backend/manager/modules/restapi/interface/common/jaxrs/pom.xml 
b/backend/manager/modules/restapi/interface/common/jaxrs/pom.xml
index dbc4e95..91f8e05 100644
--- a/backend/manager/modules/restapi/interface/common/jaxrs/pom.xml
+++ b/backend/manager/modules/restapi/interface/common/jaxrs/pom.xml
@@ -15,6 +15,11 @@
   <dependencies>
 
     <dependency>
+      <groupId>org.ovirt.engine.core</groupId>
+      <artifactId>utils</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
       <groupId>org.ovirt.engine.api</groupId>
       <artifactId>restapi-definition</artifactId>
       <version>${project.version}</version>
diff --git 
a/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/resource/AbstractActionableResource.java
 
b/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/resource/AbstractActionableResource.java
index f90e01b..424139c 100644
--- 
a/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/resource/AbstractActionableResource.java
+++ 
b/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/resource/AbstractActionableResource.java
@@ -23,17 +23,17 @@
 import java.util.concurrent.Executor;
 
 import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
 import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
 
 import org.ovirt.engine.api.common.util.LinkHelper;
-import org.ovirt.engine.api.common.util.ReapedMap;
 import org.ovirt.engine.api.common.util.StatusUtils;
 import org.ovirt.engine.api.model.Action;
 import org.ovirt.engine.api.model.BaseResource;
 import org.ovirt.engine.api.model.CreationStatus;
 import org.ovirt.engine.api.model.Fault;
 import org.ovirt.engine.api.resource.ActionResource;
+import org.ovirt.engine.core.utils.ReapedMap;
 
 public abstract class AbstractActionableResource<R extends BaseResource> 
extends AbstractUpdatableResource<R> {
 
@@ -91,6 +91,7 @@
             action.setStatus(StatusUtils.create(CreationStatus.PENDING));
             actions.put(action.getId(), actionResource);
             executor.execute(new Runnable() {
+                @Override
                 public void run() {
                     perform(task);
                     actions.reapable(actionResource.getAction().getId());
@@ -169,6 +170,7 @@
             this.reason = reason;
         }
 
+        @Override
         public void run() {
             try {
                 execute();
@@ -206,6 +208,7 @@
         public DoNothingTask(Action action) {
             super(action);
         }
+        @Override
         public void execute(){
         }
     }
@@ -214,6 +217,7 @@
      * Fallback executor, starts a new thread for each task.
      */
     protected static class SimpleExecutor implements Executor {
+        @Override
         public void execute(Runnable task) {
             new Thread(task).start();
         }
diff --git 
a/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/ReapedMap.java
 
b/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/ReapedMap.java
deleted file mode 100644
index 968acb0..0000000
--- 
a/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/ReapedMap.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
-* Copyright (c) 2010 Red Hat, Inc.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*           http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-package org.ovirt.engine.api.common.util;
-
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.SoftReference;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-
-/**
- * Models a strongly-referenced primary hash map, coupled with a reapable
- * secondary map based on soft-referenced values (rather than keys, as is
- * the case with the java.util.WeakHashMap).
- *
- * Use this like a normal hash map, but when values need no longer be
- * retained they should be marked as reapable so that they are made eligible
- * for garbage collection. Entries are finally evicted if not already GC'd
- * before the expiry of the reapAfter timeout (calculated either from the
- * point at which it was marked reapable or the last time of access).
- * Freeing of the entry prior to this timeout expiring is at the discretion
- * of the garbage collector and depends on whether the JVM is experiencing
- * memory pressure, the type of JVM selected (the client JVM uses much more
- * aggressive GC policies that the server variant) and also the JVM options
- * controlling the heap size.
- *
- * REVISIT: does the world really need yet another hand-rolled cache type?
- * REVISIT: inherited entrySet() etc. don't take account of secondary
- *
- * @param <K> key type
- * @param <V> value type
- */
-public class ReapedMap<K, V> extends HashMap<K, V> {
-
-    // FIXME: I just made up this UID
-    static final long serialVersionUID = 12345678987654321L;
-
-    private static Long DEFAULT_REAP_AFTER = 10 * 60 * 1000L; // 10 minutes
-
-    private long reapAfter;
-    private boolean accessBasedAging;
-    private ReferenceQueue<V> queue;
-
-    // Secondary Map, note:
-    // - keys are strongly referenced, as GC of corresponding values
-    //   will trigger their release
-    // - reap requires a predictable iteration order (based on insertion order)
-    //   hence the use of LinkedHasMap
-    //
-    LinkedHashMap<K, IdAwareReference<K, V>> reapableMap;
-
-    public ReapedMap() {
-        this(DEFAULT_REAP_AFTER);
-    }
-
-    /**
-     * @param reapAfter entries become eligible for reaping after this 
duration (ms)
-     */
-    public ReapedMap(long reapAfter) {
-        this(reapAfter, false);
-    }
-
-    /**
-     * @param reapAfter entries become eligible for reaping after this 
duration (ms)
-     * @param accessBasedAging reset reapAfter timeout on each access
-     */
-    public ReapedMap(long reapAfter, boolean accessBasedAging) {
-        this(reapAfter, accessBasedAging, new ReferenceQueue<V>());
-    }
-
-    /**
-     * Package-protected constructor intended for test use.
-     *
-     * @param reapAfter entries become eligible for reaping after this 
duration (ms)
-     * @param accessBasedAging reset reapAfter timeout on each access
-     * @param queue reference queue to avoid leaked mappings in case where
-     * aggressive GC eats referent before it is reaped
-     */
-    ReapedMap(long reapAfter, boolean accessBasedAging, ReferenceQueue<V> 
queue) {
-        this.reapAfter = reapAfter;
-        this.accessBasedAging = accessBasedAging;
-        this.queue = queue;
-        reapableMap = new LinkedHashMap<K, IdAwareReference<K, V>>();
-    }
-
-    @Override
-    public synchronized V get(Object key) {
-        V ret = super.get(key);
-        if (ret == null) {
-            IdAwareReference<K, V> ref = accessBasedAging ? 
reapableMap.remove(key) : reapableMap.get(key);
-            if (ref != null) {
-                if (ref.isEnqueued()) {
-                    ref.clear();
-                    reapableMap.remove(key);
-                } else {
-                    ret = ref.get();
-                    if (ret == null) {
-                        reapableMap.remove(key);
-                    } else if (accessBasedAging) {
-                        // re-insert on timestamp reset so
-                        // as to maintain insertion order
-                        reapableMap.put(ref.key, ref.reset());
-                    }
-                }
-            }
-        }
-        reap();
-        return ret;
-    }
-
-    @Override
-    public synchronized V put(K k, V v)  {
-        reap();
-        return super.put(k, v);
-    }
-
-    @Override
-    public synchronized V remove(Object key) {
-        V ret = super.remove(key);
-        if (ret == null) {
-            IdAwareReference<K, V> ref = reapableMap.remove(key);
-            if (ref != null) {
-                if (ref.isEnqueued()) {
-                    ref.clear();
-                } else {
-                    ret = ref.get();
-                }
-            }
-        }
-        reap();
-        return ret;
-    }
-
-    @Override
-    public synchronized void clear() {
-        super.clear();
-        reapableMap.clear();
-        while (queue.poll() != null)
-            ;
-    }
-
-    /**
-     * Mark a key as being reapable, caching corresponding soft reference to
-     * corresponding value in the secondary map.
-     *
-     * @param k
-     */
-    public synchronized void reapable(K k) {
-        V v = super.remove(k);
-        if (v != null) {
-            reapableMap.put(k, new IdAwareReference<K, V>(k, v, queue));
-        }
-        reap();
-    }
-
-    /**
-     * @return the size of the secondary map
-     */
-    public synchronized long reapableSize() {
-        return reapableMap.size();
-    }
-
-    /**
-     * Reap <i>before</i> additive operations, <i>after</i> for neutral and
-     * destructive ones.
-     */
-    private synchronized void reap() {
-
-        // reap entries older than age permitted
-        //
-        long now = System.currentTimeMillis();
-        Iterator<Map.Entry<K, IdAwareReference<K, V>>> entries = 
reapableMap.entrySet().iterator();
-        while (entries.hasNext()) {
-            Map.Entry<K, IdAwareReference<K, V>> entry = entries.next();
-            IdAwareReference<K, V> v = entry.getValue();
-            if (now - v.timestamp > reapAfter) {
-                entries.remove();
-                entry.getValue().clear();
-                entry.setValue(null);
-            } else {
-                // guaranteed iteration on insertion order => no older entries
-                //
-                break;
-            }
-        }
-
-        // poll reference queue for GC-pending references to trigger
-        // reaping of referent
-        //
-        Object ref = null;
-        while ((ref = queue.poll()) != null) {
-            @SuppressWarnings("unchecked")
-            IdAwareReference<K, V> value = (IdAwareReference<K, V>)ref;
-            if (value != null) {
-                reapableMap.remove(value.getKey());
-            }
-        }
-    }
-
-    /**
-     * Encapsulate key and timestamp (the latter is used for
-     * eager reaping). The reference queue provides access to
-     * finalizable instances of the reference type, not the
-     * class wrapping it. Hence we must extend SoftReference
-     * as opposed to encapsulating it.
-     */
-    static class IdAwareReference<T, S> extends SoftReference<S> {
-        long timestamp;
-        long last;
-        T key;
-
-        IdAwareReference(T key, S value, ReferenceQueue<S> queue) {
-            super(value, queue);
-            this.key = key;
-            last = timestamp = System.currentTimeMillis();
-        }
-
-        public T getKey() {
-            return key;
-        }
-
-        public boolean equals(Object other) {
-            boolean ret = false;
-            S one = null;
-            ret = other == this
-                  || (other instanceof SoftReference<?>
-                      && (one = get()) != null
-                      && one.equals(((SoftReference<?>)other).get()));
-            return ret;
-        }
-
-        public int hashCode() {
-            S one = get();
-            return one != null ? one.hashCode() : 0;
-        }
-
-        private IdAwareReference<T, S> reset() {
-            last = timestamp;
-            timestamp = System.currentTimeMillis();
-            return this;
-        }
-     }
-}
diff --git 
a/backend/manager/modules/restapi/interface/common/jaxrs/src/test/java/org/ovirt/engine/api/common/util/ReapableMapTest.java
 
b/backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/ReapedMapTest.java
similarity index 72%
rename from 
backend/manager/modules/restapi/interface/common/jaxrs/src/test/java/org/ovirt/engine/api/common/util/ReapableMapTest.java
rename to 
backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/ReapedMapTest.java
index 9e644c5..dc2dad5 100644
--- 
a/backend/manager/modules/restapi/interface/common/jaxrs/src/test/java/org/ovirt/engine/api/common/util/ReapableMapTest.java
+++ 
b/backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/ReapedMapTest.java
@@ -14,33 +14,28 @@
 * limitations under the License.
 */
 
-package org.ovirt.engine.api.common.util;
+package org.ovirt.engine.core.utils;
 
-import static org.easymock.EasyMock.expect;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
 
-import org.easymock.IExpectationSetters;
-import org.easymock.classextension.EasyMock;
-import org.easymock.classextension.IMocksControl;
 import org.junit.Assert;
-import org.junit.Before;
 import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.ovirt.engine.core.utils.ReapedMap.IdAwareReference;
 
 
-public class ReapableMapTest extends Assert {
+public class ReapedMapTest extends Assert {
 
     private static final String[] NUMBERS = { "one", "two", "three", "four", 
"five" };
 
     private static final NumberMapper MAPPER = new NumberMapper();
 
-    private IMocksControl control;
     private ReapedMap<String, Integer> map;
-
-    @Before
-    public void setUp() {
-        control = EasyMock.createNiceControl();
-    }
 
     @Test
     public void testReapingWithoutGC() throws Exception {
@@ -78,8 +73,6 @@
         assertExpected(3);
         assertSizes(1, 1);
         assertNull(map.get("three"));
-
-        control.verify();
     }
 
     @Test
@@ -106,8 +99,6 @@
         assertExpected(2);
         assertSizes(1, 0);
         assertNull(map.get("three"));
-
-        control.verify();
     }
 
     @Test
@@ -121,8 +112,6 @@
         populate(4);
         assertSizes(2, 1);
         assertNull(map.get("three"));
-
-        control.verify();
     }
 
     @Test
@@ -136,36 +125,39 @@
         map.remove("two");
         assertSizes(0, 1);
         assertNull(map.get("three"));
-
-        control.verify();
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    private void setUpGCExpectations(int gcAfter) {
-        ReferenceQueue<Integer> queue = 
(ReferenceQueue<Integer>)control.createMock(ReferenceQueue.class);
+    private void setUpGCExpectations(final int gcAfter) {
+        ReferenceQueue<Integer> queue = mock(ReferenceQueue.class);
         map = new ReapedMap<String, Integer>(10000, false, queue);
-        for (int i = 0 ; i < gcAfter ; i++) {
-            expect(queue.poll()).andReturn(null);
-        }
-        // the gcAfter^th queue poll simulates a GC event and triggers deletion
-        // on the reapable map
-        ReapedMap.IdAwareReference<String, Integer> ref = 
control.createMock(ReapedMap.IdAwareReference.class);
-        // awkward syntax required to work around compilation error
-        // on Reference<capture#nnn ? extends Integer> mismatch
-        ((IExpectationSetters) expect(queue.poll())).andReturn(ref);
-        IExpectationSetters<? extends String> refSetter = expect(ref.getKey());
-        ((IExpectationSetters<String>)refSetter).andReturn("three");
 
-        control.replay();
+        final IdAwareReference ref = mock(IdAwareReference.class);
+        when(ref.getKey()).thenReturn("three", new Object[] { null });
+
+        // the gcAfter queue poll simulates a GC event and triggers deletion
+        // on the reapable map
+        when(queue.poll()).thenAnswer(new Answer<Reference<Integer>>() {
+            private int times = 0;
+
+            @Override
+            public Reference<Integer> answer(InvocationOnMock invocation) 
throws Throwable {
+                if (times == gcAfter) {
+                    ++times;
+                    return ref;
+                }
+
+                ++times;
+                return null;
+            }
+        });
     }
 
     @SuppressWarnings("unchecked")
     private void setUpAccessBaseAgingExpectations() {
-        ReferenceQueue<Integer> queue = 
(ReferenceQueue<Integer>)control.createMock(ReferenceQueue.class);
+        ReferenceQueue<Integer> queue = mock(ReferenceQueue.class);
         map = new ReapedMap<String, Integer>(1000, true, queue);
-        expect(queue.poll()).andReturn(null).anyTimes();
-
-        control.replay();
+        when(queue.poll()).thenReturn(null);
     }
 
     private void populate(Integer ... values) {
@@ -189,5 +181,5 @@
         public String getKey(Integer i) {
             return i <= NUMBERS.length ? NUMBERS[i-1] : null;
         }
-    };
+    }
 }


--
To view, visit http://gerrit.ovirt.org/12722
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I924355a495945a063b8e15f233188fc236df2432
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Allon Mureinik <amure...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to