Skip to content

Commit 4ef6b0f

Browse files
committed
add function to delete old recordings when more space is requested
1 parent 10a9b94 commit 4ef6b0f

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed

photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NTDriverStation.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,56 @@ public String printMatchData() {
134134
return message;
135135
}
136136

137+
/**
138+
* Compares two match data strings and returns a negative, 0, or a postive if the first is less
139+
* than, equal to, or greater than the second.
140+
*
141+
* @param first
142+
* @param second
143+
* @return a negative, 0, or a positive if the first is less than, equal to, or greater than the
144+
* second
145+
*/
146+
public static int compareMatchData(String first, String second) {
147+
String[] firstParts = first.split(", ");
148+
String[] secondParts = second.split(", ");
149+
150+
String firstMatchInfo = firstParts[1].split(" ")[1];
151+
String secondMatchInfo = secondParts[1].split(" ")[1];
152+
153+
String firstType = firstMatchInfo.substring(0, 1);
154+
String secondType = secondMatchInfo.substring(0, 1);
155+
156+
int firstCmp;
157+
int secondCmp;
158+
switch (firstType) {
159+
case "P" -> firstCmp = 1;
160+
case "Q" -> firstCmp = 2;
161+
case "E" -> firstCmp = 3;
162+
default -> firstCmp = 0;
163+
}
164+
switch (secondType) {
165+
case "P" -> secondCmp = 1;
166+
case "Q" -> secondCmp = 2;
167+
case "E" -> secondCmp = 3;
168+
default -> secondCmp = 0;
169+
}
170+
171+
if (Integer.compare(firstCmp, secondCmp) != 0) {
172+
return Integer.compare(firstCmp, secondCmp);
173+
}
174+
175+
// same type, compare match numbers
176+
int firstMatchNumber = Integer.parseInt(firstMatchInfo.substring(1));
177+
int secondMatchNumber = Integer.parseInt(secondMatchInfo.substring(1));
178+
if (Integer.compare(firstMatchNumber, secondMatchNumber) != 0) {
179+
return Integer.compare(firstMatchNumber, secondMatchNumber);
180+
}
181+
// same match number, compare replay numbers
182+
int firstReplay = Integer.parseInt(firstParts[2].split(" ")[1]);
183+
int secondReplay = Integer.parseInt(secondParts[2].split(" ")[1]);
184+
return Integer.compare(firstReplay, secondReplay);
185+
}
186+
137187
// Copied from
138188
// https://github.com/wpilibsuite/allwpilib/blob/07192285f65321a2f7363227a2216f09b715252d/hal/src/main/java/edu/wpi/first/hal/DriverStationJNI.java#L123C1-L140C4
139189
// TODO: upstream!

photon-core/src/main/java/org/photonvision/common/hardware/HardwareManager.java

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,16 @@
2020
import edu.wpi.first.networktables.IntegerPublisher;
2121
import edu.wpi.first.networktables.IntegerSubscriber;
2222
import java.io.IOException;
23+
import java.nio.file.Path;
24+
import java.util.ArrayList;
2325
import java.util.HashMap;
2426
import java.util.Map;
2527
import org.photonvision.common.configuration.ConfigManager;
2628
import org.photonvision.common.configuration.HardwareConfig;
2729
import org.photonvision.common.configuration.HardwareSettings;
30+
import org.photonvision.common.configuration.PathManager;
2831
import org.photonvision.common.dataflow.networktables.NTDataChangeListener;
32+
import org.photonvision.common.dataflow.networktables.NTDriverStation;
2933
import org.photonvision.common.dataflow.networktables.NetworkTablesManager;
3034
import org.photonvision.common.hardware.GPIO.CustomGPIO;
3135
import org.photonvision.common.hardware.GPIO.pi.PigpioSocket;
@@ -228,4 +232,89 @@ private void statusLEDUpdate() {
228232
public void publishMetrics() {
229233
metricsManager.publishMetrics();
230234
}
235+
236+
/**
237+
* Ensures there is enough space for new recordings by clearing stored recordings to free up disk
238+
* space. This method should delete the oldest recordings, prioritizing recordings from matches
239+
* over practice sessions regardless of age.
240+
*
241+
* @param requestedSpace The amount of space to free in MB
242+
* @return true if enough space was cleared, false otherwise
243+
*/
244+
public boolean reserveRecordingSpace(double requestedSpace) {
245+
if (metricsManager.getDiskSpaceAvailable() > requestedSpace * 1024) {
246+
return true; // Enough space already available
247+
}
248+
249+
Path recordingsDir = PathManager.getInstance().getRootFolder().resolve("recordings");
250+
251+
// Create a list of all the recordings
252+
ArrayList<Path> recordings = new ArrayList<>();
253+
try {
254+
if (!java.nio.file.Files.exists(recordingsDir)
255+
|| !java.nio.file.Files.isDirectory(recordingsDir)) {
256+
logger.error("Recordings directory does not exist");
257+
return false; // No recordings directory
258+
}
259+
260+
try (var cameraStream = java.nio.file.Files.list(recordingsDir)) {
261+
cameraStream
262+
.filter(java.nio.file.Files::isDirectory)
263+
.forEach(
264+
cameraDir -> {
265+
try (var recStream = java.nio.file.Files.list(cameraDir)) {
266+
recStream.filter(java.nio.file.Files::isDirectory).forEach(recordings::add);
267+
} catch (Exception e) {
268+
// skip unreadable camera folder
269+
}
270+
});
271+
}
272+
} catch (Exception e) {
273+
return false; // Unable to list recordings
274+
}
275+
276+
if (recordings.isEmpty()) {
277+
return false; // No recordings to delete
278+
}
279+
280+
// Create practice list and match list
281+
ArrayList<Path> matchRecordings = new ArrayList<>();
282+
ArrayList<Path> practiceRecordings = new ArrayList<>();
283+
284+
for (Path rec : recordings) {
285+
String dirName = rec.getFileName().toString().toLowerCase();
286+
if (dirName.startsWith("event")) {
287+
matchRecordings.add(rec);
288+
} else {
289+
practiceRecordings.add(rec);
290+
}
291+
}
292+
293+
// Sort both lists based on solely the filename
294+
matchRecordings.sort(
295+
(a, b) ->
296+
NTDriverStation.compareMatchData(
297+
a.getFileName().toString(), b.getFileName().toString()));
298+
practiceRecordings.sort(
299+
(a, b) -> a.getFileName().toString().compareTo(b.getFileName().toString()));
300+
301+
while (requestedSpace * 1024
302+
> HardwareManager.getInstance().metricsManager.getDiskSpaceAvailable()) {
303+
Path toDelete = null;
304+
if (!practiceRecordings.isEmpty()) {
305+
toDelete = practiceRecordings.remove(0);
306+
} else if (!matchRecordings.isEmpty()) {
307+
toDelete = matchRecordings.remove(0);
308+
} else {
309+
return false; // No recordings left to delete
310+
}
311+
try {
312+
java.nio.file.Files.delete(toDelete);
313+
} catch (Exception e) {
314+
// Ignore errors during deletion
315+
}
316+
}
317+
318+
return true;
319+
}
231320
}

0 commit comments

Comments
 (0)