Return-Path: Delivered-To: apmail-openjpa-dev-archive@www.apache.org Received: (qmail 76158 invoked from network); 23 Sep 2008 19:39:13 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 23 Sep 2008 19:39:13 -0000 Received: (qmail 83249 invoked by uid 500); 23 Sep 2008 19:39:10 -0000 Delivered-To: apmail-openjpa-dev-archive@openjpa.apache.org Received: (qmail 83224 invoked by uid 500); 23 Sep 2008 19:39:10 -0000 Mailing-List: contact dev-help@openjpa.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@openjpa.apache.org Delivered-To: mailing list dev@openjpa.apache.org Received: (qmail 83213 invoked by uid 99); 23 Sep 2008 19:39:10 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 23 Sep 2008 12:39:10 -0700 X-ASF-Spam-Status: No, hits=2.0 required=10.0 tests=HTML_MESSAGE,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of kwsutter@gmail.com designates 74.125.46.30 as permitted sender) Received: from [74.125.46.30] (HELO yw-out-2324.google.com) (74.125.46.30) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 23 Sep 2008 19:38:11 +0000 Received: by yw-out-2324.google.com with SMTP id 5so334450ywh.63 for ; Tue, 23 Sep 2008 12:38:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to :subject:mime-version:content-type; bh=MRrNifYvzXFDd2VBVNCWHt7V+IRwiInJycCwMMA8DZg=; b=SDCHNmhMNRhp/oz0/8htHSphfdtHWfnXUVLy2EFxTnCTidcCNF/XVtHPBmDHEBfouV AiG2AYnSfPmsQtTs8YKD+pyqN+R5b2oqOKbai2/HCLVC4iSLR3bW5TSWVUCNG9xv3vGk cWwrXqBFOdglkIk4JWSXX2veBBvizNG3MfjWo= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:mime-version:content-type; b=mU+Q9CjeQY6O+TlQRec3oEYaFX9HuKeGTl8lOHDzIQ+tCL5twllYoM8rT2nyFvuLgJ tcWLIz0bM0v/RyqcVT6sTIaF1ppdnnHutK5c72LhZaP1ADRMLyGNoSIsIfEkjDGFd+LI f5ETd/LIK8+eyVfNXPomoRnbDlH0VGAV8QkEE= Received: by 10.142.12.14 with SMTP id 14mr2161120wfl.182.1222198722638; Tue, 23 Sep 2008 12:38:42 -0700 (PDT) Received: by 10.142.144.1 with HTTP; Tue, 23 Sep 2008 12:38:42 -0700 (PDT) Message-ID: <89c0c52c0809231238i1157d671j7e1de5269b4ae4c2@mail.gmail.com> Date: Tue, 23 Sep 2008 14:38:42 -0500 From: "Kevin Sutter" To: dev@openjpa.apache.org Subject: Re: svn commit: r698284 - in /openjpa/trunk: openjpa-kernel/src/main/java/org/apache/openjpa/meta/ openjpa-persistence/src/main/java/org/apache/openjpa/persistence/ openjpa-slice/src/main/java/org/apache/openjpa/slice/ openjpa-slice/src/main/java/org MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_Part_80412_3904327.1222198722626" X-Virus-Checked: Checked by ClamAV on apache.org ------=_Part_80412_3904327.1222198722626 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline Pinaki, I know I'm being a pain in the butt... But, wouldn't these changes also require doc updates? ;-) Thanks, Kevin On Tue, Sep 23, 2008 at 1:58 PM, wrote: > Author: ppoddar > Date: Tue Sep 23 11:58:00 2008 > New Revision: 698284 > > URL: http://svn.apache.org/viewvc?rev=698284&view=rev > Log: > Introduces notion of @Replicated entity. This feature allows to relax > collocation constraint for quasi-stationary master data. A replicated entity > is stored as identical copies across multiple slices. The > ReplicationStrategy works similar to DistributionStrategy for replicated > entity. The slice association cardinality has uniformly changed to array of > slices from a single slice name both for replicated and non-replicated > entity. The non-replicated entities can refer to replicated entities but not > vice versa. The query operation (especially the ones with aggregate > function) is aware of replicated data and queries only one of the slices to > avoid duplication. > > Added: > > openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/Replicated.java > > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ReplicationPolicy.java > > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SliceImplHelper.java > > openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Country.java > Modified: > > openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java > > openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java > > openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java > > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedBrokerImpl.java > > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedConfiguration.java > > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributionPolicy.java > > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ProductDerivation.java > > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SlicePersistence.java > > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedJDBCConfigurationImpl.java > > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreManager.java > > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreQuery.java > > openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Address.java > > openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestBasic.java > openjpa/trunk/openjpa-slice/src/test/resources/META-INF/persistence.xml > > Modified: > openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java?rev=698284&r1=698283&r2=698284&view=diff > > ============================================================================== > --- > openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java > (original) > +++ > openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java > Tue Sep 23 11:58:00 2008 > @@ -164,7 +164,8 @@ > private int _identity = ID_UNKNOWN; > private int _idStrategy = ValueStrategies.NONE; > private int _accessType = ACCESS_UNKNOWN; > - > + private boolean _replicated = false; > + > private String _seqName = DEFAULT_STRING; > private SequenceMetaData _seqMeta = null; > private String _cacheName = DEFAULT_STRING; > @@ -2401,4 +2402,20 @@ > Collections.sort(result); > return result.toArray(new String[result.size()]); > } > + > + /** > + * Affirms the persistence instances of this receiver is replicated > across > + * multiple databases. > + */ > + public boolean isReplicated() { > + return _replicated; > + } > + > + /** > + * Sets the persistence instances of this receiver to be replicated > across > + * multiple databases. > + */ > + public void setReplicated(boolean flag) { > + _replicated = flag; > + } > } > > Modified: > openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java?rev=698284&r1=698283&r2=698284&view=diff > > ============================================================================== > --- > openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java > (original) > +++ > openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java > Tue Sep 23 11:58:00 2008 > @@ -175,6 +175,7 @@ > _tags.put(ManagedInterface.class, MANAGED_INTERFACE); > _tags.put(ReadOnly.class, READ_ONLY); > _tags.put(Type.class, TYPE); > + _tags.put(Replicated.class, REPLICATED); > } > > private final OpenJPAConfiguration _conf; > @@ -577,6 +578,9 @@ > if (isMetaDataMode()) > parseManagedInterface(meta, (ManagedInterface) > anno); > break; > + case REPLICATED: > + meta.setReplicated(true); > + break; > default: > throw new UnsupportedException(_loc.get("unsupported", > _cls, > anno.toString())); > > Modified: > openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java?rev=698284&r1=698283&r2=698284&view=diff > > ============================================================================== > --- > openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java > (original) > +++ > openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java > Tue Sep 23 11:58:00 2008 > @@ -80,4 +80,5 @@ > MANAGED_INTERFACE, > READ_ONLY, > TYPE, > + REPLICATED > } > > Added: > openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/Replicated.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/Replicated.java?rev=698284&view=auto > > ============================================================================== > --- > openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/Replicated.java > (added) > +++ > openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/Replicated.java > Tue Sep 23 11:58:00 2008 > @@ -0,0 +1,44 @@ > +/* > + * 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.persistence; > + > +import static java.lang.annotation.ElementType.TYPE; > +import static java.lang.annotation.RetentionPolicy.RUNTIME; > + > +import java.lang.annotation.Retention; > +import java.lang.annotation.Target; > + > +/** > + * Annotation to specify the instance of the annotated entity be > + * replicated across more than one slices. The actual slices > where an > + * instance of the annotated entity will be replicated is determined by > + * the return value of user-specified > + * {@link ReplicationPolicy#replicate(Object, java.util.List, Object)} > + * method. > + * > + * @see ReplicationPolicy > + * > + * @author Pinaki Poddar > + * > + */ > +@Target({ TYPE }) > +@Retention(RUNTIME) > +public @interface Replicated { > + > +} > > Modified: > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedBrokerImpl.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedBrokerImpl.java?rev=698284&r1=698283&r2=698284&view=diff > > ============================================================================== > --- > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedBrokerImpl.java > (original) > +++ > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedBrokerImpl.java > Tue Sep 23 11:58:00 2008 > @@ -22,7 +22,6 @@ > import org.apache.openjpa.kernel.OpCallbacks; > import org.apache.openjpa.kernel.OpenJPAStateManager; > import org.apache.openjpa.lib.util.Localizer; > -import org.apache.openjpa.util.UserException; > > /** > * A specialized Broker to associate slice identifiers with the > StateManagers as > @@ -36,11 +35,17 @@ > */ > @SuppressWarnings("serial") > public class DistributedBrokerImpl extends FinalizingBrokerImpl { > - private transient String slice; > - > + private transient String _rootSlice; > + private transient DistributedConfiguration _conf; > private static final Localizer _loc = > Localizer.forPackage(DistributedBrokerImpl.class); > > + public DistributedConfiguration getConfiguration() { > + if (_conf == null) { > + _conf = (DistributedConfiguration)super.getConfiguration(); > + } > + return _conf; > + } > /** > * Assigns slice identifier to the resultant StateManager as > initialized by > * the super class implementation. The slice identifier is decided > by > @@ -54,32 +59,28 @@ > public OpenJPAStateManager persist(Object pc, Object id, boolean > explicit, > OpCallbacks call) { > OpenJPAStateManager sm = getStateManager(pc); > + String[] targets = null; > + boolean replicated = SliceImplHelper.isReplicated(sm); > if (getOperatingSet().isEmpty() > - && (sm == null || sm.getImplData() == > null)) { > - slice = getSlice(pc); > + && (sm == null || sm.getImplData() == null)) { > + targets = SliceImplHelper.getSlicesByPolicy(pc, > getConfiguration(), > + this); > + if (!replicated) { > + _rootSlice = targets[0]; > + } > } > sm = super.persist(pc, id, explicit, call); > - if (sm.getImplData() == null) > - sm.setImplData(slice, true); > - > + if (sm.getImplData() == null) { > + if (targets == null) { > + targets = replicated > + ? SliceImplHelper.getSlicesByPolicy(pc, > getConfiguration(), this) > + : new String[]{_rootSlice}; > + } > + sm.setImplData(targets, true); > + } > return sm; > } > > - /** > - * Gets the slice by the user-defined distribution policy. > - */ > - String getSlice(Object pc) { > - DistributedConfiguration conf = > - (DistributedConfiguration) > getConfiguration(); > - String slice = > - > (conf.getDistributionPolicyInstance().distribute(pc, conf > - .getActiveSliceNames(), > this)); > - if (!conf.getActiveSliceNames().contains(slice)) > - throw new > UserException(_loc.get("bad-policy-slice", new Object[] { > - > conf.getDistributionPolicyInstance().getClass().getName(), > - slice, pc, > conf.getActiveSliceNames() })); > - return slice; > - } > > @Override > public boolean endOperation() { > > Modified: > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedConfiguration.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedConfiguration.java?rev=698284&r1=698283&r2=698284&view=diff > > ============================================================================== > --- > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedConfiguration.java > (original) > +++ > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedConfiguration.java > Tue Sep 23 11:58:00 2008 > @@ -75,4 +75,10 @@ > * the available slices. > */ > DistributionPolicy getDistributionPolicyInstance(); > + > + /** > + * Gets the policy that governs how new replicated instances will > be > + * replicated across the available slices. > + */ > + ReplicationPolicy getReplicationPolicyInstance(); > } > > Modified: > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributionPolicy.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributionPolicy.java?rev=698284&r1=698283&r2=698284&view=diff > > ============================================================================== > --- > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributionPolicy.java > (original) > +++ > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributionPolicy.java > Tue Sep 23 11:58:00 2008 > @@ -19,6 +19,7 @@ > package org.apache.openjpa.slice; > > import java.util.List; > +import java.util.Random; > > > /** > @@ -44,4 +45,16 @@ > * @see DistributedConfiguration#getActiveSliceNames() > */ > String distribute(Object pc, List slices, Object context); > + > + /** > + * Implements a default distribution policy to store the given > + * instance to a randomly selected available slice. > + * > + */ > + public static class Default implements DistributionPolicy { > + private static Random RNG = new Random(); > + public String distribute(Object pc, List slices, > Object ctx) { > + return slices.get(RNG.nextInt(slices.size())); > + } > + } > } > > Modified: > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ProductDerivation.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ProductDerivation.java?rev=698284&r1=698283&r2=698284&view=diff > > ============================================================================== > --- > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ProductDerivation.java > (original) > +++ > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ProductDerivation.java > Tue Sep 23 11:58:00 2008 > @@ -22,7 +22,9 @@ > > import org.apache.openjpa.conf.OpenJPAProductDerivation; > import org.apache.openjpa.lib.conf.AbstractProductDerivation; > +import org.apache.openjpa.lib.conf.Configuration; > import org.apache.openjpa.slice.jdbc.DistributedJDBCBrokerFactory; > +import org.apache.openjpa.slice.jdbc.DistributedJDBCConfigurationImpl; > > /** > * Derives configuration for Slice. > @@ -58,6 +60,28 @@ > } > > public int getType() { > - return TYPE_FEATURE; > + return TYPE_STORE; > } > + > + /** > + * Sets the {@link DistributionPolicy} and {@link > ReplicationPolicy} to > + * their respective defaults if not set by the user. > + */ > + @Override > + public boolean afterSpecificationSet(Configuration c) { > + if (!(c instanceof DistributedJDBCConfigurationImpl)) > + return false; > + DistributedJDBCConfigurationImpl conf = > + (DistributedJDBCConfigurationImpl)c; > + boolean modified = false; > + if (conf.getDistributionPolicyInstance() == null) { > + conf.distributionPolicyPlugin.setString("random"); > + modified = true; > + } > + if (conf.getReplicationPolicyInstance() == null) { > + conf.replicationPolicyPlugin.setString("all"); > + modified = true; > + } > + return modified; > + } > } > > Added: > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ReplicationPolicy.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ReplicationPolicy.java?rev=698284&view=auto > > ============================================================================== > --- > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ReplicationPolicy.java > (added) > +++ > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ReplicationPolicy.java > Tue Sep 23 11:58:00 2008 > @@ -0,0 +1,60 @@ > +/* > + * 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.slice; > + > +import java.util.List; > + > + > +/** > + * Policy to select one of the physical databases referred as > slice > + * in which a given persistent instance will be replicated. > + * > + * @author Pinaki Poddar > + * > + */ > +public interface ReplicationPolicy { > + /** > + * Gets the name of the slices where a given instance will be > replicated. > + * > + * @param pc The newly persistent or to-be-merged object. > + * @param slices list of names of the active slices. The ordering > of > + * the list is either explicit openjpa.slice.Names > property > + * or implicit i.e. alphabetic order of available identifiers if > + * openjpa.slice.Names is unspecified. > + * @param context generic persistence context managing the given > instance. > + * > + * @return identifier of the slices. This names must match one of > the > + * given slice names. Return null or empty list to imply all active > slices. > + * > + * @see DistributedConfiguration#getActiveSliceNames() > + */ > + String[] replicate(Object pc, List slices, Object context); > + > + /** > + * Implements a default replication policy to replicate the given > + * instance across all available slices. > + * > + */ > + public static class Default implements ReplicationPolicy { > + public String[] replicate(Object pc, List slices, > + Object context) { > + return null; > + } > + } > +} > > Added: > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SliceImplHelper.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SliceImplHelper.java?rev=698284&view=auto > > ============================================================================== > --- > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SliceImplHelper.java > (added) > +++ > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SliceImplHelper.java > Tue Sep 23 11:58:00 2008 > @@ -0,0 +1,88 @@ > +/* > + * 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.slice; > + > +import java.util.List; > + > +import org.apache.openjpa.conf.OpenJPAConfiguration; > +import org.apache.openjpa.kernel.OpenJPAStateManager; > +import org.apache.openjpa.lib.util.Localizer; > +import org.apache.openjpa.meta.ClassMetaData; > +import org.apache.openjpa.util.UserException; > + > +/** > + * Utility methods to determine the target slices for a persistence > capable > + * instance by calling back to user-specified distribution policy. > + * > + * @author Pinaki Poddar > + * > + */ > +public class SliceImplHelper { > + private static final Localizer _loc = > + Localizer.forPackage(SliceImplHelper.class); > + > + /** > + * Gets the target slices by calling user-specified > + * {@link DistributionPolicy} or {@link ReplicationPolicy} > + * depending on whether the given instance is {@link Replicated > replicated}. > + */ > + public static String[] getSlicesByPolicy(Object pc, > + DistributedConfiguration conf, Object ctx) { > + List availables = conf.getActiveSliceNames(); > + Object policy = null; > + String[] targets = null; > + if (isReplicated(pc, conf)) { > + policy = conf.getReplicationPolicyInstance(); > + targets = ((ReplicationPolicy)policy).replicate > + (pc, availables, ctx); > + if (targets == null || targets.length == 0) > + targets = availables.toArray(new > String[availables.size()]); > + } else { > + policy = conf.getDistributionPolicyInstance(); > + String slice = > ((DistributionPolicy)policy).distribute > + (pc, availables, ctx); > + targets = new String[]{slice}; > + } > + for (String target : targets) > + if (!availables.contains(target)) > + throw new > UserException(_loc.get("bad-policy-slice", new Object[] { > + policy.getClass().getName(), > target, pc, availables})); > + return targets; > + } > + > + /** > + * Affirms if the given instance be replicated to multiple slices. > + */ > + public static boolean isReplicated(Object pc, OpenJPAConfiguration > conf) { > + if (pc == null) > + return false; > + ClassMetaData meta = conf.getMetaDataRepositoryInstance() > + .getMetaData(pc.getClass(), null, false); > + return (meta == null) ? false : meta.isReplicated(); > + } > + > + /** > + * Affirms if the given instance be replicated to multiple slices. > + */ > + public static boolean isReplicated(OpenJPAStateManager sm) { > + if (sm == null) > + return false; > + return sm.getMetaData().isReplicated(); > + } > +} > > Modified: > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SlicePersistence.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SlicePersistence.java?rev=698284&r1=698283&r2=698284&view=diff > > ============================================================================== > --- > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SlicePersistence.java > (original) > +++ > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SlicePersistence.java > Tue Sep 23 11:58:00 2008 > @@ -18,6 +18,8 @@ > */ > package org.apache.openjpa.slice; > > +import java.util.Arrays; > + > import org.apache.openjpa.enhance.PersistenceCapable; > import org.apache.openjpa.kernel.StateManagerImpl; > import org.apache.openjpa.util.ImplHelper; > @@ -32,6 +34,8 @@ > /** > * Get the slice identifier for the given instance if it is a > managed > * instance and has been assigned to a slice. > + * If the given instance is replicated across multiple slices then > returns > + * comma-separated list of slice names. > * > * @return name of the slice, if any. null otherwise. > */ > @@ -45,6 +49,13 @@ > if (sm == null) > return null; > Object slice = sm.getImplData(); > - return (slice instanceof String) ? (String)slice : null; > + if (slice instanceof String[]) { > + if (((String[])slice).length == 1) { > + return ((String[])slice)[0]; > + } else { > + return Arrays.toString(((String[])slice)); > + } > + } > + return null; > } > } > > Modified: > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedJDBCConfigurationImpl.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedJDBCConfigurationImpl.java?rev=698284&r1=698283&r2=698284&view=diff > > ============================================================================== > --- > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedJDBCConfigurationImpl.java > (original) > +++ > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedJDBCConfigurationImpl.java > Tue Sep 23 11:58:00 2008 > @@ -49,6 +49,7 @@ > import org.apache.openjpa.slice.DistributionPolicy; > import org.apache.openjpa.slice.ExecutorServiceValue; > import org.apache.openjpa.slice.ProductDerivation; > +import org.apache.openjpa.slice.ReplicationPolicy; > import org.apache.openjpa.slice.Slice; > import org.apache.openjpa.util.UserException; > > @@ -73,11 +74,13 @@ > protected StringValue masterPlugin; > protected StringListValue namesPlugin; > protected ExecutorServiceValue executorServicePlugin; > - protected PluginValue distributionPolicyPlugin; > + public PluginValue distributionPolicyPlugin; > + public PluginValue replicationPolicyPlugin; > > public static final String DOT = "."; > public static final String REGEX_DOT = "\\."; > - public static final String PREFIX_SLICE = > ProductDerivation.PREFIX_SLICE + DOT; > + public static final String PREFIX_SLICE = > ProductDerivation.PREFIX_SLICE + > + DOT; > public static final String PREFIX_OPENJPA = "openjpa."; > private static Localizer _loc = > Localizer.forPackage(DistributedJDBCConfigurationImpl.class); > @@ -95,8 +98,18 @@ > brokerPlugin.setString(DistributedBrokerImpl.class.getName()); > > distributionPolicyPlugin = addPlugin("DistributionPolicy", true); > + distributionPolicyPlugin.setAlias("random", > + DistributionPolicy.Default.class.getName()); > + distributionPolicyPlugin.setDefault("random"); > distributionPolicyPlugin.setDynamic(true); > > + replicationPolicyPlugin = addPlugin > + ("ReplicatedDistributionPolicy", true); > + replicationPolicyPlugin.setAlias("all", > + ReplicationPolicy.Default.class.getName()); > + replicationPolicyPlugin.setDefault("all"); > + replicationPolicyPlugin.setDynamic(true); > + > lenientPlugin = addBoolean("Lenient"); > > masterPlugin = addString("Master"); > @@ -185,6 +198,18 @@ > } > > public void setDistributionPolicyInstance(String val) { > + replicationPolicyPlugin.set(val); > + } > + > + public ReplicationPolicy getReplicationPolicyInstance() { > + if (replicationPolicyPlugin.get() == null) { > + > replicationPolicyPlugin.instantiate(ReplicationPolicy.class, > + this, true); > + } > + return (ReplicationPolicy) replicationPolicyPlugin.get(); > + } > + > + public void setReplicatedDistributionPolicyInstance(String val) { > distributionPolicyPlugin.set(val); > } > > > Modified: > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreManager.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreManager.java?rev=698284&r1=698283&r2=698284&view=diff > > ============================================================================== > --- > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreManager.java > (original) > +++ > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreManager.java > Tue Sep 23 11:58:00 2008 > @@ -18,6 +18,7 @@ > */ > package org.apache.openjpa.slice.jdbc; > > +import java.io.IOException; > import java.sql.Connection; > import java.sql.SQLException; > import java.util.ArrayList; > @@ -42,6 +43,7 @@ > import org.apache.openjpa.kernel.FetchConfiguration; > import org.apache.openjpa.kernel.OpenJPAStateManager; > import org.apache.openjpa.kernel.PCState; > +import org.apache.openjpa.kernel.QueryContext; > import org.apache.openjpa.kernel.QueryLanguages; > import org.apache.openjpa.kernel.Seq; > import org.apache.openjpa.kernel.StoreContext; > @@ -54,10 +56,15 @@ > import org.apache.openjpa.meta.ClassMetaData; > import org.apache.openjpa.meta.FieldMetaData; > import org.apache.openjpa.slice.DistributionPolicy; > +import org.apache.openjpa.slice.SliceImplHelper; > import org.apache.openjpa.slice.ProductDerivation; > +import org.apache.openjpa.slice.ReplicationPolicy; > import org.apache.openjpa.util.InternalException; > import org.apache.openjpa.util.StoreException; > import org.apache.openjpa.util.UserException; > +import org.apache.tools.ant.taskdefs.condition.IsReference; > + > +import sun.reflect.ReflectionFactory.GetReflectionFactoryAction; > > /** > * A Store manager for multiple physical databases referred as > slice. > @@ -109,71 +116,70 @@ > > /** > * Decides the index of the StoreManager by first looking at the > - * implementation data. If not found then {@link DistributionPolicy > - * DistributionPolicy} determines the target store for new instances > and > - * additional connection info is used to estimate for the existing > - * instances. > + * implementation data. If no implementation data is found, then > estimates > + * targets slices by using additional connection info. If no > additional > + * connection info then calls back to user-defined policy. > */ > - protected String findSliceName(OpenJPAStateManager sm, Object info) { > - boolean hasIndex = hasSlice(sm); > - if (hasIndex) > - return sm.getImplData().toString(); > - String slice = estimateSlice(sm, info); > - if (slice == null) > + protected String[] findSliceNames(OpenJPAStateManager sm, Object info) > { > + boolean hasImplData = sm.getImplData() != null; > + if (hasImplData) > + return (String[])sm.getImplData(); > + String[] targets = estimateSlice(sm, info); > + if (targets == null) > return assignSlice(sm); > - return slice; > - } > - > - private boolean hasSlice(OpenJPAStateManager sm) { > - return sm.getImplData() != null; > + return targets; > } > - > - private String assignSlice(OpenJPAStateManager sm) { > - Object pc = sm.getPersistenceCapable(); > - DistributionPolicy policy = _conf.getDistributionPolicyInstance(); > - List sliceNames = _conf.getActiveSliceNames(); > - String slice =policy.distribute(pc, sliceNames, getContext()); > - if (!sliceNames.contains(slice)) { > - throw new UserException(_loc.get("bad-policy-slice", new > Object[] { > - policy.getClass().getName(), slice, pc, sliceNames > })); > - } > - sm.setImplData(slice, true); > - return slice; > + > + private String[] assignSlice(OpenJPAStateManager sm) { > + Object pc = sm.getPersistenceCapable(); > + String[] targets = SliceImplHelper.getSlicesByPolicy(pc, _conf, > + getContext()); > + sm.setImplData(targets, true); > + return targets; > } > - > + > /** > * The additional edata is used, if possible, to find the StoreManager > * managing the given StateManager. If the additional data is > unavailable > * then return null. > * > */ > - private String estimateSlice(OpenJPAStateManager sm, Object edata) { > + private String[] estimateSlice(OpenJPAStateManager sm, Object edata) { > if (edata == null || !(edata instanceof ConnectionInfo)) > return null; > > + List temps = null; > Result result = ((ConnectionInfo) edata).result; > if (result instanceof ResultSetResult) { > JDBCStore store = ((ResultSetResult) result).getStore(); > for (SliceStoreManager slice : _slices) { > if (slice == store) { > - String sliceId = slice.getName(); > - sm.setImplData(sliceId, true); > - return sliceId; > + if (temps == null) > + temps = new ArrayList(); > + temps.add(slice.getName()); > } > } > } > - return null; > + if (temps != null) { > + String[] targets = temps.toArray(new String[temps.size()]); > + sm.setImplData(targets, true); > + return targets; > + } > + return null; > } > > /** > - * Selects a child StoreManager where the given instance resides. > + * Selects child StoreManager(s) where the given instance resides. > */ > private StoreManager selectStore(OpenJPAStateManager sm, Object edata) > { > - String name = findSliceName(sm, edata); > - SliceStoreManager slice = lookup(name); > - if (slice == null) > - throw new InternalException(_loc.get("wrong-slice", name, > sm)); > - return slice; > + String[] targets = findSliceNames(sm, edata); > + for (String target : targets) { > + SliceStoreManager slice = lookup(target); > + if (slice == null) > + throw new InternalException(_loc.get("wrong-slice", > target, sm)); > + return slice; > + } > + return null; > } > > public boolean assignField(OpenJPAStateManager sm, int field, > @@ -222,13 +228,16 @@ > } > > public boolean exists(OpenJPAStateManager sm, Object edata) { > + List targets = null; > for (SliceStoreManager slice : _slices) { > if (slice.exists(sm, edata)) { > - sm.setImplData(slice.getName(), true); > - return true; > + if (targets == null) > + targets.add(slice.getName()); > } > } > - return false; > + if (targets != null) > + sm.setImplData(targets.toArray(new String[targets.size()]), > true); > + return targets != null; > } > > > @@ -244,7 +253,11 @@ > List subset = > subsets.get(slice.getName()); > if (subset.isEmpty()) > continue; > - futures.add(threadPool.submit(new Flusher(slice, subset))); > + if (containsReplicated(subset)) { > + slice.flush(subset); > + } else { > + futures.add(threadPool.submit(new Flusher(slice, subset))); > + } > } > for (Future future : futures) { > Collection error; > @@ -262,12 +275,16 @@ > return exceptions; > } > > + boolean containsReplicated(List sms) { > + for (OpenJPAStateManager sm : sms) > + if (sm.getMetaData().isReplicated()) > + return true; > + return false; > + } > + > /** > * Separate the given list of StateManagers in separate lists for each > slice > * by the associated slice identifier of each StateManager. > - * @param sms > - * @param edata > - * @return > */ > private Map> bin( > Collection/**/ sms, Object edata) { > @@ -277,8 +294,10 @@ > subsets.put(slice.getName(), new > ArrayList()); > for (Object x : sms) { > OpenJPAStateManager sm = (OpenJPAStateManager) x; > - String slice = findSliceName(sm, edata); > - subsets.get(slice).add(sm); > + String[] targets = findSliceNames(sm, edata); > + for (String slice : targets) { > + subsets.get(slice).add(sm); > + } > } > return subsets; > } > @@ -306,15 +325,15 @@ > public boolean initialize(OpenJPAStateManager sm, PCState state, > FetchConfiguration fetch, Object edata) { > if (edata instanceof ConnectionInfo) { > - String slice = findSliceName(sm, (ConnectionInfo) edata); > - if (slice != null) > - return lookup(slice).initialize(sm, state, fetch, edata); > + String[] targets = findSliceNames(sm, (ConnectionInfo) edata); > + if (targets != null || targets.length > 0) > + return lookup(targets[0]).initialize(sm, state, fetch, > edata); > } > // not a part of Query result load. Look into the slices till found > List targets = getTargets(fetch); > for (SliceStoreManager slice : targets) { > if (slice.initialize(sm, state, fetch, edata)) { > - sm.setImplData(slice.getName(), true); > + sm.setImplData(new String[]{slice.getName()}, true); > return true; > } > } > @@ -381,7 +400,13 @@ > } > > public boolean syncVersion(OpenJPAStateManager sm, Object edata) { > - return selectStore(sm, edata).syncVersion(sm, edata); > + String[] targets = findSliceNames(sm, edata); > + boolean sync = true; > + for (String replica : targets) { > + SliceStoreManager slice = lookup(replica); > + sync &= slice.syncVersion(sm, edata); > + } > + return sync; > } > > @Override > > Modified: > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreQuery.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreQuery.java?rev=698284&r1=698283&r2=698284&view=diff > > ============================================================================== > --- > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreQuery.java > (original) > +++ > openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreQuery.java > Tue Sep 23 11:58:00 2008 > @@ -77,7 +77,7 @@ > > public void setContext(QueryContext ctx) { > super.setContext(ctx); > - for (StoreQuery q:_queries) > + for (StoreQuery q : _queries) > q.setContext(ctx); > } > > @@ -124,6 +124,9 @@ > StoreManager sm = > owner.getDistributedStore().getSlice(i); > if (!targets.contains(sm)) > continue; > + // if replicated, then execute only on single slice > + if (i > 0 && > containsReplicated(query.getContext())) > + continue; > QueryExecutor call = new QueryExecutor(); > call.executor = executors.get(i); > call.query = query; > @@ -164,6 +167,27 @@ > return result; > } > > + /** > + * Scans metadata to find out if a replicated class is the > candidate. > + **/ > + boolean containsReplicated(QueryContext query) { > + Class candidate = query.getCandidateType(); > + if (candidate != null) { > + ClassMetaData meta = > query.getStoreContext().getConfiguration() > + .getMetaDataRepositoryInstance() > + .getMetaData(candidate, null, true); > + if (meta != null && meta.isReplicated()) > + return true; > + } > + ClassMetaData[] metas = query.getAccessPathMetaDatas(); > + if (metas == null || metas.length < 1) > + return false; > + for (ClassMetaData type : metas) > + if (type.isReplicated()) > + return true; > + return false; > + } > + > public Number executeDelete(StoreQuery q, Object[] params) { > Iterator qs = owner._queries.iterator(); > final List> futures = new > ArrayList>(); > > Modified: > openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Address.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Address.java?rev=698284&r1=698283&r2=698284&view=diff > > ============================================================================== > --- > openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Address.java > (original) > +++ > openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Address.java > Tue Sep 23 11:58:00 2008 > @@ -28,6 +28,9 @@ > > private String city; > private int zip; > + > + @OneToOne > + private Country country; > > @OneToOne(mappedBy = "address") > Person owner; > @@ -79,4 +82,12 @@ > public String toString() { > return city; > } > + > + public Country getCountry() { > + return country; > + } > + > + public void setCountry(Country country) { > + this.country = country; > + } > } > > Added: > openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Country.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Country.java?rev=698284&view=auto > > ============================================================================== > --- > openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Country.java > (added) > +++ > openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Country.java > Tue Sep 23 11:58:00 2008 > @@ -0,0 +1,56 @@ > +/* > + * 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.slice; > + > +import javax.persistence.Entity; > +import javax.persistence.Id; > + > +import org.apache.openjpa.persistence.Replicated; > + > +/** > + * A persistence entity to be replicated across multiple databases. > + * A non-replicated entity can refer to a replicated entity. > + * > + * @author Pinaki Poddar > + * > + */ > +@Entity > +@Replicated > +public class Country { > + @Id > + private String name; > + > + private long population; > + > + public String getName() { > + return name; > + } > + > + public void setName(String name) { > + this.name = name; > + } > + > + public long getPopulation() { > + return population; > + } > + > + public void setPopulation(long population) { > + this.population = population; > + } > +} > > Modified: > openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestBasic.java > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestBasic.java?rev=698284&r1=698283&r2=698284&view=diff > > ============================================================================== > --- > openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestBasic.java > (original) > +++ > openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestBasic.java > Tue Sep 23 11:58:00 2008 > @@ -30,18 +30,22 @@ > * > */ > public class TestBasic extends SliceTestCase { > - > + /** > + * Specify persistence unit name as System property > -Dunit or > + * use the default value as "slice". > + */ > protected String getPersistenceUnitName() { > - return "slice"; > + return System.getProperty("unit","slice"); > } > > > public void setUp() throws Exception { > - super.setUp(PObject.class, Person.class, Address.class, > CLEAR_TABLES); > + super.setUp(PObject.class, Person.class, Address.class, > Country.class, > + CLEAR_TABLES); > } > > /** > - * Persist N objects. > + * Persist N independent objects. > */ > List create(int N) { > List pcs = new ArrayList(); > @@ -128,18 +132,25 @@ > } > > public void testPersistConnectedObjectGraph() { > + EntityManager em = emf.createEntityManager(); > + em.getTransaction().begin(); > Person p1 = new Person("A"); > Person p2 = new Person("B"); > Person p3 = new Person("C"); > Address a1 = new Address("Rome", 12345); > Address a2 = new Address("San Francisco", 23456); > Address a3 = new Address("New York", 34567); > + Country c1 = em.find(Country.class, "Italy"); > + if (c1 == null) { > + c1 = new Country(); > + c1.setName("Italy"); > + em.persist(c1); > + } > + a1.setCountry(c1); > p1.setAddress(a1); > p2.setAddress(a2); > p3.setAddress(a3); > > - EntityManager em = emf.createEntityManager(); > - em.getTransaction().begin(); > em.persist(p1); > em.persist(p2); > em.persist(p3); > @@ -185,5 +196,46 @@ > assertEquals(pc.getId(), pc2.getId()); > assertEquals(value + 1, pc2.getValue()); > } > + > + public void testPersistReplicatedObjects() { > + EntityManager em = emf.createEntityManager(); > + em.getTransaction().begin(); > + String[] names = {"USA", "India", "China"}; > + for (String name : names) { > + Country country = new Country(); > + country.setName(name); > + em.persist(country); > + } > + em.getTransaction().commit(); > + assertEquals(names.length, count(Country.class)); > + > + Country india = em.find(Country.class, "India"); > + assertNotNull(india); > + assertEquals("India", india.getName()); > + } > + > + public void testUpdateReplicatedObjects() { > + EntityManager em = emf.createEntityManager(); > + em.getTransaction().begin(); > + String[] names = {"USA", "India", "China"}; > + long[] population = {300,1200,1400}; > + for (int i = 0; i < names.length; i++) { > + Country country = new Country(); > + country.setName(names[i]); > + country.setPopulation(population[i]); > + em.persist(country); > + } > + em.getTransaction().commit(); > + > + assertEquals(names.length, count(Country.class)); > + Country india = em.find(Country.class, "India"); > + > + assertNotNull(india); > + assertEquals("India", india.getName()); > + india.setPopulation(1201); > + em.getTransaction().begin(); > + em.merge(india); > + em.getTransaction().commit(); > + } > > } > > Modified: > openjpa/trunk/openjpa-slice/src/test/resources/META-INF/persistence.xml > URL: > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/test/resources/META-INF/persistence.xml?rev=698284&r1=698283&r2=698284&view=diff > > ============================================================================== > --- openjpa/trunk/openjpa-slice/src/test/resources/META-INF/persistence.xml > (original) > +++ openjpa/trunk/openjpa-slice/src/test/resources/META-INF/persistence.xml > Tue Sep 23 11:58:00 2008 > @@ -22,6 +22,7 @@ > org.apache.openjpa.slice.PObject > org.apache.openjpa.slice.Person > org.apache.openjpa.slice.Address > + org.apache.openjpa.slice.Country > > > > @@ -83,6 +84,7 @@ > org.apache.openjpa.slice.PObject > org.apache.openjpa.slice.Person > org.apache.openjpa.slice.Address > + org.apache.openjpa.slice.Country > > > value="org.apache.derby.jdbc.EmbeddedDriver"/> > @@ -122,4 +124,28 @@ > value="DefaultMissingInfo=true"/> > > > + > + > + > + > + value="com.mysql.jdbc.Driver"/> > + > + > + value="org.apache.openjpa.slice.policy.UserDistributionPolicy"/> > + > + > + > + value="com.mysql.jdbc.Driver"/> > + value="jdbc:mysql://localhost/slice1"/> > + value="com.mysql.jdbc.Driver"/> > + value="jdbc:mysql://localhost/slice2"/> > + > + > + > + value="refresh"/> > + value="DefaultMissingInfo=true"/> > + value="supported"/> > + > + > + > > > > ------=_Part_80412_3904327.1222198722626--