DynamicBloomFilter.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:10k
源码类别:

网格计算

开发平台:

Java

  1. /**
  2.  *
  3.  * Copyright (c) 2005, European Commission project OneLab under contract 034819 (http://www.one-lab.org)
  4.  * All rights reserved.
  5.  * Redistribution and use in source and binary forms, with or 
  6.  * without modification, are permitted provided that the following 
  7.  * conditions are met:
  8.  *  - Redistributions of source code must retain the above copyright 
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  *  - Redistributions in binary form must reproduce the above copyright 
  11.  *    notice, this list of conditions and the following disclaimer in 
  12.  *    the documentation and/or other materials provided with the distribution.
  13.  *  - Neither the name of the University Catholique de Louvain - UCL
  14.  *    nor the names of its contributors may be used to endorse or 
  15.  *    promote products derived from this software without specific prior 
  16.  *    written permission.
  17.  *    
  18.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
  19.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
  20.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
  21.  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
  22.  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
  23.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
  24.  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
  25.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
  26.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  27.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
  28.  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  29.  * POSSIBILITY OF SUCH DAMAGE.
  30.  */
  31. /**
  32.  * Licensed to the Apache Software Foundation (ASF) under one
  33.  * or more contributor license agreements.  See the NOTICE file
  34.  * distributed with this work for additional information
  35.  * regarding copyright ownership.  The ASF licenses this file
  36.  * to you under the Apache License, Version 2.0 (the
  37.  * "License"); you may not use this file except in compliance
  38.  * with the License.  You may obtain a copy of the License at
  39.  *
  40.  *     http://www.apache.org/licenses/LICENSE-2.0
  41.  *
  42.  * Unless required by applicable law or agreed to in writing, software
  43.  * distributed under the License is distributed on an "AS IS" BASIS,
  44.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  45.  * See the License for the specific language governing permissions and
  46.  * limitations under the License.
  47.  */
  48. package org.apache.hadoop.util.bloom;
  49. import java.io.DataInput;
  50. import java.io.DataOutput;
  51. import java.io.IOException;
  52. /**
  53.  * Implements a <i>dynamic Bloom filter</i>, as defined in the INFOCOM 2006 paper.
  54.  * <p>
  55.  * A dynamic Bloom filter (DBF) makes use of a <code>s * m</code> bit matrix but
  56.  * each of the <code>s</code> rows is a standard Bloom filter. The creation 
  57.  * process of a DBF is iterative. At the start, the DBF is a <code>1 * m</code>
  58.  * bit matrix, i.e., it is composed of a single standard Bloom filter.
  59.  * It assumes that <code>n<sub>r</sub></code> elements are recorded in the 
  60.  * initial bit vector, where <code>n<sub>r</sub> <= n</code> (<code>n</code> is
  61.  * the cardinality of the set <code>A</code> to record in the filter).  
  62.  * <p>
  63.  * As the size of <code>A</code> grows during the execution of the application,
  64.  * several keys must be inserted in the DBF.  When inserting a key into the DBF,
  65.  * one must first get an active Bloom filter in the matrix.  A Bloom filter is
  66.  * active when the number of recorded keys, <code>n<sub>r</sub></code>, is 
  67.  * strictly less than the current cardinality of <code>A</code>, <code>n</code>.
  68.  * If an active Bloom filter is found, the key is inserted and 
  69.  * <code>n<sub>r</sub></code> is incremented by one. On the other hand, if there
  70.  * is no active Bloom filter, a new one is created (i.e., a new row is added to
  71.  * the matrix) according to the current size of <code>A</code> and the element
  72.  * is added in this new Bloom filter and the <code>n<sub>r</sub></code> value of
  73.  * this new Bloom filter is set to one.  A given key is said to belong to the
  74.  * DBF if the <code>k</code> positions are set to one in one of the matrix rows.
  75.  * <p>
  76.  * Originally created by
  77.  * <a href="http://www.one-lab.org">European Commission One-Lab Project 034819</a>.
  78.  *
  79.  * @see Filter The general behavior of a filter
  80.  * @see BloomFilter A Bloom filter
  81.  * 
  82.  * @see <a href="http://www.cse.fau.edu/~jie/research/publications/Publication_files/infocom2006.pdf">Theory and Network Applications of Dynamic Bloom Filters</a>
  83.  */
  84. public class DynamicBloomFilter extends Filter {
  85.   /** 
  86.    * Threshold for the maximum number of key to record in a dynamic Bloom filter row.
  87.    */
  88.   private int nr;
  89.   /**
  90.    * The number of keys recorded in the current standard active Bloom filter.
  91.    */
  92.   private int currentNbRecord;
  93.   /**
  94.    * The matrix of Bloom filter.
  95.    */
  96.   private BloomFilter[] matrix;
  97.   /**
  98.    * Zero-args constructor for the serialization.
  99.    */
  100.   public DynamicBloomFilter() { }
  101.   /**
  102.    * Constructor.
  103.    * <p>
  104.    * Builds an empty Dynamic Bloom filter.
  105.    * @param vectorSize The number of bits in the vector.
  106.    * @param nbHash The number of hash function to consider.
  107.    * @param hashType type of the hashing function (see
  108.    * {@link org.apache.hadoop.util.hash.Hash}).
  109.    * @param nr The threshold for the maximum number of keys to record in a
  110.    * dynamic Bloom filter row.
  111.    */
  112.   public DynamicBloomFilter(int vectorSize, int nbHash, int hashType, int nr) {
  113.     super(vectorSize, nbHash, hashType);
  114.     this.nr = nr;
  115.     this.currentNbRecord = 0;
  116.     matrix = new BloomFilter[1];
  117.     matrix[0] = new BloomFilter(this.vectorSize, this.nbHash, this.hashType);
  118.   }
  119.   @Override
  120.   public void add(Key key) {
  121.     if (key == null) {
  122.       throw new NullPointerException("Key can not be null");
  123.     }
  124.     BloomFilter bf = getActiveStandardBF();
  125.     if (bf == null) {
  126.       addRow();
  127.       bf = matrix[matrix.length - 1];
  128.       currentNbRecord = 0;
  129.     }
  130.     bf.add(key);
  131.     currentNbRecord++;
  132.   }
  133.   @Override
  134.   public void and(Filter filter) {
  135.     if (filter == null
  136.         || !(filter instanceof DynamicBloomFilter)
  137.         || filter.vectorSize != this.vectorSize
  138.         || filter.nbHash != this.nbHash) {
  139.       throw new IllegalArgumentException("filters cannot be and-ed");
  140.     }
  141.     DynamicBloomFilter dbf = (DynamicBloomFilter)filter;
  142.     if (dbf.matrix.length != this.matrix.length || dbf.nr != this.nr) {
  143.       throw new IllegalArgumentException("filters cannot be and-ed");
  144.     }
  145.     for (int i = 0; i < matrix.length; i++) {
  146.       matrix[i].and(dbf.matrix[i]);
  147.     }
  148.   }
  149.   @Override
  150.   public boolean membershipTest(Key key) {
  151.     if (key == null) {
  152.       return true;
  153.     }
  154.     for (int i = 0; i < matrix.length; i++) {
  155.       if (matrix[i].membershipTest(key)) {
  156.         return true;
  157.       }
  158.     }
  159.     return false;
  160.   }
  161.   @Override
  162.   public void not() {
  163.     for (int i = 0; i < matrix.length; i++) {
  164.       matrix[i].not();
  165.     }
  166.   }
  167.   @Override
  168.   public void or(Filter filter) {
  169.     if (filter == null
  170.         || !(filter instanceof DynamicBloomFilter)
  171.         || filter.vectorSize != this.vectorSize
  172.         || filter.nbHash != this.nbHash) {
  173.       throw new IllegalArgumentException("filters cannot be or-ed");
  174.     }
  175.     DynamicBloomFilter dbf = (DynamicBloomFilter)filter;
  176.     if (dbf.matrix.length != this.matrix.length || dbf.nr != this.nr) {
  177.       throw new IllegalArgumentException("filters cannot be or-ed");
  178.     }
  179.     for (int i = 0; i < matrix.length; i++) {
  180.       matrix[i].or(dbf.matrix[i]);
  181.     }
  182.   }
  183.   @Override
  184.   public void xor(Filter filter) {
  185.     if (filter == null
  186.         || !(filter instanceof DynamicBloomFilter)
  187.         || filter.vectorSize != this.vectorSize
  188.         || filter.nbHash != this.nbHash) {
  189.       throw new IllegalArgumentException("filters cannot be xor-ed");
  190.     }
  191.     DynamicBloomFilter dbf = (DynamicBloomFilter)filter;
  192.     if (dbf.matrix.length != this.matrix.length || dbf.nr != this.nr) {
  193.       throw new IllegalArgumentException("filters cannot be xor-ed");
  194.     }
  195.     for(int i = 0; i<matrix.length; i++) {
  196.         matrix[i].xor(dbf.matrix[i]);
  197.     }
  198.   }
  199.   @Override
  200.   public String toString() {
  201.     StringBuilder res = new StringBuilder();
  202.     for (int i = 0; i < matrix.length; i++) {
  203.       res.append(matrix[i]);
  204.       res.append(Character.LINE_SEPARATOR);
  205.     }
  206.     return res.toString();
  207.   }
  208.   // Writable
  209.   @Override
  210.   public void write(DataOutput out) throws IOException {
  211.     super.write(out);
  212.     out.writeInt(nr);
  213.     out.writeInt(currentNbRecord);
  214.     out.writeInt(matrix.length);
  215.     for (int i = 0; i < matrix.length; i++) {
  216.       matrix[i].write(out);
  217.     }
  218.   }
  219.   @Override
  220.   public void readFields(DataInput in) throws IOException {
  221.     super.readFields(in);
  222.     nr = in.readInt();
  223.     currentNbRecord = in.readInt();
  224.     int len = in.readInt();
  225.     matrix = new BloomFilter[len];
  226.     for (int i = 0; i < matrix.length; i++) {
  227.       matrix[i] = new BloomFilter();
  228.       matrix[i].readFields(in);
  229.     }
  230.   }
  231.   /**
  232.    * Adds a new row to <i>this</i> dynamic Bloom filter.
  233.    */
  234.   private void addRow() {
  235.     BloomFilter[] tmp = new BloomFilter[matrix.length + 1];
  236.     for (int i = 0; i < matrix.length; i++) {
  237.       tmp[i] = matrix[i];
  238.     }
  239.     tmp[tmp.length-1] = new BloomFilter(vectorSize, nbHash, hashType);
  240.     matrix = tmp;
  241.   }
  242.   /**
  243.    * Returns the active standard Bloom filter in <i>this</i> dynamic Bloom filter.
  244.    * @return BloomFilter The active standard Bloom filter.
  245.    *   <code>Null</code> otherwise.
  246.    */
  247.   private BloomFilter getActiveStandardBF() {
  248.     if (currentNbRecord >= nr) {
  249.       return null;
  250.     }
  251.     return matrix[matrix.length - 1];
  252.   }
  253. }