diff options
author | Alexander Sulfrian <alexander@sulfrian.net> | 2010-06-08 09:01:43 +0200 |
---|---|---|
committer | Alexander Sulfrian <alexander@sulfrian.net> | 2010-06-08 09:01:43 +0200 |
commit | d1fa08fdc9cb11dccee76d668ff85df30458c295 (patch) | |
tree | 1d19df6405103577d872902486792e8c23bce711 /infrastructure/net.appjet.common/util/ExpiringMapping.java | |
parent | d7c5ad7d6263fd1baf9bfdbaa4c50b70ef2fbdb2 (diff) | |
parent | 70d1f9d6fcaefe611e778b8dbf3bafea8934aa08 (diff) | |
download | etherpad-d1fa08fdc9cb11dccee76d668ff85df30458c295.tar.gz etherpad-d1fa08fdc9cb11dccee76d668ff85df30458c295.tar.xz etherpad-d1fa08fdc9cb11dccee76d668ff85df30458c295.zip |
Merge remote branch 'upstream/master'
Conflicts:
etherpad/src/etherpad/control/pro/admin/pro_admin_control.js
etherpad/src/etherpad/control/pro/pro_main_control.js
etherpad/src/etherpad/control/pro_help_control.js
etherpad/src/etherpad/globals.js
etherpad/src/etherpad/legacy_urls.js
etherpad/src/etherpad/pne/pne_utils.js
etherpad/src/etherpad/pro/pro_utils.js
etherpad/src/main.js
etherpad/src/plugins/fileUpload/templates/fileUpload.ejs
etherpad/src/plugins/testplugin/templates/page.ejs
etherpad/src/static/css/pad2_ejs.css
etherpad/src/static/css/pro-help.css
etherpad/src/static/img/jun09/pad/protop.gif
etherpad/src/static/js/store.js
etherpad/src/themes/default/templates/framed/framedheader-pro.ejs
etherpad/src/themes/default/templates/main/home.ejs
etherpad/src/themes/default/templates/pro-help/main.ejs
etherpad/src/themes/default/templates/pro-help/pro-help-template.ejs
infrastructure/com.etherpad/licensing.scala
trunk/etherpad/src/etherpad/collab/ace/contentcollector.js
trunk/etherpad/src/etherpad/collab/ace/linestylefilter.js
trunk/etherpad/src/static/css/home-opensource.css
trunk/etherpad/src/static/js/ace.js
trunk/etherpad/src/static/js/linestylefilter_client.js
trunk/etherpad/src/templates/email/eepnet_license_info.ejs
trunk/etherpad/src/templates/pad/pad_body2.ejs
trunk/etherpad/src/templates/pad/pad_content.ejs
trunk/etherpad/src/templates/pad/padfull_body.ejs
trunk/etherpad/src/templates/pro/admin/pne-license-manager.ejs
Diffstat (limited to 'infrastructure/net.appjet.common/util/ExpiringMapping.java')
-rw-r--r-- | infrastructure/net.appjet.common/util/ExpiringMapping.java | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/infrastructure/net.appjet.common/util/ExpiringMapping.java b/infrastructure/net.appjet.common/util/ExpiringMapping.java new file mode 100644 index 0000000..d4b9d5a --- /dev/null +++ b/infrastructure/net.appjet.common/util/ExpiringMapping.java @@ -0,0 +1,163 @@ +/** + * Copyright 2009 Google 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 net.appjet.common.util; + +import java.util.*; + +// this class is synchronized + +public class ExpiringMapping<K,V> { + + private Map<K,TimeStampedValue> keyToValue = + new HashMap<K,TimeStampedValue>(); + private SortedMap<Long,K> timeToKey= new TreeMap<Long,K>(); + + private long lastTimeStamp = 0; + + private ExpiryPolicy policy; + + public ExpiringMapping(final long maxAgeMillis) { + this(new ExpiryPolicy() { + public boolean hasExpired(long timeStamp, long now, int rank) { + return now - timeStamp > maxAgeMillis; + } + }); + } + + protected ExpiringMapping(ExpiryPolicy policy) { + this.policy = policy; + } + + public synchronized void clear() { + keyToValue.clear(); + timeToKey.clear(); + } + + public synchronized void put(K key, V value) { + TimeStampedValue old = keyToValue.get(key); + if (old != null) { + timeToKey.remove(old.getTimeStamp()); + } + TimeStampedValue newVal = new TimeStampedValue(value); + keyToValue.put(key, newVal); + timeToKey.put(newVal.getTimeStamp(), key); + checkExpiry(); + } + + public synchronized void touch(K key) { + TimeStampedValue old = keyToValue.get(key); + if (old != null) { + put(key, old.getValue()); + } + } + + public synchronized void remove(Object key) { + TimeStampedValue old = keyToValue.get(key); + if (old != null) { + keyToValue.remove(key); + timeToKey.remove(old.getTimeStamp()); + } + } + + // doesn't "touch" key or trigger expiry of expired items + public synchronized V get(Object key) { + if (keyToValue.containsKey(key)) { + return keyToValue.get(key).getValue(); + } else { + return null; + } + } + + public synchronized boolean containsKey(Object key) { + return keyToValue.containsKey(key); + } + + public synchronized void checkExpiry() { + while (timeToKey.size() > 0) { + long oldestTime = timeToKey.firstKey(); + if (hasExpired(oldestTime, timeToKey.size())) { + remove(timeToKey.get(oldestTime)); + } + else { + break; + } + } + } + + // lists keys in time order, oldest to newest + public synchronized List<K> listAllKeys() { + List<K> keyList = new java.util.ArrayList<K>(timeToKey.size()); + for(Map.Entry<Long,K> entry : timeToKey.entrySet()) { + keyList.add(entry.getValue()); + } + return Collections.unmodifiableList(keyList); + } + + // result must be monotonic + private boolean hasExpired(long time, int rank) { + return policy.hasExpired(time, System.currentTimeMillis(), rank); + } + + private long nowTimeStamp() { + // return "now", but unique + long now = System.currentTimeMillis(); + if (now <= lastTimeStamp) { + now = lastTimeStamp+1; + } + lastTimeStamp = now; + return now; + } + + private class TimeStampedValue { + private final V value; + private long timeStamp; + private TimeStampedValue(V value) { + this(value, nowTimeStamp()); + } + private TimeStampedValue(V value, long timeStamp) { + this.value = value; this.timeStamp = timeStamp; + } + public void setTimeStamp(long ts) { + timeStamp = ts; + } + public long getTimeStamp() { + return timeStamp; + } + public V getValue() { + return value; + } + public String toString() { + return "("+value+", "+new Date(timeStamp)+")"; + } + } + + public synchronized String toString() { + return keyToValue.toString(); + } + + protected interface ExpiryPolicy { + // result must be monotonic wrt timeStamp given now + boolean hasExpired(long timeStamp, long now, int rank); + } + +} + + /*private static int compareLongs(long a, long b) { + if (a < b) return -1; + if (a > b) return 1; + return 0; + }*/ |