forked from j62/ctbrec
Add new event for when the disk space is exhausted
This commit is contained in:
parent
3351a976ae
commit
7bb33568cf
|
@ -5,8 +5,13 @@
|
||||||
* login / favorites
|
* login / favorites
|
||||||
* media player isn't working because of their authetication mechanism
|
* media player isn't working because of their authetication mechanism
|
||||||
* Fixed bug in recorder servlet. Actions for unpin and notes were mixed up
|
* Fixed bug in recorder servlet. Actions for unpin and notes were mixed up
|
||||||
|
and not properly synchronized between the server and the client
|
||||||
* Recordings now start immediately for newly added models
|
* Recordings now start immediately for newly added models
|
||||||
* Added confirmation dialog for "Pause All" and "Resume All"
|
* Added confirmation dialog for "Pause All", "Resume All" and shutdown
|
||||||
|
* Fix: recording started event was not fired in client / server mode
|
||||||
|
* CTB Recorder now stops recording, if less than 100 MiB space is left
|
||||||
|
* New event, which is fired, if the disk is full (or less than the configured
|
||||||
|
threshold is available)
|
||||||
|
|
||||||
3.8.6
|
3.8.6
|
||||||
========================
|
========================
|
||||||
|
|
|
@ -23,6 +23,7 @@ import ctbrec.event.EventHandlerConfiguration;
|
||||||
import ctbrec.event.EventHandlerConfiguration.ActionConfiguration;
|
import ctbrec.event.EventHandlerConfiguration.ActionConfiguration;
|
||||||
import ctbrec.event.EventHandlerConfiguration.PredicateConfiguration;
|
import ctbrec.event.EventHandlerConfiguration.PredicateConfiguration;
|
||||||
import ctbrec.event.ExecuteProgram;
|
import ctbrec.event.ExecuteProgram;
|
||||||
|
import ctbrec.event.MatchAllPredicate;
|
||||||
import ctbrec.event.ModelPredicate;
|
import ctbrec.event.ModelPredicate;
|
||||||
import ctbrec.event.ModelStatePredicate;
|
import ctbrec.event.ModelStatePredicate;
|
||||||
import ctbrec.event.RecordingStatePredicate;
|
import ctbrec.event.RecordingStatePredicate;
|
||||||
|
@ -152,6 +153,11 @@ public class ActionSettingsPanel extends GridPane {
|
||||||
pc.getConfiguration().put("state", recordingState.getValue().name());
|
pc.getConfiguration().put("state", recordingState.getValue().name());
|
||||||
pc.setName("state = " + recordingState.getValue().toString());
|
pc.setName("state = " + recordingState.getValue().toString());
|
||||||
config.getPredicates().add(pc);
|
config.getPredicates().add(pc);
|
||||||
|
} else if(event.getValue() == Event.Type.NO_SPACE_LEFT) {
|
||||||
|
PredicateConfiguration pc = new PredicateConfiguration();
|
||||||
|
pc.setType(MatchAllPredicate.class.getName());
|
||||||
|
pc.setName("no space left");
|
||||||
|
config.getPredicates().add(pc);
|
||||||
}
|
}
|
||||||
if(!modelSelectionPane.isAllSelected()) {
|
if(!modelSelectionPane.isAllSelected()) {
|
||||||
PredicateConfiguration pc = new PredicateConfiguration();
|
PredicateConfiguration pc = new PredicateConfiguration();
|
||||||
|
@ -200,7 +206,7 @@ public class ActionSettingsPanel extends GridPane {
|
||||||
if(event.getValue() == Event.Type.RECORDING_STATUS_CHANGED && recordingState.getValue() == null) {
|
if(event.getValue() == Event.Type.RECORDING_STATUS_CHANGED && recordingState.getValue() == null) {
|
||||||
throw new IllegalStateException("Select a state");
|
throw new IllegalStateException("Select a state");
|
||||||
}
|
}
|
||||||
if(modelSelectionPane.getSelectedItems().isEmpty() && !modelSelectionPane.isAllSelected()) {
|
if(event.getValue() != Event.Type.NO_SPACE_LEFT && modelSelectionPane.getSelectedItems().isEmpty() && !modelSelectionPane.isAllSelected()) {
|
||||||
throw new IllegalStateException("Select one or more models or tick off \"all\"");
|
throw new IllegalStateException("Select one or more models or tick off \"all\"");
|
||||||
}
|
}
|
||||||
if(!(showNotification.isSelected() || playSound.isSelected() || executeProgram.isSelected())) {
|
if(!(showNotification.isSelected() || playSound.isSelected() || executeProgram.isSelected())) {
|
||||||
|
@ -231,10 +237,23 @@ public class ActionSettingsPanel extends GridPane {
|
||||||
event.getItems().clear();
|
event.getItems().clear();
|
||||||
event.getItems().add(Event.Type.MODEL_STATUS_CHANGED);
|
event.getItems().add(Event.Type.MODEL_STATUS_CHANGED);
|
||||||
event.getItems().add(Event.Type.RECORDING_STATUS_CHANGED);
|
event.getItems().add(Event.Type.RECORDING_STATUS_CHANGED);
|
||||||
|
event.getItems().add(Event.Type.NO_SPACE_LEFT);
|
||||||
event.setOnAction(evt -> modelState.setVisible(event.getSelectionModel().getSelectedItem() == Event.Type.MODEL_STATUS_CHANGED));
|
event.setOnAction(evt -> modelState.setVisible(event.getSelectionModel().getSelectedItem() == Event.Type.MODEL_STATUS_CHANGED));
|
||||||
event.getSelectionModel().select(Event.Type.MODEL_STATUS_CHANGED);
|
event.getSelectionModel().select(Event.Type.MODEL_STATUS_CHANGED);
|
||||||
layout.add(event, 1, row++);
|
layout.add(event, 1, row++);
|
||||||
|
|
||||||
|
event.getSelectionModel().selectedItemProperty().addListener((obs, oldV, newV) -> {
|
||||||
|
boolean modelRelatedStuffDisabled = false;
|
||||||
|
if(newV == Event.Type.NO_SPACE_LEFT) {
|
||||||
|
modelRelatedStuffDisabled = true;
|
||||||
|
modelSelectionPane.selectAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
modelState.setDisable(modelRelatedStuffDisabled);
|
||||||
|
recordingState.setDisable(modelRelatedStuffDisabled);
|
||||||
|
modelSelectionPane.setDisable(modelRelatedStuffDisabled);
|
||||||
|
});
|
||||||
|
|
||||||
layout.add(new Label("State"), 0, row);
|
layout.add(new Label("State"), 0, row);
|
||||||
modelState.getItems().clear();
|
modelState.getItems().clear();
|
||||||
modelState.getItems().addAll(Model.State.values());
|
modelState.getItems().addAll(Model.State.values());
|
||||||
|
|
|
@ -118,4 +118,8 @@ public class ListSelectionPane<T extends Comparable<T>> extends GridPane {
|
||||||
public boolean isAllSelected() {
|
public boolean isAllSelected() {
|
||||||
return selectAll.isSelected();
|
return selectAll.isSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void selectAll() {
|
||||||
|
selectAll.setSelected(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,12 @@ public abstract class Event {
|
||||||
/**
|
/**
|
||||||
* This event is fired whenever the state of a recording changes.
|
* This event is fired whenever the state of a recording changes.
|
||||||
*/
|
*/
|
||||||
RECORDING_STATUS_CHANGED("recording status changed");
|
RECORDING_STATUS_CHANGED("recording status changed"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This event is fired when the disk space is exhausted
|
||||||
|
*/
|
||||||
|
NO_SPACE_LEFT("no space left");
|
||||||
|
|
||||||
private String desc;
|
private String desc;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package ctbrec.event;
|
||||||
|
|
||||||
|
import ctbrec.event.EventHandlerConfiguration.PredicateConfiguration;
|
||||||
|
|
||||||
|
public class MatchAllPredicate extends EventPredicate {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(Event evt) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(PredicateConfiguration pc) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package ctbrec.event;
|
||||||
|
|
||||||
|
public class NoSpaceLeftEvent extends Event {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.NO_SPACE_LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "No space left on device";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "No space left on device";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getExecutionParams() {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -49,6 +49,7 @@ import ctbrec.Recording.State;
|
||||||
import ctbrec.event.Event;
|
import ctbrec.event.Event;
|
||||||
import ctbrec.event.EventBusHolder;
|
import ctbrec.event.EventBusHolder;
|
||||||
import ctbrec.event.ModelIsOnlineEvent;
|
import ctbrec.event.ModelIsOnlineEvent;
|
||||||
|
import ctbrec.event.NoSpaceLeftEvent;
|
||||||
import ctbrec.event.RecordingStateChangedEvent;
|
import ctbrec.event.RecordingStateChangedEvent;
|
||||||
import ctbrec.io.HttpClient;
|
import ctbrec.io.HttpClient;
|
||||||
import ctbrec.recorder.download.Download;
|
import ctbrec.recorder.download.Download;
|
||||||
|
@ -111,6 +112,7 @@ public class NextGenLocalRecorder implements Recorder {
|
||||||
if (!recordingProcesses.isEmpty() && !enoughSpaceForRecording()) {
|
if (!recordingProcesses.isEmpty() && !enoughSpaceForRecording()) {
|
||||||
LOG.info("No space left -> Stopping all recordings");
|
LOG.info("No space left -> Stopping all recordings");
|
||||||
stopRecordingProcesses();
|
stopRecordingProcesses();
|
||||||
|
EventBusHolder.BUS.post(new NoSpaceLeftEvent());
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't check space left on device", e);
|
LOG.error("Couldn't check space left on device", e);
|
||||||
|
@ -577,7 +579,7 @@ public class NextGenLocalRecorder implements Recorder {
|
||||||
boolean enoughSpaceForRecording() throws IOException {
|
boolean enoughSpaceForRecording() throws IOException {
|
||||||
long minimum = config.getSettings().minimumSpaceLeftInBytes;
|
long minimum = config.getSettings().minimumSpaceLeftInBytes;
|
||||||
if (minimum == 0) { // 0 means don't check
|
if (minimum == 0) { // 0 means don't check
|
||||||
return true;
|
return getFreeSpaceBytes() > 100 * 1024 * 1024; // leave at least 100 MiB free
|
||||||
} else {
|
} else {
|
||||||
return getFreeSpaceBytes() > minimum;
|
return getFreeSpaceBytes() > minimum;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import ctbrec.Hmac;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
import ctbrec.event.EventBusHolder;
|
import ctbrec.event.EventBusHolder;
|
||||||
|
import ctbrec.event.NoSpaceLeftEvent;
|
||||||
import ctbrec.event.RecordingStateChangedEvent;
|
import ctbrec.event.RecordingStateChangedEvent;
|
||||||
import ctbrec.io.BandwidthMeter;
|
import ctbrec.io.BandwidthMeter;
|
||||||
import ctbrec.io.HttpClient;
|
import ctbrec.io.HttpClient;
|
||||||
|
@ -57,6 +58,7 @@ public class RemoteRecorder implements Recorder {
|
||||||
private List<Site> sites;
|
private List<Site> sites;
|
||||||
private long spaceTotal = -1;
|
private long spaceTotal = -1;
|
||||||
private long spaceFree = -1;
|
private long spaceFree = -1;
|
||||||
|
private boolean noSpaceLeftDetected = false;
|
||||||
|
|
||||||
private Config config;
|
private Config config;
|
||||||
private HttpClient client;
|
private HttpClient client;
|
||||||
|
@ -184,6 +186,7 @@ public class RemoteRecorder implements Recorder {
|
||||||
private static final String COULDNT_SYNCHRONIZE_WITH_SERVER = "Couldn't synchronize with server";
|
private static final String COULDNT_SYNCHRONIZE_WITH_SERVER = "Couldn't synchronize with server";
|
||||||
private static final String COULDNT_SYNCHRONIZE_WITH_SERVER_HTTP_STATUS = "Couldn't synchronize with server. HTTP status: {} - {}";
|
private static final String COULDNT_SYNCHRONIZE_WITH_SERVER_HTTP_STATUS = "Couldn't synchronize with server. HTTP status: {} - {}";
|
||||||
private volatile boolean running = false;
|
private volatile boolean running = false;
|
||||||
|
private static final long ONE_HUNDRED_MIB = 100 * 1024 * 1024;
|
||||||
|
|
||||||
public SyncThread() {
|
public SyncThread() {
|
||||||
setName("RemoteRecorder SyncThread");
|
setName("RemoteRecorder SyncThread");
|
||||||
|
@ -218,6 +221,16 @@ public class RemoteRecorder implements Recorder {
|
||||||
long throughput = resp.getLong("throughput");
|
long throughput = resp.getLong("throughput");
|
||||||
Duration timeframe = Duration.ofSeconds(resp.getInt("throughputTimeframe"));
|
Duration timeframe = Duration.ofSeconds(resp.getInt("throughputTimeframe"));
|
||||||
BandwidthMeter.setThroughput(throughput, timeframe);
|
BandwidthMeter.setThroughput(throughput, timeframe);
|
||||||
|
long minimumSpaceLeftInBytes = resp.optLong("minimumSpaceLeftInBytes");
|
||||||
|
if (minimumSpaceLeftInBytes > 0 && minimumSpaceLeftInBytes >= spaceFree
|
||||||
|
|| minimumSpaceLeftInBytes == 0 && spaceFree < ONE_HUNDRED_MIB) {
|
||||||
|
if (!noSpaceLeftDetected) {
|
||||||
|
EventBusHolder.BUS.post(new NoSpaceLeftEvent());
|
||||||
|
}
|
||||||
|
noSpaceLeftDetected = true;
|
||||||
|
} else {
|
||||||
|
noSpaceLeftDetected = false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG.error(COULDNT_SYNCHRONIZE_WITH_SERVER_HTTP_STATUS, response.code(), json);
|
LOG.error(COULDNT_SYNCHRONIZE_WITH_SERVER_HTTP_STATUS, response.code(), json);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.slf4j.LoggerFactory;
|
||||||
import com.squareup.moshi.JsonAdapter;
|
import com.squareup.moshi.JsonAdapter;
|
||||||
import com.squareup.moshi.Moshi;
|
import com.squareup.moshi.Moshi;
|
||||||
|
|
||||||
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
import ctbrec.io.BandwidthMeter;
|
import ctbrec.io.BandwidthMeter;
|
||||||
|
@ -211,6 +212,7 @@ public class RecorderServlet extends AbstractCtbrecServlet {
|
||||||
jsonResponse.put("spaceFree", recorder.getFreeSpaceBytes());
|
jsonResponse.put("spaceFree", recorder.getFreeSpaceBytes());
|
||||||
jsonResponse.put("throughput", BandwidthMeter.getThroughput());
|
jsonResponse.put("throughput", BandwidthMeter.getThroughput());
|
||||||
jsonResponse.put("throughputTimeframe", BandwidthMeter.MEASURE_TIMEFRAME.getSeconds());
|
jsonResponse.put("throughputTimeframe", BandwidthMeter.MEASURE_TIMEFRAME.getSeconds());
|
||||||
|
jsonResponse.put("minimumSpaceLeftInBytes", Config.getInstance().getSettings().minimumSpaceLeftInBytes);
|
||||||
resp.getWriter().write(jsonResponse.toString());
|
resp.getWriter().write(jsonResponse.toString());
|
||||||
break;
|
break;
|
||||||
case "changePriority":
|
case "changePriority":
|
||||||
|
|
Loading…
Reference in New Issue