You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ja...@apache.org on 2014/03/05 15:59:06 UTC
svn commit: r1574516 - in /ace/trunk:
org.apache.ace.client.repository/src/org/apache/ace/client/repository/stateful/impl/
run-server-allinone/ run-server-allinone/scripts/
Author: jawi
Date: Wed Mar 5 14:59:06 2014
New Revision: 1574516
URL: http://svn.apache.org/r1574516
Log:
Improved performance of the StatefulTargetRepository:
- When lots of artifacts are present, changing one of those would cause *all*
targets to update its state, even if the target had no association whatsoever
with the originating artifact, this causes a lots of overhead and loss of
performance;
- made the event-handling for the stateful target repository a little more smarter
in its decision to recalculate the state of a (stateful) target. This is now
only done when a target actually has something to do with the entity, for
example, because it is reachable from the given target, or is a resource
processor for an reachable artifact;
- improved the state calculation of a stateful target a little by storing the
reachable artifacts and the artifacts of the latest deployment version in a
sorted set. This way, we can use a single "equals()" check, instead of a
double "containsAll()" check.
Added:
ace/trunk/run-server-allinone/scripts/addbundles.gogo
Modified:
ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/stateful/impl/StatefulTargetObjectImpl.java
ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/stateful/impl/StatefulTargetRepositoryImpl.java
ace/trunk/run-server-allinone/server-allinone.bndrun
Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/stateful/impl/StatefulTargetObjectImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/stateful/impl/StatefulTargetObjectImpl.java?rev=1574516&r1=1574515&r2=1574516&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/stateful/impl/StatefulTargetObjectImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/stateful/impl/StatefulTargetObjectImpl.java Wed Mar 5 14:59:06 2014
@@ -29,6 +29,8 @@ import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
+import java.util.SortedSet;
+import java.util.TreeSet;
import org.apache.ace.client.repository.Associatable;
import org.apache.ace.client.repository.Association;
@@ -246,7 +248,7 @@ public class StatefulTargetObjectImpl im
private void determineStoreState(DeploymentVersionObject deploymentVersionObject) {
synchronized (m_lock) {
- List<String> fromShop = new ArrayList<String>();
+ SortedSet<String> fromShop = new TreeSet<String>();
ArtifactObject[] artifactsFromShop = m_repository.getNecessaryArtifacts(getID());
DeploymentVersionObject mostRecentVersion;
if (deploymentVersionObject == null) {
@@ -265,13 +267,11 @@ public class StatefulTargetObjectImpl im
return;
}
- // TODO in the artifacts we get from the shop, there seem to be some duplicates
- // which does not influence the algorithm below, but we might want to optimize this
for (ArtifactObject ao : artifactsFromShop) {
fromShop.add(ao.getURL());
}
- List<String> fromDeployment = new ArrayList<String>();
+ SortedSet<String> fromDeployment = new TreeSet<String>();
for (DeploymentArtifact da : getArtifactsFromDeployment()) {
fromDeployment.add(da.getDirective(DeploymentArtifact.DIRECTIVE_KEY_BASEURL));
}
@@ -279,7 +279,7 @@ public class StatefulTargetObjectImpl im
if ((mostRecentVersion == null) && fromShop.isEmpty()) {
setStoreState(StoreState.New);
}
- else if (fromShop.containsAll(fromDeployment) && fromDeployment.containsAll(fromShop)) {
+ else if (fromShop.equals(fromDeployment)) {
// great, we have the same artifacts. But... do they need to be reprocessed?
// this might be the case when the target has new tags that affect templates
for (ArtifactObject ao : artifactsFromShop) {
Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/stateful/impl/StatefulTargetRepositoryImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/stateful/impl/StatefulTargetRepositoryImpl.java?rev=1574516&r1=1574515&r2=1574516&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/stateful/impl/StatefulTargetRepositoryImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/stateful/impl/StatefulTargetRepositoryImpl.java Wed Mar 5 14:59:06 2014
@@ -38,9 +38,12 @@ import org.apache.ace.client.repository.
import org.apache.ace.client.repository.RepositoryUtil;
import org.apache.ace.client.repository.SessionFactory;
import org.apache.ace.client.repository.helper.bundle.BundleHelper;
+import org.apache.ace.client.repository.object.Artifact2FeatureAssociation;
import org.apache.ace.client.repository.object.ArtifactObject;
import org.apache.ace.client.repository.object.DeploymentArtifact;
import org.apache.ace.client.repository.object.DeploymentVersionObject;
+import org.apache.ace.client.repository.object.Distribution2TargetAssociation;
+import org.apache.ace.client.repository.object.Feature2DistributionAssociation;
import org.apache.ace.client.repository.object.TargetObject;
import org.apache.ace.client.repository.object.FeatureObject;
import org.apache.ace.client.repository.object.DistributionObject;
@@ -609,8 +612,8 @@ public class StatefulTargetRepositoryImp
}
/**
- * Returns a map of all resource processors that are available. If there are multiple versions
- * of a specific processor, it will only return the latest version.
+ * Returns a map of all resource processors that are available. If there are multiple versions of a specific
+ * processor, it will only return the latest version.
*
* @return a map of all resource processors, indexed by processor ID
*/
@@ -742,7 +745,7 @@ public class StatefulTargetRepositoryImp
*/
private static String nextVersion(String version) {
try {
- // in case the given version is null or empty, v will be '0.0.0'...
+ // in case the given version is null or empty, v will be '0.0.0'...
Version v = Version.parseVersion(version);
Version result = new Version(v.getMajor() + 1, 0, 0);
return result.toString();
@@ -771,6 +774,15 @@ public class StatefulTargetRepositoryImp
}
}
}
+ else if (TargetObject.PRIVATE_TOPIC_CHANGED.equals(topic)) {
+ synchronized (m_repository) {
+ String id = ((TargetObject) event.getProperty(RepositoryObject.EVENT_ENTITY)).getID();
+ StatefulTargetObjectImpl stoi = getStatefulTargetObject(id);
+ if (stoi != null) {
+ stoi.determineStatus();
+ }
+ }
+ }
else if (TargetObject.PRIVATE_TOPIC_REMOVED.equals(topic)) {
synchronized (m_repository) {
String id = ((TargetObject) event.getProperty(RepositoryObject.EVENT_ENTITY)).getID();
@@ -794,12 +806,19 @@ public class StatefulTargetRepositoryImp
}
}
}
- else {
+ else if (!RepositoryAdmin.PRIVATE_TOPIC_LOGIN.equals(topic) && !RepositoryAdmin.PRIVATE_TOPIC_REFRESH.equals(topic)) {
// Something else has changed; however, the entire shop may have an influence on
- // any target, so recheck everything.
- synchronized (m_repository) {
- for (StatefulTargetObjectImpl stoi : m_repository.values()) {
- stoi.determineStatus();
+ // any target, so recheck everything that is reachable from the entity...
+
+ RepositoryObject entity = (RepositoryObject) event.getProperty(RepositoryObject.EVENT_ENTITY);
+ if (entity != null) {
+ synchronized (m_repository) {
+ for (StatefulTargetObjectImpl stoi : m_repository.values()) {
+ // Check whether the entity is reachable from this target...
+ if (isReachableFrom(stoi, entity)) {
+ stoi.determineStatus();
+ }
+ }
}
}
}
@@ -813,6 +832,78 @@ public class StatefulTargetRepositoryImp
}
}
+ /**
+ * Determines whether a given entity is reachable from a given stateful target, by traversing all its associations.
+ *
+ * @param target
+ * the stateful target object to check;
+ * @param entity
+ * the entity to test.
+ * @return <code>true</code> if the given entity is reachable from the given target, <code>false</code> otherwise.
+ */
+ private boolean isReachableFrom(StatefulTargetObjectImpl target, RepositoryObject entity) {
+ if (entity instanceof DistributionObject) {
+ return target.isAssociated(entity, DistributionObject.class);
+ }
+ else if (entity instanceof Distribution2TargetAssociation) {
+ return ((Distribution2TargetAssociation) entity).getRight().contains(target.getTargetObject());
+ }
+ else if (entity instanceof FeatureObject) {
+ for (DistributionObject dist : target.getDistributions()) {
+ if (dist.isAssociated(entity, FeatureObject.class)) {
+ return true;
+ }
+ }
+ }
+ else if (entity instanceof Feature2DistributionAssociation) {
+ List<DistributionObject> associatedDistributions = ((Feature2DistributionAssociation) entity).getRight();
+ for (DistributionObject dist : target.getDistributions()) {
+ if (associatedDistributions.contains(dist)) {
+ return true;
+ }
+ }
+ }
+ else if (entity instanceof ArtifactObject) {
+ List<ArtifactObject> reachableArtifacts = new ArrayList<ArtifactObject>();
+ for (DistributionObject dist : target.getDistributions()) {
+ for (FeatureObject feat : dist.getFeatures()) {
+ if (feat.isAssociated(entity, ArtifactObject.class)) {
+ return true;
+ }
+ else {
+ // Keep a list of reachable artifacts while we're at it, used below...
+ reachableArtifacts.addAll(feat.getArtifacts());
+ }
+ }
+ }
+
+ // Not found as regular artifact, maybe we've got a resource processor?
+ String resourceProcessorPID = entity.getAttribute(BundleHelper.KEY_RESOURCE_PROCESSOR_PID);
+ if (resourceProcessorPID != null) {
+ for (ArtifactObject reachableArtifact : reachableArtifacts) {
+ if (resourceProcessorPID.equals(reachableArtifact.getProcessorPID())) {
+ return true;
+ }
+ }
+ }
+ }
+ else if (entity instanceof Artifact2FeatureAssociation) {
+ for (DistributionObject dist : target.getDistributions()) {
+ List<FeatureObject> associatedFeatures = ((Artifact2FeatureAssociation) entity).getRight();
+ for (FeatureObject feat : dist.getFeatures()) {
+ if (associatedFeatures.contains(feat)) {
+ return true;
+ }
+ }
+ }
+ }
+ else {
+ // Uhoh, this actually shouldn't happen...
+ m_log.log(LogService.LOG_WARNING, "Unhandled entity in reachability check for stateful target: " + entity.getDefinition());
+ }
+ return false;
+ }
+
boolean needsNewVersion(ArtifactObject artifact, String targetID, String version) {
return m_artifactRepository.needsNewVersion(artifact, getTargetObject(targetID), targetID, version);
}
Added: ace/trunk/run-server-allinone/scripts/addbundles.gogo
URL: http://svn.apache.org/viewvc/ace/trunk/run-server-allinone/scripts/addbundles.gogo?rev=1574516&view=auto
==============================================================================
--- ace/trunk/run-server-allinone/scripts/addbundles.gogo (added)
+++ ace/trunk/run-server-allinone/scripts/addbundles.gogo Wed Mar 5 14:59:06 2014
@@ -0,0 +1,33 @@
+#
+# Creates an additional 100 bundles and 10 configuration files
+#
+
+# install test bundle with additional Gogo commands needed later on in this script
+pwd = (cd) getAbsolutePath
+start 'file:'$pwd'/../org.apache.ace.test/generated/org.apache.ace.test.jar'
+
+# create a workspace
+w = (cw)
+
+# create 100 bundle artifacts and link them to the 10 features...
+a = 0
+while {(lt $a 10)} {
+ each [0 1 2 3 4 5 6 7 8 9] {
+ echo 'Creating bundle artifact-extra-'$a$it' ...'
+ # generate artifacts and associate them
+ $w ca (gba 'artifact-extra-2-'$it'-'$a) true
+ $w ca2f '(bundle-symbolicname=artifact-extra-2-'$it'-'$a')' '(name=feature-'$it')'
+ }
+ a = (inc $a)
+}
+
+each [0 1 2 3 4 5 6 7 8 9] {
+ echo 'Creating config-'$it'.xml ...'
+ c = (gca 'config-extra-2-'$it 'common' 'prop'$it'1' 'prop'$it'2' 'prop'$it'3')
+ $w ca $c true
+ $w ca2f '(artifactName=config-extra-2-'$it'.xml)' '(name=feature-'$it')'
+}
+
+# commit and delete the workspace
+$w commit
+rw $w
Modified: ace/trunk/run-server-allinone/server-allinone.bndrun
URL: http://svn.apache.org/viewvc/ace/trunk/run-server-allinone/server-allinone.bndrun?rev=1574516&r1=1574515&r2=1574516&view=diff
==============================================================================
--- ace/trunk/run-server-allinone/server-allinone.bndrun (original)
+++ ace/trunk/run-server-allinone/server-allinone.bndrun Wed Mar 5 14:59:06 2014
@@ -77,7 +77,7 @@
launch.storage.dir=bundle-cache
# Add some extra memory to the VM
--runvm: -Xmx1G
+-runvm: -Xmx1G -agentpath:/Applications/YourKit_Java_Profiler_2013_build_13072.app/bin/mac/libyjpagent.jnilib
# Enable Yourkit profiling
#-runvm: -Xmx1G -agentpath:/Applications/YourKit_Java_Profiler_12.0.5.app/bin/mac/libyjpagent.jnilib
\ No newline at end of file