org/sonews/util/TimeoutMap.java
author cli
Tue Apr 27 22:11:30 2010 +0200 (2010-04-27)
changeset 27 d879bab39600
permissions -rw-r--r--
Fix for #567 "mailinglist gateway does not recover after database outage".
chris@1
     1
/*
chris@1
     2
 *   SONEWS News Server
chris@1
     3
 *   see AUTHORS for the list of contributors
chris@1
     4
 *
chris@1
     5
 *   This program is free software: you can redistribute it and/or modify
chris@1
     6
 *   it under the terms of the GNU General Public License as published by
chris@1
     7
 *   the Free Software Foundation, either version 3 of the License, or
chris@1
     8
 *   (at your option) any later version.
chris@1
     9
 *
chris@1
    10
 *   This program is distributed in the hope that it will be useful,
chris@1
    11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
chris@1
    12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
chris@1
    13
 *   GNU General Public License for more details.
chris@1
    14
 *
chris@1
    15
 *   You should have received a copy of the GNU General Public License
chris@1
    16
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
chris@1
    17
 */
chris@1
    18
chris@1
    19
package org.sonews.util;
chris@1
    20
chris@1
    21
import java.util.HashMap;
chris@1
    22
import java.util.HashSet;
chris@1
    23
import java.util.Map;
chris@1
    24
import java.util.Set;
chris@1
    25
import java.util.concurrent.ConcurrentHashMap;
chris@1
    26
chris@1
    27
/**
chris@1
    28
 * Implementation of a Map that will loose its stored values after a 
chris@1
    29
 * configurable amount of time.
chris@1
    30
 * This class may be used to cache config values for example.
chris@1
    31
 * @author Christian Lins
chris@1
    32
 * @since sonews/0.5.0
chris@1
    33
 */
chris@1
    34
public class TimeoutMap<K,V> extends ConcurrentHashMap<K, V>
chris@1
    35
{
chris@1
    36
  
chris@1
    37
  private static final long serialVersionUID = 453453467700345L;
chris@1
    38
chris@1
    39
  private int                    timeout     = 60000; // 60 sec
chris@1
    40
  private transient Map<K, Long> timeoutMap  = new HashMap<K, Long>();
chris@1
    41
  
chris@1
    42
  /**
chris@1
    43
   * Constructor.
chris@1
    44
   * @param timeout Timeout in milliseconds
chris@1
    45
   */
chris@1
    46
  public TimeoutMap(final int timeout)
chris@1
    47
  {
chris@1
    48
    this.timeout = timeout;
chris@1
    49
  }
chris@1
    50
  
chris@1
    51
  /**
chris@1
    52
   * Uses default timeout (60 sec).
chris@1
    53
   */
chris@1
    54
  public TimeoutMap()
chris@1
    55
  {
chris@1
    56
  }
chris@1
    57
  
chris@1
    58
  /**
chris@1
    59
   * 
chris@1
    60
   * @param key
chris@1
    61
   * @return true if key is still valid.
chris@1
    62
   */
chris@1
    63
  protected boolean checkTimeOut(Object key)
chris@1
    64
  {
chris@1
    65
    synchronized(this.timeoutMap)
chris@1
    66
    {
chris@1
    67
      if(this.timeoutMap.containsKey(key))
chris@1
    68
      {
chris@1
    69
        long keytime = this.timeoutMap.get(key);
chris@1
    70
        if((System.currentTimeMillis() - keytime) < this.timeout)
chris@1
    71
        {
chris@1
    72
          return true;
chris@1
    73
        }
chris@1
    74
        else
chris@1
    75
        {
chris@1
    76
          remove(key);
chris@1
    77
          return false;
chris@1
    78
        }
chris@1
    79
      }
chris@1
    80
      else
chris@1
    81
      {
chris@1
    82
        return false;
chris@1
    83
      }
chris@1
    84
    }
chris@1
    85
  }
chris@1
    86
  
chris@1
    87
  @Override
chris@1
    88
  public boolean containsKey(Object key)
chris@1
    89
  {
chris@1
    90
    return checkTimeOut(key);
chris@1
    91
  }
chris@1
    92
chris@1
    93
  @Override
chris@1
    94
  public synchronized V get(Object key)
chris@1
    95
  {
chris@1
    96
    if(checkTimeOut(key))
chris@1
    97
    {
chris@1
    98
      return super.get(key);
chris@1
    99
    }
chris@1
   100
    else
chris@1
   101
    {
chris@1
   102
      return null;
chris@1
   103
    }
chris@1
   104
  }
chris@1
   105
chris@1
   106
  @Override
chris@1
   107
  public V put(K key, V value)
chris@1
   108
  {
chris@1
   109
    synchronized(this.timeoutMap)
chris@1
   110
    {
chris@1
   111
      removeStaleKeys();
chris@1
   112
      this.timeoutMap.put(key, System.currentTimeMillis());
chris@1
   113
      return super.put(key, value);
chris@1
   114
    }
chris@1
   115
  }
chris@1
   116
chris@1
   117
  /**
chris@1
   118
   * @param arg0
chris@1
   119
   * @return
chris@1
   120
   */
chris@1
   121
  @Override
chris@1
   122
  public V remove(Object arg0)
chris@1
   123
  {
chris@1
   124
    synchronized(this.timeoutMap)
chris@1
   125
    {
chris@1
   126
      this.timeoutMap.remove(arg0);
chris@1
   127
      V val = super.remove(arg0);
chris@1
   128
      return val;
chris@1
   129
    }
chris@1
   130
  }
chris@1
   131
chris@1
   132
  protected void removeStaleKeys()
chris@1
   133
  {
chris@1
   134
    synchronized(this.timeoutMap)
chris@1
   135
    {
chris@1
   136
      Set<Object> keySet = new HashSet<Object>(this.timeoutMap.keySet());
chris@1
   137
      for(Object key : keySet)
chris@1
   138
      {
chris@1
   139
        // The key/value is removed by the checkTimeOut() method if true
chris@1
   140
        checkTimeOut(key);
chris@1
   141
      }
chris@1
   142
    }
chris@1
   143
  }
chris@1
   144
  
chris@1
   145
}