Skip to content

Commit fbb60e3

Browse files
committed
do not allow to change monitoring configuration without checks + add tests
1 parent ad1e422 commit fbb60e3

File tree

10 files changed

+152
-68
lines changed

10 files changed

+152
-68
lines changed

net.lecousin.core/src/main/java/net/lecousin/framework/application/LCCore.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ public static interface Environment {
4747
/** Return the libraries manager. */
4848
LibrariesManager getSystemLibraries();
4949

50+
/** Return true if the current thread is allowed to change system configuration. */
51+
boolean currentThreadIsSystem();
52+
5053
/** Return a system logger, that may be used during initialization of the environment. */
5154
Logger getSystemLogger(String name);
5255

net.lecousin.core/src/main/java/net/lecousin/framework/application/StandaloneLCCore.java

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import net.lecousin.framework.application.libraries.LibrariesManager;
1212
import net.lecousin.framework.concurrent.async.IAsync;
1313
import net.lecousin.framework.concurrent.threads.DrivesThreadingManager.DrivesProvider;
14+
import net.lecousin.framework.concurrent.threads.TaskManagerMonitor;
1415
import net.lecousin.framework.concurrent.threads.Threading;
1516
import net.lecousin.framework.concurrent.threads.priority.SimpleTaskPriorityManager;
1617
import net.lecousin.framework.log.Logger;
@@ -47,7 +48,25 @@ public StandaloneLCCore() {
4748
private int nbCPUThreads = -1;
4849
private int nbUnmanagedThreads = -1;
4950
private DrivesProvider drivesProvider = null;
50-
51+
private TaskManagerMonitor.Configuration cpuMonitorConfig = new TaskManagerMonitor.Configuration(
52+
60 * 1000, // 1 minute
53+
5 * 60 * 1000, // 5 minutes
54+
15 * 60 * 1000, // 15 minutes
55+
false
56+
);
57+
private TaskManagerMonitor.Configuration driveMonitorConfig = new TaskManagerMonitor.Configuration(
58+
30 * 1000, // 30 seconds
59+
1 * 60 * 1000, // 1 minute
60+
15 * 60 * 1000, // 15 minutes
61+
false
62+
);
63+
private TaskManagerMonitor.Configuration unmanagedMonitorConfig = new TaskManagerMonitor.Configuration(
64+
60 * 1000, // 1 minute
65+
5 * 60 * 1000, // 5 minutes
66+
15 * 60 * 1000, // 15 minutes
67+
false
68+
);
69+
5170
@Override
5271
public void add(Application app) {
5372
if (this.app == null)
@@ -75,6 +94,24 @@ public void setDrivesProvider(DrivesProvider provider) {
7594
if (Threading.isInitialized()) throw new IllegalStateException(ERROR_ALREADY_INITIALIZED);
7695
drivesProvider = provider;
7796
}
97+
98+
/** Set the monitoring configuration for CPU tasks. */
99+
public void setCpuMonitorConfig(TaskManagerMonitor.Configuration config) {
100+
if (Threading.isInitialized()) throw new IllegalStateException(ERROR_ALREADY_INITIALIZED);
101+
cpuMonitorConfig = config;
102+
}
103+
104+
/** Set the monitoring configuration for drive tasks. */
105+
public void setDriveMonitorConfig(TaskManagerMonitor.Configuration config) {
106+
if (Threading.isInitialized()) throw new IllegalStateException(ERROR_ALREADY_INITIALIZED);
107+
driveMonitorConfig = config;
108+
}
109+
110+
/** Set the monitoring configuration for unmanaged tasks. */
111+
public void setUnmanagedMonitorConfig(TaskManagerMonitor.Configuration config) {
112+
if (Threading.isInitialized()) throw new IllegalStateException(ERROR_ALREADY_INITIALIZED);
113+
unmanagedMonitorConfig = config;
114+
}
78115

79116
private static long logThreadingInterval = 30000;
80117

@@ -90,16 +127,15 @@ public void start() {
90127
app.getThreadFactory(),
91128
SimpleTaskPriorityManager.class,
92129
nbCPUThreads,
130+
cpuMonitorConfig,
93131
drivesProvider,
94-
nbUnmanagedThreads
132+
driveMonitorConfig,
133+
nbUnmanagedThreads,
134+
unmanagedMonitorConfig
95135
);
96136

97137
// debugging
98138
if (app.isDebugMode()) {
99-
Threading.MONITOR_CONFIG_CPU.checkLocksOnBlockedTasks = true;
100-
Threading.MONITOR_CONFIG_DRIVE.checkLocksOnBlockedTasks = true;
101-
Threading.MONITOR_CONFIG_UNMANAGED.checkLocksOnBlockedTasks = true;
102-
103139
final Logger logger = app.getLoggerFactory().getLogger("Threading Status");
104140
class ThreadingLogger extends Thread implements Closeable {
105141
ThreadingLogger() {
@@ -153,6 +189,11 @@ public LibrariesManager getSystemLibraries() {
153189
return app.getLibrariesManager();
154190
}
155191

192+
@Override
193+
public boolean currentThreadIsSystem() {
194+
return true;
195+
}
196+
156197
@Override
157198
public void toClose(Closeable c) {
158199
synchronized (toCloseSync) { toCloseSync.add(c); }

net.lecousin.core/src/main/java/net/lecousin/framework/application/launcher/DynamicLibrariesManager.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
import net.lecousin.framework.concurrent.async.AsyncSupplier;
4646
import net.lecousin.framework.concurrent.async.IAsync;
4747
import net.lecousin.framework.concurrent.async.JoinPoint;
48-
import net.lecousin.framework.concurrent.tasks.drives.FullReadFileTask;
48+
import net.lecousin.framework.concurrent.tasks.drives.ReadFullFile;
4949
import net.lecousin.framework.concurrent.threads.Task;
5050
import net.lecousin.framework.concurrent.threads.Task.Priority;
5151
import net.lecousin.framework.exception.NoException;
@@ -135,7 +135,7 @@ public ApplicationClassLoader start(Application app) {
135135
}
136136

137137
private void loadSplashFile(File splashFile) {
138-
Task<byte[], IOException> read = FullReadFileTask.create(splashFile, Task.Priority.URGENT);
138+
Task<byte[], IOException> read = ReadFullFile.create(splashFile, Task.Priority.URGENT);
139139
read.start();
140140
Task<Void,NoException> load = Task.cpu("Loading splash image", Task.Priority.URGENT, () -> {
141141
ImageIcon img = new ImageIcon(read.getOutput().getResult());
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@
99
import net.lecousin.framework.concurrent.threads.Task.Priority;
1010

1111
/** Task to read all bytes from a file. */
12-
public class FullReadFileTask implements Executable<byte[],IOException> {
12+
public class ReadFullFile implements Executable<byte[],IOException> {
1313

1414
/** Create task. */
1515
public static Task<byte[],IOException> create(File file, Priority priority) {
16-
return Task.file(file, "Read full content of " + file.getAbsolutePath(), priority, new FullReadFileTask(file), null);
16+
return Task.file(file, "Read full content of " + file.getAbsolutePath(), priority, new ReadFullFile(file), null);
1717
}
1818

1919
/** Constructor. */
20-
public FullReadFileTask(File file) {
20+
public ReadFullFile(File file) {
2121
this.file = file;
2222
}
2323

net.lecousin.core/src/main/java/net/lecousin/framework/concurrent/threads/DrivesThreadingManager.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@ public class DrivesThreadingManager {
2525
DrivesThreadingManager(
2626
ThreadFactory threadFactory,
2727
Class<? extends TaskPriorityManager> taskPriorityManagerClass,
28-
DrivesProvider drivesProvider
28+
DrivesProvider drivesProvider,
29+
TaskManagerMonitor.Configuration driveMonitoring
2930
) {
3031
this.threadFactory = threadFactory;
3132
this.taskPriorityManagerClass = taskPriorityManagerClass;
33+
this.driveMonitoring = driveMonitoring;
3234
rootResources = new HashMap<>();
3335
rootManagers = new HashMap<>();
3436
managers = new HashMap<>();
@@ -47,7 +49,7 @@ public class DrivesThreadingManager {
4749
prio = new SimpleTaskPriorityManager();
4850
}
4951
TaskManager tm = new MonoThreadTaskManager(
50-
DRIVE + path, resource, threadFactory, prio, Threading.MONITOR_CONFIG_DRIVE);
52+
DRIVE + path, resource, threadFactory, prio, driveMonitoring);
5153
tm.start();
5254
rootResources.put(path, resource);
5355
rootManagers.put(path, tm);
@@ -64,6 +66,7 @@ public class DrivesThreadingManager {
6466
private Map<String, Object> rootResources;
6567
private Map<String, TaskManager> rootManagers;
6668
private Map<Object, TaskManager> managers;
69+
private TaskManagerMonitor.Configuration driveMonitoring;
6770

6871
/** Return the associated resource for the given file. */
6972
public Object getResource(File file) {
@@ -129,6 +132,14 @@ public String getPartitionPath(String path) {
129132
return null;
130133
}
131134

135+
void setMonitoringConfiguration(TaskManagerMonitor.Configuration config) {
136+
synchronized (rootManagers) {
137+
driveMonitoring = config;
138+
for (TaskManager tm : rootManagers.values())
139+
tm.getMonitor().setConfiguration(config);
140+
}
141+
}
142+
132143
/** Interface to provide drives and partitions. */
133144
public static interface DrivesProvider {
134145
/** Register listeners. */
@@ -171,10 +182,10 @@ private void newDrive(Triple<Object, List<File>, Boolean> driveAndPartitions) {
171182
TaskManager tm;
172183
if (multiThread)
173184
tm = new MultiThreadTaskManager(
174-
DRIVE + drive.toString(), drive, 2, threadFactory, prio, Threading.MONITOR_CONFIG_DRIVE);
185+
DRIVE + drive.toString(), drive, 2, threadFactory, prio, driveMonitoring);
175186
else
176187
tm = new MonoThreadTaskManager(
177-
DRIVE + drive.toString(), drive, threadFactory, prio, Threading.MONITOR_CONFIG_DRIVE);
188+
DRIVE + drive.toString(), drive, threadFactory, prio, driveMonitoring);
178189
tm.start();
179190
synchronized (managers) {
180191
managers.put(drive, tm);

net.lecousin.core/src/main/java/net/lecousin/framework/concurrent/threads/TaskManagerMonitor.java

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,11 @@
1515
public final class TaskManagerMonitor {
1616

1717
/** Configuration. */
18-
@SuppressWarnings({
19-
"squid:ClassVariableVisibilityCheck",
20-
"squid:S1444" // field not final
21-
})
2218
public static class Configuration {
23-
public int taskExecutionMillisecondsBeforeToWarn;
24-
public int taskExecutionMillisecondsBeforeToPutAside;
25-
public int taskExecutionMillisecondsBeforeToKill;
26-
public boolean checkLocksOnBlockedTasks;
19+
private int taskExecutionMillisecondsBeforeToWarn;
20+
private int taskExecutionMillisecondsBeforeToPutAside;
21+
private int taskExecutionMillisecondsBeforeToKill;
22+
private boolean checkLocksOnBlockedTasks;
2723

2824
/** Constructor. */
2925
public Configuration(
@@ -37,6 +33,16 @@ public Configuration(
3733
this.taskExecutionMillisecondsBeforeToKill = taskExecutionMillisecondsBeforeToKill;
3834
this.checkLocksOnBlockedTasks = checkLocksOnBlockedTasks;
3935
}
36+
37+
/** Make a copy of this configuration. */
38+
public Configuration duplicate() {
39+
return new Configuration(
40+
taskExecutionMillisecondsBeforeToWarn,
41+
taskExecutionMillisecondsBeforeToPutAside,
42+
taskExecutionMillisecondsBeforeToKill,
43+
checkLocksOnBlockedTasks
44+
);
45+
}
4046
}
4147

4248
TaskManagerMonitor(TaskManager manager, Configuration config) {
@@ -57,9 +63,10 @@ public Configuration getConfiguration() {
5763
return config;
5864
}
5965

60-
/** Check tasks now. */
61-
public void checkNow() {
66+
void setConfiguration(Configuration config) {
6267
synchronized (thread.lock) {
68+
this.config = config;
69+
thread.wait = 0;
6370
thread.lock.notify();
6471
}
6572
}
@@ -68,11 +75,12 @@ private class Monitor implements Runnable, Closeable {
6875

6976
private Object lock = new Object();
7077
private boolean closed = false;
78+
private long wait;
7179

7280
@Override
7381
@SuppressWarnings("squid:S2142") // InterruptedException
7482
public void run() {
75-
long wait = config.taskExecutionMillisecondsBeforeToWarn;
83+
wait = config.taskExecutionMillisecondsBeforeToWarn;
7684
while (!closed) {
7785
synchronized (lock) {
7886
if (wait > 0)

net.lecousin.core/src/main/java/net/lecousin/framework/concurrent/threads/Threading.java

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -38,27 +38,6 @@ public static Logger getLogger() {
3838
return logger;
3939
}
4040

41-
public static final TaskManagerMonitor.Configuration MONITOR_CONFIG_CPU = new TaskManagerMonitor.Configuration(
42-
60 * 1000, // 1 minute
43-
5 * 60 * 1000, // 5 minutes
44-
15 * 60 * 1000, // 15 minutes
45-
false
46-
);
47-
48-
public static final TaskManagerMonitor.Configuration MONITOR_CONFIG_DRIVE = new TaskManagerMonitor.Configuration(
49-
30 * 1000, // 30 seconds
50-
1 * 60 * 1000, // 1 minute
51-
15 * 60 * 1000, // 15 minutes
52-
false
53-
);
54-
55-
public static final TaskManagerMonitor.Configuration MONITOR_CONFIG_UNMANAGED = new TaskManagerMonitor.Configuration(
56-
60 * 1000, // 1 minute
57-
5 * 60 * 1000, // 5 minutes
58-
15 * 60 * 1000, // 15 minutes
59-
false
60-
);
61-
6241
public static boolean traceBlockingTasks = System.getProperty("lc.traceBlockingTasks") != null;
6342
public static boolean traceTaskTime = System.getProperty("lc.traceTaskTime") != null;
6443

@@ -79,38 +58,38 @@ public static void init(
7958
ThreadFactory threadFactory,
8059
Class<? extends TaskPriorityManager> taskPriorityManagerClass,
8160
int nbCPUThreads,
61+
TaskManagerMonitor.Configuration cpuMonitoring,
8262
DrivesProvider drivesProvider,
83-
int nbUnmanagedThreads
63+
TaskManagerMonitor.Configuration driveMonitoring,
64+
int nbUnmanagedThreads,
65+
TaskManagerMonitor.Configuration unmanagedMonitoring
8466
) {
8567
if (isInitialized()) throw new IllegalStateException("Threading has been already initialized.");
8668
logger = LCCore.get().getThreadingLogger();
8769
TaskScheduler.init();
88-
TaskPriorityManager prio;
70+
TaskPriorityManager prioCpu;
71+
TaskPriorityManager prioDrive;
8972
try {
90-
prio = taskPriorityManagerClass.newInstance();
73+
prioCpu = taskPriorityManagerClass.newInstance();
74+
prioDrive = taskPriorityManagerClass.newInstance();
9175
} catch (Exception e) {
9276
Threading.getLogger().error("Unable to instantiate " + taskPriorityManagerClass.getName());
93-
prio = new SimpleTaskPriorityManager();
77+
prioCpu = new SimpleTaskPriorityManager();
78+
prioDrive = new SimpleTaskPriorityManager();
9479
}
9580
cpuManager = new MultiThreadTaskManager(
9681
"CPU",
9782
Threading.CPU,
9883
nbCPUThreads > 0 ? nbCPUThreads : Runtime.getRuntime().availableProcessors(),
9984
threadFactory,
100-
prio,
101-
MONITOR_CONFIG_CPU
85+
prioCpu,
86+
cpuMonitoring
10287
);
10388
cpuManager.start();
10489
resources.put(CPU, cpuManager);
105-
drivesManager = new DrivesThreadingManager(threadFactory, taskPriorityManagerClass, drivesProvider);
106-
try {
107-
prio = taskPriorityManagerClass.newInstance();
108-
} catch (Exception e) {
109-
Threading.getLogger().error("Unable to instantiate " + taskPriorityManagerClass.getName());
110-
prio = new SimpleTaskPriorityManager();
111-
}
90+
drivesManager = new DrivesThreadingManager(threadFactory, taskPriorityManagerClass, drivesProvider, driveMonitoring);
11291
unmanagedManager = new ThreadPoolTaskManager(
113-
"Unmanaged tasks manager", UNMANAGED, nbUnmanagedThreads, threadFactory, prio, MONITOR_CONFIG_UNMANAGED);
92+
"Unmanaged tasks manager", UNMANAGED, nbUnmanagedThreads, threadFactory, prioDrive, unmanagedMonitoring);
11493
resources.put(UNMANAGED, unmanagedManager);
11594
LCCore.get().toClose(new StopMultiThreading());
11695
synchronized (resources) {
@@ -266,6 +245,24 @@ public static TaskExecutor getTaskExecutor() {
266245
return executor != null ? executor.getCurrentTask() : null;
267246
}
268247

248+
/** Set the monitoring configuration for CPU tasks. */
249+
public static void setCpuMonitorConfiguration(TaskManagerMonitor.Configuration config) {
250+
if (!LCCore.get().currentThreadIsSystem()) throw new IllegalThreadStateException();
251+
cpuManager.getMonitor().setConfiguration(config);
252+
}
253+
254+
/** Set the monitoring configuration for drives tasks. */
255+
public static void setDrivesMonitorConfiguration(TaskManagerMonitor.Configuration config) {
256+
if (!LCCore.get().currentThreadIsSystem()) throw new IllegalThreadStateException();
257+
drivesManager.setMonitoringConfiguration(config);
258+
}
259+
260+
/** Set the monitoring configuration for unmanaged tasks. */
261+
public static void setUnmanagedMonitorConfiguration(TaskManagerMonitor.Configuration config) {
262+
if (!LCCore.get().currentThreadIsSystem()) throw new IllegalThreadStateException();
263+
unmanagedManager.getMonitor().setConfiguration(config);
264+
}
265+
269266
/** Wait for the given tasks to be done. */
270267
public static <TError extends Exception> void waitFinished(Collection<? extends Task<?,TError>> tasks) throws TError, CancelException {
271268
for (Task<?,TError> t : tasks) {

0 commit comments

Comments
 (0)