001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    package org.apache.hadoop.util;
019    
020    /**
021     * CacheableIPList loads a list of subnets from a file.
022     * The list is cached and the cache can be refreshed by specifying cache timeout.
023     * A negative value of cache timeout disables any caching.
024     *
025     * Thread safe.
026     */
027    
028    public class CacheableIPList implements IPList {
029      private final long cacheTimeout;
030      private volatile long cacheExpiryTimeStamp;
031      private volatile FileBasedIPList ipList;
032    
033      public CacheableIPList(FileBasedIPList ipList, long cacheTimeout) {
034        this.cacheTimeout =  cacheTimeout;
035        this.ipList = ipList;
036        updateCacheExpiryTime();
037      }
038    
039      /**
040       * Reloads the ip list
041       */
042      private  void  reset() {
043        ipList = ipList.reload();
044        updateCacheExpiryTime();
045      }
046    
047      private void updateCacheExpiryTime() {
048        if (cacheTimeout < 0) {
049          cacheExpiryTimeStamp = -1; // no automatic cache expiry.
050        }else {
051          cacheExpiryTimeStamp = System.currentTimeMillis() + cacheTimeout;
052        }
053      }
054    
055      /**
056       * Refreshes the ip list
057       */
058      public  void refresh () {
059        cacheExpiryTimeStamp = 0;
060      }
061    
062      @Override
063      public boolean isIn(String ipAddress) {
064        //is cache expired
065        //Uses Double Checked Locking using volatile
066        if (cacheExpiryTimeStamp >= 0 && cacheExpiryTimeStamp < System.currentTimeMillis()) {
067          synchronized(this) {
068            //check if cache expired again
069            if (cacheExpiryTimeStamp < System.currentTimeMillis()) {
070              reset();
071            }
072          }
073        }
074        return ipList.isIn(ipAddress);
075      }
076    }