You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2014/04/25 17:26:36 UTC
[3/4] git commit: [KARAF-2888] Support updates on the FeaturesService
bundle itself
[KARAF-2888] Support updates on the FeaturesService bundle itself
This is done by updating the bundle separately and writing a file with resolution request so that when the service is restarted, the full resolution will happen
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/400e9407
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/400e9407
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/400e9407
Branch: refs/heads/master
Commit: 400e9407db1bce65bfd5c9a5070893f4536b6e0a
Parents: c01c51d
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Fri Apr 25 17:09:18 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 25 17:13:14 2014 +0200
----------------------------------------------------------------------
.../internal/service/FeaturesServiceImpl.java | 109 +++++++++++++++++--
.../features/internal/service/StateStorage.java | 12 +-
2 files changed, 106 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/400e9407/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
index da27397..5d40440 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
@@ -16,6 +16,9 @@
*/
package org.apache.karaf.features.internal.service;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
@@ -52,6 +55,8 @@ import org.apache.karaf.features.RepositoryEvent;
import org.apache.karaf.features.internal.download.StreamProvider;
import org.apache.karaf.features.internal.region.SubsystemResolver;
import org.apache.karaf.features.internal.util.ChecksumUtils;
+import org.apache.karaf.features.internal.util.JsonReader;
+import org.apache.karaf.features.internal.util.JsonWriter;
import org.apache.karaf.features.internal.util.Macro;
import org.apache.karaf.features.internal.util.MapUtils;
import org.apache.karaf.features.internal.util.MultiException;
@@ -82,6 +87,7 @@ import static org.apache.felix.resolver.Util.getSymbolicName;
import static org.apache.felix.resolver.Util.getVersion;
import static org.apache.karaf.features.internal.resolver.ResourceUtils.getFeatureId;
import static org.apache.karaf.features.internal.resolver.ResourceUtils.getUri;
+import static org.apache.karaf.features.internal.service.StateStorage.toStringStringSetMap;
import static org.apache.karaf.features.internal.util.MapUtils.addToMapSet;
import static org.apache.karaf.features.internal.util.MapUtils.apply;
import static org.apache.karaf.features.internal.util.MapUtils.contains;
@@ -197,6 +203,55 @@ public class FeaturesServiceImpl implements FeaturesService {
this.updateSnaphots = updateSnaphots;
this.globalRepository = globalRepository;
loadState();
+ checkResolve();
+
+ }
+
+ private void checkResolve() {
+ if (bundle == null) {
+ return; // Most certainly in unit tests
+ }
+ File resolveFile = bundle.getBundleContext().getDataFile("resolve");
+ if (!resolveFile.exists()) {
+ return;
+ }
+ Map<String, Object> request;
+ try(
+ FileInputStream fis = new FileInputStream(resolveFile)
+ ) {
+ request = (Map<String, Object>) JsonReader.read(fis);
+ } catch (IOException e) {
+ LOGGER.warn("Error reading resolution request", e);
+ return;
+ }
+ Map<String, Set<String>> requestedFeatures = toStringStringSetMap((Map) request.get("features"));
+ Collection<String> opts = (Collection<String>) request.get("options");
+ EnumSet<Option> options = EnumSet.noneOf(Option.class);
+ for (String opt : opts) {
+ options.add(Option.valueOf(opt));
+ }
+ // Resolve
+ try {
+ doInstallFeaturesInThread(requestedFeatures, copyState(), options);
+ } catch (Exception e) {
+ LOGGER.warn("Error updating state", e);
+ }
+ }
+
+ private void writeResolve(Map<String, Set<String>> requestedFeatures, EnumSet<Option> options) throws IOException {
+ File resolveFile = bundle.getBundleContext().getDataFile("resolve");
+ Map<String, Object> request = new HashMap<>();
+ List<String> opts = new ArrayList<>();
+ for (Option opt : options) {
+ opts.add(opt.toString());
+ }
+ request.put("features", requestedFeatures);
+ request.put("options", opts);
+ try(
+ FileOutputStream fos = new FileOutputStream(resolveFile);
+ ) {
+ JsonWriter.write(fos, request);
+ }
}
//
@@ -1025,16 +1080,52 @@ public class FeaturesServiceImpl implements FeaturesService {
// #10: send events
//
- // TODO: handle update on the features service itself
+ //
+ // Handle updates on the FeaturesService bundle
+ //
RegionDeployment rootRegionDeployment = deployment.regions.get(ROOT_REGION);
- if (rootRegionDeployment != null &&
- (rootRegionDeployment.toUpdate.containsKey(bundle)
- || rootRegionDeployment.toDelete.contains(bundle))) {
-
- LOGGER.warn("Updating or uninstalling of the FeaturesService is not supported");
- rootRegionDeployment.toUpdate.remove(bundle);
- rootRegionDeployment.toDelete.remove(bundle);
-
+ // We don't support uninstalling the bundle
+ if (rootRegionDeployment != null && rootRegionDeployment.toDelete.contains(bundle)) {
+ throw new UnsupportedOperationException("Uninstalling the FeaturesService bundle is not supported");
+ }
+ // If the bundle needs to be updated, do the following:
+ // - create flag files to indicate the resolution must be continued after restart
+ // - update the checksum and save the state
+ // - compute bundles wired to the FeaturesService bundle that will be refreshed
+ // - stop the bundle
+ // - update the bundle
+ // - refresh wired bundles
+ // - start the bundle
+ // - exit
+ // When restarting, the resolution will be attempted again
+ if (rootRegionDeployment != null && rootRegionDeployment.toUpdate.containsKey(bundle)) {
+ writeResolve(requestedFeatures, options);
+ // If the bundle is updated because of a different checksum,
+ // save the new checksum persistently
+ if (deployment.bundleChecksums.containsKey(bundle.getBundleId())) {
+ synchronized (lock) {
+ this.state.bundleChecksums.put(bundle.getBundleId(), deployment.bundleChecksums.get(bundle.getBundleId()));
+ saveState();
+ }
+ }
+ Resource resource = rootRegionDeployment.toUpdate.get(bundle);
+ String uri = getUri(resource);
+ print("The FeaturesService bundle needs is being updated with " + uri, verbose);
+ toRefresh.clear();
+ toRefresh.add(bundle);
+ computeBundlesToRefresh(toRefresh,
+ dstate.bundles.values(),
+ Collections.<Resource, Bundle>emptyMap(),
+ Collections.<Resource, List<Wire>>emptyMap());
+ bundle.stop(Bundle.STOP_TRANSIENT);
+ try (
+ InputStream is = getBundleInputStream(resource, providers)
+ ) {
+ bundle.update(is);
+ }
+ refreshPackages(toRefresh);
+ bundle.start();
+ return;
}
//
http://git-wip-us.apache.org/repos/asf/karaf/blob/400e9407/features/core/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
index 8168994..e6adab0 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
@@ -70,7 +70,7 @@ public abstract class StateStorage {
protected abstract InputStream getInputStream() throws IOException;
protected abstract OutputStream getOutputStream() throws IOException;
- protected Map<String, Set<String>> toStringStringSetMap(Map<?,?> map) {
+ static Map<String, Set<String>> toStringStringSetMap(Map<?,?> map) {
Map<String, Set<String>> nm = new HashMap<>();
for (Map.Entry entry : map.entrySet()) {
nm.put(entry.getKey().toString(), toStringSet((Collection) entry.getValue()));
@@ -78,7 +78,7 @@ public abstract class StateStorage {
return nm;
}
- protected Map<String, Set<Long>> toStringLongSetMap(Map<?,?> map) {
+ static Map<String, Set<Long>> toStringLongSetMap(Map<?,?> map) {
Map<String, Set<Long>> nm = new HashMap<>();
for (Map.Entry entry : map.entrySet()) {
nm.put(entry.getKey().toString(), toLongSet((Collection) entry.getValue()));
@@ -86,7 +86,7 @@ public abstract class StateStorage {
return nm;
}
- protected Set<String> toStringSet(Collection<?> col) {
+ static Set<String> toStringSet(Collection<?> col) {
Set<String> ns = new TreeSet<>();
for (Object o : col) {
ns.add(o.toString());
@@ -94,7 +94,7 @@ public abstract class StateStorage {
return ns;
}
- protected Set<Long> toLongSet(Collection<?> set) {
+ static Set<Long> toLongSet(Collection<?> set) {
Set<Long> ns = new TreeSet<>();
for (Object o : set) {
ns.add(toLong(o));
@@ -102,7 +102,7 @@ public abstract class StateStorage {
return ns;
}
- protected Map<Long, Long> toLongLongMap(Map<?,?> map) {
+ static Map<Long, Long> toLongLongMap(Map<?,?> map) {
Map<Long, Long> nm = new HashMap<>();
for (Map.Entry entry : map.entrySet()) {
nm.put(toLong(entry.getKey()), toLong(entry.getValue()));
@@ -110,7 +110,7 @@ public abstract class StateStorage {
return nm;
}
- protected Map<String, Long> toStringLongMap(Map<?,?> map) {
+ static Map<String, Long> toStringLongMap(Map<?,?> map) {
Map<String, Long> nm = new HashMap<>();
for (Map.Entry entry : map.entrySet()) {
nm.put(entry.getKey().toString(), toLong(entry.getValue()));