All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.openjpa.datacache.PartitionedDataCache Maven / Gradle / Ivy

There is a newer version: 4.0.1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.openjpa.datacache;

import java.lang.reflect.Array;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.openjpa.lib.conf.PluginListValue;
import org.apache.openjpa.lib.conf.Value;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.util.UserException;

/**
 * A partitioned data cache maintains a set of partitions that are DataCache themselves.
 * Each of the partitioned DataCaches can be individually configured.
 * However, all partitions must be of the same type. By default, this cache uses
 * {@linkplain ConcurrentDataCache} as its partitions.
 * 
* This cache can be configured as a plug-in as follows: *
* <property name='openjpa.DataCache" * value="partitioned(name=X, PartitionType=concurrent,Partitions='(name=a,cacheSize=100), * (name=b,cacheSize=200)') *
* Notice that the individual partition properties are enclosed parentheses, separated by comma * and finally the whole property string is enclosed in single quote. * Each partition must have a non-empty name that are unique among the partitions. * The {@linkplain CacheDistributionPolicy policy} can return * the name of a partition to distribute the managed instances to be cached in respective partition. * * The above configuration will configure a partitioned cache named X with two partitions named * a and b with cache size 100 and 200 respectively. * Besides the two partitions, this cache instance itself can store data and referred by its own name * (X in the above example). *
* * @author Pinaki Poddar * * @since 2.0.0 */ public class PartitionedDataCache extends ConcurrentDataCache { private static final long serialVersionUID = 1L; private static final Localizer _loc = Localizer.forPackage(PartitionedDataCache.class); private Class _type = ConcurrentDataCache.class; private final List _partProperties = new ArrayList<>(); private final Map _partitions = new HashMap<>(); @Override public void initialize(DataCacheManager mgr) { super.initialize(mgr); for(DataCache part : _partitions.values()){ part.initialize(mgr); } } /** * Sets the type of the partitions. * Each partition is a DataCache itself. * * @param type the name of the type that implements {@linkplain DataCache} interface. * Aliases such as "concurrent" is also recognized. * * @throws Exception if the given type is not resolvable to a loadable type. */ public void setPartitionType(String type) throws Exception { Value value = conf.getValue("DataCache"); ClassLoader ctxLoader = AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction()); ClassLoader loader = conf.getClassResolverInstance().getClassLoader(null, ctxLoader); _type = (Class) AccessController.doPrivileged( J2DoPrivHelper.getForNameAction(value.unalias(type), true, loader)); } /** * Set partitions from a String configuration. * * @param parts a String of the form (p1, p2, p3) where p1, p2 etc. itself are plug-in strings * for individual Data Cache configuration. */ public void setPartitions(String parts) { _partProperties.clear(); parsePartitionProperties(parts); PluginListValue partitions = new PluginListValue("partitions"); String[] types = (String[])Array.newInstance(String.class, _partProperties.size()); Arrays.fill(types, _type.getName()); partitions.setClassNames(types); partitions.setProperties(_partProperties.toArray(new String[_partProperties.size()])); DataCache[] array = (DataCache[])partitions.instantiate(_type, conf); for (DataCache part : array) { if (part.getName() == null) throw new UserException(_loc.get("partition-cache-null-partition", parts)); if (_partitions.containsKey(part.getName())) throw new UserException(_loc.get("partition-cache-duplicate-partition", part.getName(), parts)); if (part.getName().equals(DataCache.NAME_DEFAULT)) throw new UserException(_loc.get("partition-cache-default-partition", part.getName(), parts)); _partitions.put(part.getName(), part); } } /** * Returns the individual partition configuration properties. */ public List getPartitions() { return _partProperties; } @Override public DataCache getPartition(String name, boolean create) { return _partitions.get(name); } /** * Gets the name of the configured partitions. */ @Override public Set getPartitionNames() { return _partitions.keySet(); } /** * Always returns true. */ @Override public final boolean isPartitioned() { return !_partitions.isEmpty(); } @Override public void endConfiguration() { if (!isPartitioned()) conf.getConfigurationLog().warn(_loc.get("partition-cache-no-config")); } /** * Parses property string of the form (p1),(p2),(p3) to produce a list of * p1, p2 and p3. The component strings * p1 etc. must be enclosed in parentheses and separated by comma. * plug-in string to produce a list of * * @param properties property string of the form (p1),(p2),(p3) */ private void parsePartitionProperties(String full) { String properties = new String(full); while (true) { if (properties == null) break; properties = properties.trim(); if (properties.length() == 0) break; if (properties.startsWith(",")) { properties = properties.substring(1); } else if (!_partProperties.isEmpty()) { throw new UserException(_loc.get("partition-cache-parse-error-comma", full, properties)); } if (properties.startsWith("(") && properties.endsWith(")")) { int i = properties.indexOf(")"); String p = properties.substring(1,i); // exclude the end parentheses _partProperties.add(p); if (i < properties.length()-1) { properties = properties.substring(i+1); } else { break; } } else { throw new UserException(_loc.get("partition-cache-parse-error-paren", full, properties)); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy