/* * INESC-ID, Instituto de Engenharia de Sistemas e Computadores Investigação e Desevolvimento em Lisboa * Copyright 2013 INESC-ID and/or its affiliates and other * contributors as indicated by the @author tags. All rights reserved. * See the copyright.txt in the distribution for a full listing of * individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 3.0 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.infinispan.dataplacement.bloomier; import edu.utexas.ece.mpc.bloomier.ImmutableBloomierFilter; import org.infinispan.configuration.cache.Configuration; import org.infinispan.dataplacement.OwnersInfo; import org.infinispan.dataplacement.lookup.ObjectLookup; import org.infinispan.dataplacement.lookup.ObjectLookupFactory; import org.infinispan.util.TypedProperties; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeoutException; /** * An Object Lookup Factory that constructs {@link BloomierFilterObjectLookup} * * This implementation encodes the new owners in a bloomier filter * * @author Pedro Ruivo * @since 5.2 */ public class BloomierFilterObjectLookupFactory implements ObjectLookupFactory { private static final Log log = LogFactory.getLog(BloomierFilterObjectLookupFactory.class); //value size in bits private static final int VALUE_SIZE = 4 * 8; private static final String NUMBER_OF_HASHES = "numberOfHashes"; private static final String TIMEOUT = "timeout"; private int numberOfHashes = 10; private int timeout = 10000; @Override public void setConfiguration(Configuration configuration) { TypedProperties typedProperties = configuration.dataPlacement().properties(); numberOfHashes = getIntProperty(typedProperties, NUMBER_OF_HASHES, numberOfHashes); timeout = getIntProperty(typedProperties, TIMEOUT, timeout); } @SuppressWarnings("unchecked") @Override public ObjectLookup createObjectLookup(Map<Object, OwnersInfo> keysToMove, int numberOfOwners) { ImmutableBloomierFilter[] bloomierFilters = new ImmutableBloomierFilter[numberOfOwners]; for (int i = 0; i < numberOfOwners; ++i) { Map<Object, Integer> map = split(keysToMove, i); try { bloomierFilters[i] = createBloomierFilter(map); } catch (TimeoutException e) { return null; } } return new BloomierFilterObjectLookup(bloomierFilters); } @Override public void init(ObjectLookup objectLookup) { //no-op } @Override public int getNumberOfQueryProfilingPhases() { return 1; } private Map<Object, Integer> split(Map<Object, OwnersInfo> keysToMove, int iteration) { Map<Object, Integer> map = new HashMap<Object, Integer>(); for (Map.Entry<Object, OwnersInfo> entry : keysToMove.entrySet()) { map.put(entry.getKey(), entry.getValue().getOwner(iteration)); } return map; } private ImmutableBloomierFilter<Object, Integer> createBloomierFilter(Map<Object, Integer> newOwners) throws TimeoutException { int numberOfKeys = newOwners.size() * 4; return new ImmutableBloomierFilter<Object, Integer>(newOwners, numberOfKeys, numberOfHashes, VALUE_SIZE, Integer.class, timeout); } private int getIntProperty(TypedProperties properties, String propertyName, int defaultValue) { try { String tmp = properties.getProperty(propertyName, Integer.toString(defaultValue)); return Integer.parseInt(tmp); } catch (NumberFormatException nfe) { log.warnf("Error parsing parsing property %s. The default value is %s. %s", propertyName, defaultValue, nfe.getMessage()); } return defaultValue; } }