Skip to content

Commit

Permalink
make the Scheduler Thread safe
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeloffner committed Feb 8, 2024
1 parent 3f832ff commit f864d79
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 61 deletions.
106 changes: 47 additions & 59 deletions core/src/main/java/lucee/runtime/schedule/SchedulerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.xml.sax.SAXException;

Expand All @@ -46,7 +48,7 @@
*/
public final class SchedulerImpl implements Scheduler {

private ScheduleTaskImpl[] tasks;
private Queue<TaskRef> tasks;
private Resource schedulerFile;
private StorageUtil su = new StorageUtil();
private String charset;
Expand Down Expand Up @@ -86,32 +88,32 @@ public SchedulerImpl(CFMLEngine engine, Config config, Array tasks) throws PageE
public SchedulerImpl(CFMLEngine engine, String xml, Config config) {
this.engine = (CFMLEngineImpl) engine;
this.config = config;
tasks = new ScheduleTaskImpl[0];
tasks = new ConcurrentLinkedQueue<>();
init();
}

/**
* initialize all tasks
*/
private void init() {
for (int i = 0; i < tasks.length; i++) {
init(tasks[i]);
for (TaskRef ref: tasks) {
init(ref.task);
}
}

public void startIfNecessary() {
for (int i = 0; i < tasks.length; i++) {
init(tasks[i]);
for (TaskRef ref: tasks) {
init(ref.task);
}
}

private void init(ScheduleTask task) {
((ScheduleTaskImpl) task).startIfNecessary(engine);
private void init(ScheduleTaskImpl task) {
task.startIfNecessary(engine);
}

public void stop() {
for (int i = 0; i < tasks.length; i++) {
tasks[i].stop();
for (TaskRef ref: tasks) {
ref.task.stop();
}
}

Expand All @@ -123,13 +125,13 @@ public void stop() {
* @return all schedule tasks
* @throws PageException
*/
private ScheduleTaskImpl[] readInAllTasks(Array tasks) throws PageException {
ArrayList<ScheduleTaskImpl> list = new ArrayList<ScheduleTaskImpl>();
private Queue<TaskRef> readInAllTasks(Array tasks) throws PageException {
Queue<TaskRef> queue = new ConcurrentLinkedQueue<>();
Iterator<?> it = tasks.getIterator();
while (it.hasNext()) {
list.add(readInTask((Struct) it.next()));
queue.add(new TaskRef(readInTask((Struct) it.next())));
}
return list.toArray(new ScheduleTaskImpl[list.size()]);
return queue;
}

/**
Expand Down Expand Up @@ -159,47 +161,42 @@ private ScheduleTaskImpl readInTask(Struct el) throws PageException {
}

private void addTask(ScheduleTaskImpl task) {
for (int i = 0; i < tasks.length; i++) {
if (!tasks[i].getTask().equals(task.getTask())) continue;
if (!tasks[i].md5().equals(task.md5())) {
tasks[i].log(Log.LEVEL_INFO, "invalidate task because the task is replaced with a new one");
tasks[i].setValid(false);
tasks[i] = task;
for (TaskRef ref: tasks) {
if (!ref.task.getTask().equals(task.getTask())) continue;
if (!ref.task.md5().equals(task.md5())) {
ref.task.log(Log.LEVEL_INFO, "invalidate task because the task is replaced with a new one");
ref.task.setValid(false);
ref.task = task;
init(task);
}
return;
}

ScheduleTaskImpl[] tmp = new ScheduleTaskImpl[tasks.length + 1];
for (int i = 0; i < tasks.length; i++) {
tmp[i] = tasks[i];
}
tmp[tasks.length] = task;
tasks = tmp;
tasks.add(new TaskRef(task));
init(task);
}

@Override
public ScheduleTask getScheduleTask(String name) throws ScheduleException {
for (int i = 0; i < tasks.length; i++) {
if (tasks[i].getTask().equalsIgnoreCase(name)) return tasks[i];
for (TaskRef ref: tasks) {
if (ref.task.getTask().equalsIgnoreCase(name)) return ref.task;
}
throw new ScheduleException("schedule task with name " + name + " doesn't exist");
}

@Override
public ScheduleTask getScheduleTask(String name, ScheduleTask defaultValue) {
for (int i = 0; i < tasks.length; i++) {
if (tasks[i] != null && tasks[i].getTask().equalsIgnoreCase(name)) return tasks[i];
for (TaskRef ref: tasks) {
if (ref.task.getTask().equalsIgnoreCase(name)) return ref.task;
}
return defaultValue;
}

@Override
public ScheduleTask[] getAllScheduleTasks() {
ArrayList<ScheduleTask> list = new ArrayList<ScheduleTask>();
for (int i = 0; i < tasks.length; i++) {
if (!tasks[i].isHidden()) list.add(tasks[i]);
for (TaskRef ref: tasks) {
if (!ref.task.isHidden()) list.add(ref.task);
}
return list.toArray(new ScheduleTask[list.size()]);
}
Expand All @@ -224,41 +221,24 @@ public void pauseScheduleTask(String name, boolean pause, boolean throwWhenNotEx
throw ExceptionUtil.toIOException(e);
}

for (int i = 0; i < tasks.length; i++) {
if (tasks[i].getTask().equalsIgnoreCase(name)) {
tasks[i].setPaused(pause);
for (TaskRef ref: tasks) {
if (ref.task.getTask().equalsIgnoreCase(name)) {
ref.task.setPaused(pause);
}
}
}

@Override
public void removeScheduleTask(String name, boolean throwWhenNotExist) throws IOException, ScheduleException {
synchronized (sync) {
int pos = -1;
for (int i = 0; i < tasks.length; i++) {
if (tasks[i].getTask().equalsIgnoreCase(name)) {
tasks[i].log(Log.LEVEL_INFO, "task gets removed");
tasks[i].setValid(false);
pos = i;
}
}
if (pos != -1) {
ScheduleTaskImpl[] newTasks = new ScheduleTaskImpl[tasks.length - 1];
int count = 0;
for (int i = 0; i < tasks.length; i++) {
if (i != pos) newTasks[count++] = tasks[i];

}
tasks = newTasks;
}

try {
ConfigAdmin.removeScheduledTask((ConfigPro) config, name, true);
}
catch (Exception e) {
throw ExceptionUtil.toIOException(e);
}
tasks.removeIf(ref -> ref.task.getTask().equalsIgnoreCase(name));
try {
ConfigAdmin.removeScheduledTask((ConfigPro) config, name, true);
}
catch (Exception e) {
throw ExceptionUtil.toIOException(e);
}

}

public void removeIfNoLonerValid(ScheduleTask task) throws IOException {
Expand Down Expand Up @@ -300,4 +280,12 @@ public String getCharset() {
public boolean active() {
return engine == null || engine.active();
}

private static class TaskRef {
private ScheduleTaskImpl task;

public TaskRef(ScheduleTaskImpl task) {
this.task = task;
}
}
}
2 changes: 1 addition & 1 deletion loader/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<project default="core" basedir="." name="Lucee"
xmlns:resolver="antlib:org.apache.maven.resolver.ant">

<property name="version" value="6.0.1.65-SNAPSHOT"/>
<property name="version" value="6.0.1.66-SNAPSHOT"/>

<taskdef uri="antlib:org.apache.maven.resolver.ant" resource="org/apache/maven/resolver/ant/antlib.xml">
<classpath>
Expand Down
2 changes: 1 addition & 1 deletion loader/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<groupId>org.lucee</groupId>
<artifactId>lucee</artifactId>
<version>6.0.1.65-SNAPSHOT</version>
<version>6.0.1.66-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Lucee Loader Build</name>
Expand Down

0 comments on commit f864d79

Please sign in to comment.