[wpiutil] Split DataLog background writer into different class (#6590)

DataLog is now a base class, with DataLogBackgroundWriter being the
background thread version and DataLogWriter being a non-threaded version.

Also split the C header into a separate file to make it more wpiformat friendly.
This commit is contained in:
Peter Johnson
2024-05-12 14:09:43 -07:00
committed by GitHub
parent 305a0657e2
commit 178fe99f12
20 changed files with 1588 additions and 1089 deletions

View File

@@ -14,11 +14,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* A data log. The log file is created immediately upon construction with a temporary filename. The
* file may be renamed at any time using the setFilename() function.
*
* <p>The data log is periodically flushed to disk. It can also be explicitly flushed to disk by
* using the flush() function.
* A data log for high-speed writing of data values.
*
* <p>The finish() function is needed only to indicate in the log that a particular entry is no
* longer being used (it releases the name to ID mapping). The finish() function is not required to
@@ -31,66 +27,14 @@ import java.util.concurrent.ConcurrentMap;
* For this reason (as well as the fact that timestamps can be set to arbitrary values), records in
* the log are not guaranteed to be sorted by timestamp.
*/
public final class DataLog implements AutoCloseable {
public class DataLog implements AutoCloseable {
/**
* Construct a new Data Log. The log will be initially created with a temporary filename.
* Constructs.
*
* @param dir directory to store the log
* @param filename filename to use; if none provided, a random filename is generated of the form
* "wpilog_{}.wpilog"
* @param period time between automatic flushes to disk, in seconds; this is a time/storage
* tradeoff
* @param extraHeader extra header data
* @param impl implementation handle
*/
public DataLog(String dir, String filename, double period, String extraHeader) {
m_impl = DataLogJNI.create(dir, filename, period, extraHeader);
}
/**
* Construct a new Data Log. The log will be initially created with a temporary filename.
*
* @param dir directory to store the log
* @param filename filename to use; if none provided, a random filename is generated of the form
* "wpilog_{}.wpilog"
* @param period time between automatic flushes to disk, in seconds; this is a time/storage
* tradeoff
*/
public DataLog(String dir, String filename, double period) {
this(dir, filename, period, "");
}
/**
* Construct a new Data Log. The log will be initially created with a temporary filename.
*
* @param dir directory to store the log
* @param filename filename to use; if none provided, a random filename is generated of the form
* "wpilog_{}.wpilog"
*/
public DataLog(String dir, String filename) {
this(dir, filename, 0.25);
}
/**
* Construct a new Data Log. The log will be initially created with a temporary filename.
*
* @param dir directory to store the log
*/
public DataLog(String dir) {
this(dir, "", 0.25);
}
/** Construct a new Data Log. The log will be initially created with a temporary filename. */
public DataLog() {
this("");
}
/**
* Change log filename.
*
* @param filename filename
*/
public void setFilename(String filename) {
DataLogJNI.setFilename(m_impl, filename);
protected DataLog(long impl) {
m_impl = impl;
}
/** Explicitly flushes the log data to disk. */
@@ -106,11 +50,7 @@ public final class DataLog implements AutoCloseable {
DataLogJNI.pause(m_impl);
}
/**
* Resumes appending of data records to the log. If called after stop(), opens a new file (with
* random name if SetFilename was not called after stop()) and appends Start records and schema
* data values for all previously started entries and schemas.
*/
/** Resumes appending of data records to the log. */
public void resume() {
DataLogJNI.resume(m_impl);
}
@@ -518,6 +458,8 @@ public final class DataLog implements AutoCloseable {
seen.remove(typeString);
}
private long m_impl;
/** Implementation handle. */
protected long m_impl;
private final ConcurrentMap<String, Integer> m_schemaMap = new ConcurrentHashMap<>();
}

View File

@@ -0,0 +1,86 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.util.datalog;
/**
* A data log background writer that periodically flushes the data log on a background thread. The
* data log file is created immediately upon construction with a temporary filename. The file may be
* renamed at any time using the setFilename() function.
*
* <p>The data log is periodically flushed to disk. It can also be explicitly flushed to disk by
* using the flush() function. This operation is, however, non-blocking.
*/
public final class DataLogBackgroundWriter extends DataLog {
/**
* Construct a new Data Log. The log will be initially created with a temporary filename.
*
* @param dir directory to store the log
* @param filename filename to use; if none provided, a random filename is generated of the form
* "wpilog_{}.wpilog"
* @param period time between automatic flushes to disk, in seconds; this is a time/storage
* tradeoff
* @param extraHeader extra header data
*/
public DataLogBackgroundWriter(String dir, String filename, double period, String extraHeader) {
super(DataLogJNI.bgCreate(dir, filename, period, extraHeader));
}
/**
* Construct a new Data Log. The log will be initially created with a temporary filename.
*
* @param dir directory to store the log
* @param filename filename to use; if none provided, a random filename is generated of the form
* "wpilog_{}.wpilog"
* @param period time between automatic flushes to disk, in seconds; this is a time/storage
* tradeoff
*/
public DataLogBackgroundWriter(String dir, String filename, double period) {
this(dir, filename, period, "");
}
/**
* Construct a new Data Log. The log will be initially created with a temporary filename.
*
* @param dir directory to store the log
* @param filename filename to use; if none provided, a random filename is generated of the form
* "wpilog_{}.wpilog"
*/
public DataLogBackgroundWriter(String dir, String filename) {
this(dir, filename, 0.25);
}
/**
* Construct a new Data Log. The log will be initially created with a temporary filename.
*
* @param dir directory to store the log
*/
public DataLogBackgroundWriter(String dir) {
this(dir, "", 0.25);
}
/** Construct a new Data Log. The log will be initially created with a temporary filename. */
public DataLogBackgroundWriter() {
this("");
}
/**
* Change log filename.
*
* @param filename filename
*/
public void setFilename(String filename) {
DataLogJNI.bgSetFilename(m_impl, filename);
}
/**
* Resumes appending of data records to the log. If called after stop(), opens a new file (with
* random name if SetFilename was not called after stop()) and appends Start records and schema
* data values for all previously started entries and schemas.
*/
@Override
public void resume() {
DataLogJNI.resume(m_impl);
}
}

View File

@@ -5,6 +5,7 @@
package edu.wpi.first.util.datalog;
import edu.wpi.first.util.WPIUtilJNI;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
@@ -14,7 +15,8 @@ import java.nio.ByteBuffer;
*/
public class DataLogJNI extends WPIUtilJNI {
/**
* Create a new Data Log. The log will be initially created with a temporary filename.
* Create a new Data Log background writer. The log will be initially created with a temporary
* filename.
*
* @param dir directory to store the log
* @param filename filename to use; if none provided, a random filename is generated of the form
@@ -22,22 +24,32 @@ public class DataLogJNI extends WPIUtilJNI {
* @param period time between automatic flushes to disk, in seconds; this is a time/storage
* tradeoff
* @param extraHeader extra header data
* @return data log implementation handle
* @return data log background writer implementation handle
*/
static native long create(String dir, String filename, double period, String extraHeader);
static native long bgCreate(String dir, String filename, double period, String extraHeader);
/**
* Change log filename.
*
* @param impl data log implementation handle
* @param impl data log background writer implementation handle
* @param filename filename
*/
static native void setFilename(long impl, String filename);
static native void bgSetFilename(long impl, String filename);
/**
* Create a new Data Log foreground writer.
*
* @param filename filename to use
* @param extraHeader extra header data
* @return data log writer implementation handle
* @throws IOException if file cannot be opened
*/
static native long fgCreate(String filename, String extraHeader) throws IOException;
/**
* Explicitly flushes the log data to disk.
*
* @param impl data log implementation handle
* @param impl data log background writer implementation handle
*/
static native void flush(long impl);
@@ -45,7 +57,7 @@ public class DataLogJNI extends WPIUtilJNI {
* Pauses appending of data records to the log. While paused, no data records are saved (e.g.
* AppendX is a no-op). Has no effect on entry starts / finishes / metadata changes.
*
* @param impl data log implementation handle
* @param impl data log background writer implementation handle
*/
static native void pause(long impl);
@@ -54,14 +66,14 @@ public class DataLogJNI extends WPIUtilJNI {
* random name if SetFilename was not called after Stop()) and appends Start records and schema
* data values for all previously started entries and schemas.
*
* @param impl data log implementation handle
* @param impl data log background writer implementation handle
*/
static native void resume(long impl);
/**
* Stops appending all records to the log, and closes the log file.
*
* @param impl data log implementation handle
* @param impl data log background writer implementation handle
*/
static native void stop(long impl);

View File

@@ -0,0 +1,31 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.util.datalog;
import java.io.IOException;
/** A data log writer that flushes the data log to a file when flush() is called. */
public class DataLogWriter extends DataLog {
/**
* Construct a new Data Log.
*
* @param filename filename to use
* @param extraHeader extra header data
* @throws IOException if file cannot be opened
*/
public DataLogWriter(String filename, String extraHeader) throws IOException {
super(DataLogJNI.fgCreate(filename, extraHeader));
}
/**
* Construct a new Data Log.
*
* @param filename filename to use
* @throws IOException if file cannot be opened
*/
public DataLogWriter(String filename) throws IOException {
this(filename, "");
}
}