Skip to content

Commit

Permalink
test
Browse files Browse the repository at this point in the history
  • Loading branch information
victoralfaro-dotcms committed Nov 12, 2024
1 parent 49ea6f4 commit b71fd6a
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,73 +3,115 @@
import com.dotcms.concurrent.DotConcurrentFactory;
import com.dotmarketing.portlets.workflows.actionlet.WorkFlowActionlet;
import com.dotmarketing.util.Config;
import com.dotmarketing.util.Logger;
import com.liferay.util.StringPool;
import org.osgi.framework.BundleContext;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

public class OSGIActionletLateRegistration {

private static final String OSGI_REGISTRATION_ATTEMPTS_MAX_KEY = "OSGI_REGISTRATION_ATTEMPTS_MAX";
private static final String OSGI_REGISTRATION_CHECKS_MAX_KEY = "OSGI_REGISTRATION_ATTEMPTS_MAX";
private static final int REGISTRATION_DELAY = 500;
private static final Object LOCK = new Object();

private final Hashtable<String, OSGIRegistrationAttempt> registrationAttempts = new Hashtable<>();
private final ConcurrentMap<String, OSGIRegistrationCheck> registrationChecks = new ConcurrentHashMap<>();

private Future<List<OSGIRegistrationAttempt>> registrationFuture;
private Future<List<OSGIRegistrationCheck>> registrationCheckFuture;

public void addActionlet(final BundleContext context,
final WorkFlowActionlet actionlet,
final Collection<WorkFlowActionlet> registered) {
registrationAttempts.put(actionlet.getName(), new OSGIRegistrationAttempt(context, actionlet, registered));
Logger.info(this, String.format("Adding actionlet [%s] for later registration", actionlet.getName()));
registrationChecks.put(actionlet.getName(), new OSGIRegistrationCheck(context, actionlet, registered));
startIfHasNot();
}

public List<OSGIRegistrationCheck> waitForRegistrationChecks() throws InterruptedException, ExecutionException {
synchronized (LOCK) {
startIfHasNot();
}
if (registrationCheckFuture == null) {
return List.of();
}

while(!registrationCheckFuture.isDone()) {
Logger.info(this, "Waiting for registration checks to finish");
TimeUnit.MILLISECONDS.sleep(250);
}

}
final List<OSGIRegistrationCheck> checks = registrationCheckFuture.get();
cleanUp();

public boolean isDone() {
final int maxAttempts = Config.getIntProperty(OSGI_REGISTRATION_ATTEMPTS_MAX_KEY, 12);
return registrationAttempts.isEmpty()
|| registrationAttempts.values()
.stream()
.allMatch(attempt -> attempt.isReadyToRegister() || attempt.getTries() == maxAttempts);
return checks;
}
}

private void startIfHasNot() {
synchronized (LOCK) {
if (registrationFuture == null) {
registrationFuture = DotConcurrentFactory.getInstance().getSubmitter().submit(this::checkRegistrations);
if (registrationCheckFuture == null) {
registrationCheckFuture = DotConcurrentFactory.getInstance().getSubmitter().submit(this::checkRegistrations);
}
}
}

private boolean checksLeft(int maxAttempts) {
return registrationAttempts.isEmpty() ||
registrationAttempts.values()
private boolean checkIfLeft(int maxAttempts) {
return registrationChecks.isEmpty() ||
registrationChecks.values()
.stream()
.allMatch(attempt -> attempt.isReadyToRegister() || attempt.getTries() == maxAttempts);
.allMatch(attempt -> attempt.isReadyToRegister() || attempt.getAttempts() == maxAttempts);
}

private List<OSGIRegistrationAttempt> checkRegistrations() throws InterruptedException {
final int maxAttempts = Config.getIntProperty(OSGI_REGISTRATION_ATTEMPTS_MAX_KEY, 12);
while (!checksLeft(maxAttempts)) {
registrationAttempts.values().forEach(attempt -> {
private List<OSGIRegistrationCheck> checkRegistrations() throws InterruptedException {
final int maxAttempts = Config.getIntProperty(OSGI_REGISTRATION_CHECKS_MAX_KEY, 10);
Logger.info(this, "Starting OSGI actionlet registration checks");

while (!checkIfLeft(maxAttempts)) {
registrationChecks.values().forEach(attempt -> {
Logger.info(
this,
String.format(
"New OSGI registration check for actionlet [%s]",
attempt.getActionlet().getName()));
if (OSGIUtil.getInstance().isReadyToRegisterActionlet(attempt.getContext())) {
Logger.info(
this,
String.format(
"Detected that context is ready for actionlet [%s]",
attempt.getActionlet().getName()));
attempt.setReadyToRegister(true);
} else if (attempt.getTries() < maxAttempts) {
attempt.incrementTries();
} else if (attempt.getAttempts() < maxAttempts) {
Logger.info(
this,
String.format(
"Context is NOT ready for actionlet [%s], giving another try",
attempt.getActionlet().getName()));
attempt.incrementAttempts();
}
});
TimeUnit.MILLISECONDS.sleep(REGISTRATION_DELAY);
}

return new ArrayList<>(registrationAttempts.values());
final List<OSGIRegistrationCheck> result = new ArrayList<>(registrationChecks.values());
Logger.info(
this,
String.format(
"Registration checks finished with following registrations statuses: [%s]",
result.stream()
.map(OSGIRegistrationCheck::toString)
.collect(Collectors.joining(StringPool.COMMA))));

return result;
}

private void cleanUp() {
registrationChecks.clear();
registrationCheckFuture = null;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.apache.felix.framework;

import com.dotmarketing.portlets.workflows.actionlet.WorkFlowActionlet;
import org.osgi.framework.BundleContext;

import java.util.Collection;
import java.util.Optional;

public class OSGIRegistrationCheck {

private final BundleContext context;
private final WorkFlowActionlet actionlet;
private final Collection<WorkFlowActionlet> actionlets;
private int attempts;
private boolean readyToRegister;

public OSGIRegistrationCheck(final BundleContext context,
final WorkFlowActionlet actionlet,
final Collection<WorkFlowActionlet> actionlets) {
this.context = context;
this.actionlet = actionlet;
this.actionlets = actionlets;
attempts = 0;
readyToRegister = false;
}

public BundleContext getContext() {
return context;
}

public WorkFlowActionlet getActionlet() {
return actionlet;
}

public Collection<WorkFlowActionlet> getActionlets() {
return actionlets;
}

public int getAttempts() {
return attempts;
}

public boolean isReadyToRegister() {
return readyToRegister;
}

public void setReadyToRegister(boolean readyToRegister) {
this.readyToRegister = readyToRegister;
}

public void incrementAttempts() {
attempts++;
}

@Override
public String toString() {
return "OSGIRegistrationCheck{" +
"actionlet=" + Optional.ofNullable(actionlet).map(WorkFlowActionlet::getName).orElse(null) +
", attempts=" + attempts +
", readyToRegister=" + readyToRegister +
'}';
}
}
38 changes: 19 additions & 19 deletions dotCMS/src/main/java/org/apache/felix/framework/OSGIUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,7 @@ public static OSGIUtil getInstance() {
private Framework felixFramework;
private String felixExtraPackagesFile;
private WorkflowAPIOsgiService workflowOsgiService;
private Boolean osgiStarted = false;
private OSGIActionletLateRegistration osgiActionletLateRegistration = new OSGIActionletLateRegistration();
private OSGIActionletLateRegistration osgiLateRegistration = new OSGIActionletLateRegistration();

//List of jar prefixes of the jars to be included in the osgi-extra.conf file
public final List<String> portletIDsStopped = Collections.synchronizedList(new ArrayList<>());
Expand Down Expand Up @@ -400,10 +399,11 @@ public synchronized Framework initializeFramework() {
felixFramework = null;
Logger.error(this, "Could not create framework: " + ex);
throw new RuntimeException(ex);
} finally {
registerLateActionlets();
}

setOsgiStarted(true);
System.setProperty(WebKeys.OSGI_ENABLED, osgiStarted.toString());
System.setProperty(WebKeys.OSGI_ENABLED, Boolean.TRUE.toString());
System.setProperty(WebKeys.DOTCMS_STARTUP_TIME_OSGI,
String.valueOf(System.currentTimeMillis() - start));

Expand All @@ -430,7 +430,7 @@ public void registerActionlet(final BundleContext context,
}

public boolean isReadyToRegisterActionlet(final BundleContext context) {
return osgiStarted && context.getServiceReference(WorkflowAPIOsgiService.class.getName()) != null;
return context.getServiceReference(WorkflowAPIOsgiService.class.getName()) != null;
}

public void tryToRegisterAction(final BundleContext context,
Expand All @@ -439,26 +439,26 @@ public void tryToRegisterAction(final BundleContext context,
if (isReadyToRegisterActionlet(context)) {
registerActionlet(context, actionlet, actionlets);
} else {
osgiActionletLateRegistration.addActionlet(context, actionlet, actionlets);
osgiLateRegistration.addActionlet(context, actionlet, actionlets);
}
}

public void addActionletForLater(final BundleContext context,
final WorkFlowActionlet actionlet,
final Collection<WorkFlowActionlet> actionlets) {

}

/*public void registerLateActionlets() {
Logger.info(this, String.format("Registering [%d] pending actionlets", actionletsToRegister.size()));
actionletsToRegister.forEach(tuple -> registerActionlet(tuple._1, tuple._2));
actionletsToRegister.clear();
}*/
public void registerLateActionlets() {
final List<OSGIRegistrationCheck> registrationChecks;
try {
registrationChecks = osgiLateRegistration.waitForRegistrationChecks();
} catch (Exception e) {
Logger.warn(this, "Could not get late registration checks for actionlets", e);
return;
}

Logger.info(this, String.format("Registering [%d] pending actionlets", registrationChecks.size()));

registrationChecks.stream()
.filter(OSGIRegistrationCheck::isReadyToRegister)
.forEach(check -> registerActionlet(check.getContext(), check.getActionlet(), check.getActionlets()));

private void setOsgiStarted(final boolean osgiStarted) {
this.osgiStarted = osgiStarted;
registrationChecks.clear();
}

private void startWatchingUploadFolder(final String uploadFolder) {
Expand Down

0 comments on commit b71fd6a

Please sign in to comment.