Add new event for when the disk space is exhausted

This commit is contained in:
0xb00bface 2020-08-21 17:09:07 +02:00
parent 3351a976ae
commit 7bb33568cf
9 changed files with 96 additions and 4 deletions

View File

@ -5,8 +5,13 @@
* login / favorites
* media player isn't working because of their authetication mechanism
* 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
* 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
========================

View File

@ -23,6 +23,7 @@ import ctbrec.event.EventHandlerConfiguration;
import ctbrec.event.EventHandlerConfiguration.ActionConfiguration;
import ctbrec.event.EventHandlerConfiguration.PredicateConfiguration;
import ctbrec.event.ExecuteProgram;
import ctbrec.event.MatchAllPredicate;
import ctbrec.event.ModelPredicate;
import ctbrec.event.ModelStatePredicate;
import ctbrec.event.RecordingStatePredicate;
@ -152,6 +153,11 @@ public class ActionSettingsPanel extends GridPane {
pc.getConfiguration().put("state", recordingState.getValue().name());
pc.setName("state = " + recordingState.getValue().toString());
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()) {
PredicateConfiguration pc = new PredicateConfiguration();
@ -200,7 +206,7 @@ public class ActionSettingsPanel extends GridPane {
if(event.getValue() == Event.Type.RECORDING_STATUS_CHANGED && recordingState.getValue() == null) {
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\"");
}
if(!(showNotification.isSelected() || playSound.isSelected() || executeProgram.isSelected())) {
@ -231,10 +237,23 @@ public class ActionSettingsPanel extends GridPane {
event.getItems().clear();
event.getItems().add(Event.Type.MODEL_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.getSelectionModel().select(Event.Type.MODEL_STATUS_CHANGED);
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);
modelState.getItems().clear();
modelState.getItems().addAll(Model.State.values());

View File

@ -118,4 +118,8 @@ public class ListSelectionPane<T extends Comparable<T>> extends GridPane {
public boolean isAllSelected() {
return selectAll.isSelected();
}
public void selectAll() {
selectAll.setSelected(true);
}
}

View File

@ -18,7 +18,12 @@ public abstract class Event {
/**
* 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;

View File

@ -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
}
}

View File

@ -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];
}
}

View File

@ -49,6 +49,7 @@ import ctbrec.Recording.State;
import ctbrec.event.Event;
import ctbrec.event.EventBusHolder;
import ctbrec.event.ModelIsOnlineEvent;
import ctbrec.event.NoSpaceLeftEvent;
import ctbrec.event.RecordingStateChangedEvent;
import ctbrec.io.HttpClient;
import ctbrec.recorder.download.Download;
@ -111,6 +112,7 @@ public class NextGenLocalRecorder implements Recorder {
if (!recordingProcesses.isEmpty() && !enoughSpaceForRecording()) {
LOG.info("No space left -> Stopping all recordings");
stopRecordingProcesses();
EventBusHolder.BUS.post(new NoSpaceLeftEvent());
}
} catch (IOException e) {
LOG.error("Couldn't check space left on device", e);
@ -577,7 +579,7 @@ public class NextGenLocalRecorder implements Recorder {
boolean enoughSpaceForRecording() throws IOException {
long minimum = config.getSettings().minimumSpaceLeftInBytes;
if (minimum == 0) { // 0 means don't check
return true;
return getFreeSpaceBytes() > 100 * 1024 * 1024; // leave at least 100 MiB free
} else {
return getFreeSpaceBytes() > minimum;
}

View File

@ -24,6 +24,7 @@ import ctbrec.Hmac;
import ctbrec.Model;
import ctbrec.Recording;
import ctbrec.event.EventBusHolder;
import ctbrec.event.NoSpaceLeftEvent;
import ctbrec.event.RecordingStateChangedEvent;
import ctbrec.io.BandwidthMeter;
import ctbrec.io.HttpClient;
@ -57,6 +58,7 @@ public class RemoteRecorder implements Recorder {
private List<Site> sites;
private long spaceTotal = -1;
private long spaceFree = -1;
private boolean noSpaceLeftDetected = false;
private Config config;
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_HTTP_STATUS = "Couldn't synchronize with server. HTTP status: {} - {}";
private volatile boolean running = false;
private static final long ONE_HUNDRED_MIB = 100 * 1024 * 1024;
public SyncThread() {
setName("RemoteRecorder SyncThread");
@ -218,6 +221,16 @@ public class RemoteRecorder implements Recorder {
long throughput = resp.getLong("throughput");
Duration timeframe = Duration.ofSeconds(resp.getInt("throughputTimeframe"));
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 {
LOG.error(COULDNT_SYNCHRONIZE_WITH_SERVER_HTTP_STATUS, response.code(), json);
}

View File

@ -21,6 +21,7 @@ import org.slf4j.LoggerFactory;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import ctbrec.Config;
import ctbrec.Model;
import ctbrec.Recording;
import ctbrec.io.BandwidthMeter;
@ -211,6 +212,7 @@ public class RecorderServlet extends AbstractCtbrecServlet {
jsonResponse.put("spaceFree", recorder.getFreeSpaceBytes());
jsonResponse.put("throughput", BandwidthMeter.getThroughput());
jsonResponse.put("throughputTimeframe", BandwidthMeter.MEASURE_TIMEFRAME.getSeconds());
jsonResponse.put("minimumSpaceLeftInBytes", Config.getInstance().getSettings().minimumSpaceLeftInBytes);
resp.getWriter().write(jsonResponse.toString());
break;
case "changePriority":