Skip to content

Commit

Permalink
[wpiutil] Add DataLog and DataLogManager Stop() (#5860)
Browse files Browse the repository at this point in the history
Restarting a stopped log results in creating a new log file with fresh copies of the same start records and schema data records.

Also check to see if the file has been deleted or if the log file exceeds 1.8 GB, and start a new one.
  • Loading branch information
PeterJohnson authored Nov 4, 2023
1 parent 2a04e12 commit f1a8282
Show file tree
Hide file tree
Showing 11 changed files with 394 additions and 131 deletions.
23 changes: 21 additions & 2 deletions ntcoreffi/src/main/native/cpp/DataLogManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,12 +264,18 @@ Thread::~Thread() {
void Thread::Main() {
// based on free disk space, scan for "old" FRC_*.wpilog files and remove
{
uintmax_t freeSpace = fs::space(m_logDir).free;
std::error_code ec;
uintmax_t freeSpace;
auto freeSpaceInfo = fs::space(m_logDir, ec);
if (!ec) {
freeSpace = freeSpaceInfo.available;
} else {
freeSpace = UINTMAX_MAX;
}
if (freeSpace < kFreeSpaceThreshold) {
// Delete oldest FRC_*.wpilog files (ignore FRC_TBD_*.wpilog as we just
// created one)
std::vector<fs::directory_entry> entries;
std::error_code ec;
for (auto&& entry : fs::directory_iterator{m_logDir, ec}) {
auto stem = entry.path().stem().string();
if (wpi::starts_with(stem, "FRC_") &&
Expand Down Expand Up @@ -462,6 +468,9 @@ static Instance& GetInstance(std::string_view dir = "",
std::string_view filename = "",
double period = 0.25) {
static Instance instance(dir, filename, period);
if (!instance.owner) {
instance.owner.Start(MakeLogDir(dir), filename, period);
}
return instance;
}

Expand All @@ -470,6 +479,12 @@ void DataLogManager::Start(std::string_view dir, std::string_view filename,
GetInstance(dir, filename, period);
}

void DataLogManager::Stop() {
auto& inst = GetInstance();
inst.owner.GetThread()->m_log.Stop();
inst.owner.Stop();
}

void DataLogManager::Log(std::string_view message) {
GetInstance().owner.GetThread()->m_messageLog.Append(message);
fmt::print("{}\n", message);
Expand Down Expand Up @@ -503,6 +518,10 @@ void DLM_Start(const char* dir, const char* filename, double period) {
DataLogManager::Start(dir, filename, period);
}

void DLM_Stop(void) {
DataLogManager::Stop();
}

void DLM_Log(const char* message) {
DataLogManager::Log(message);
}
Expand Down
10 changes: 10 additions & 0 deletions ntcoreffi/src/main/native/include/DataLogManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ class DataLogManager final {
static void Start(std::string_view dir = "", std::string_view filename = "",
double period = 0.25);

/**
* Stop data log manager.
*/
static void Stop();

/**
* Log a message to the "messages" entry. The message is also printed to
* standard output (followed by a newline).
Expand Down Expand Up @@ -110,6 +115,11 @@ struct WPI_DataLog;
*/
void DLM_Start(const char* dir, const char* filename, double period);

/**
* Stop data log manager.
*/
void DLM_Stop(void);

/**
* Log a message to the "messages" entry. The message is also printed to
* standard output (followed by a newline).
Expand Down
2 changes: 2 additions & 0 deletions ntcoreffi/src/main/native/symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ DLM_Log
DLM_LogNetworkTables
DLM_SignalNewDSDataOccur
DLM_Start
DLM_Stop
NT_AddListener
NT_AddListenerMultiple
NT_AddListenerSingle
Expand Down Expand Up @@ -245,6 +246,7 @@ WPI_DataLog_Resume
WPI_DataLog_SetFilename
WPI_DataLog_SetMetadata
WPI_DataLog_Start
WPI_DataLog_Stop
WPI_DestroyEvent
WPI_DestroySemaphore
WPI_DestroySignalObject
Expand Down
19 changes: 17 additions & 2 deletions wpilibc/src/main/native/cpp/DataLogManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,18 @@ Thread::~Thread() {
void Thread::Main() {
// based on free disk space, scan for "old" FRC_*.wpilog files and remove
{
uintmax_t freeSpace = fs::space(m_logDir).available;
std::error_code ec;
uintmax_t freeSpace;
auto freeSpaceInfo = fs::space(m_logDir, ec);
if (!ec) {
freeSpace = freeSpaceInfo.available;
} else {
freeSpace = UINTMAX_MAX;
}
if (freeSpace < kFreeSpaceThreshold) {
// Delete oldest FRC_*.wpilog files (ignore FRC_TBD_*.wpilog as we just
// created one)
std::vector<fs::directory_entry> entries;
std::error_code ec;
for (auto&& entry : fs::directory_iterator{m_logDir, ec}) {
auto stem = entry.path().stem().string();
if (wpi::starts_with(stem, "FRC_") &&
Expand Down Expand Up @@ -308,6 +314,9 @@ static Instance& GetInstance(std::string_view dir = "",
std::string_view filename = "",
double period = 0.25) {
static Instance instance(dir, filename, period);
if (!instance.owner) {
instance.owner.Start(MakeLogDir(dir), filename, period);
}
return instance;
}

Expand All @@ -316,6 +325,12 @@ void DataLogManager::Start(std::string_view dir, std::string_view filename,
GetInstance(dir, filename, period);
}

void DataLogManager::Stop() {
auto& inst = GetInstance();
inst.owner.GetThread()->m_log.Stop();
inst.owner.Stop();
}

void DataLogManager::Log(std::string_view message) {
GetInstance().owner.GetThread()->m_messageLog.Append(message);
fmt::print("{}\n", message);
Expand Down
5 changes: 5 additions & 0 deletions wpilibc/src/main/native/include/frc/DataLogManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ class DataLogManager final {
static void Start(std::string_view dir = "", std::string_view filename = "",
double period = 0.25);

/**
* Stop data log manager.
*/
static void Stop();

/**
* Log a message to the "messages" entry. The message is also printed to
* standard output (followed by a newline).
Expand Down
69 changes: 42 additions & 27 deletions wpilibj/src/main/java/edu/wpi/first/wpilibj/DataLogManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@
*/
public final class DataLogManager {
private static DataLog m_log;
private static boolean m_stopped;
private static String m_logDir;
private static boolean m_filenameOverride;
private static final Thread m_thread;
private static Thread m_thread;
private static final ZoneId m_utc = ZoneId.of("UTC");
private static final DateTimeFormatter m_timeFormatter =
DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss").withZone(m_utc);
Expand All @@ -59,11 +60,6 @@ public final class DataLogManager {

private DataLogManager() {}

static {
m_thread = new Thread(DataLogManager::logMain, "DataLogDS");
m_thread.setDaemon(true);
}

/** Start data log manager with default directory location. */
public static synchronized void start() {
start("", "", 0.25);
Expand Down Expand Up @@ -100,33 +96,52 @@ public static synchronized void start(String dir, String filename) {
* tradeoff
*/
public static synchronized void start(String dir, String filename, double period) {
if (m_log != null) {
return;
}
m_logDir = makeLogDir(dir);
m_filenameOverride = !filename.isEmpty();
if (m_log == null) {
m_logDir = makeLogDir(dir);
m_filenameOverride = !filename.isEmpty();

// Delete all previously existing FRC_TBD_*.wpilog files. These only exist when the robot
// never connects to the DS, so they are very unlikely to have useful data and just clutter
// the filesystem.
File[] files =
new File(m_logDir)
.listFiles((d, name) -> name.startsWith("FRC_TBD_") && name.endsWith(".wpilog"));
if (files != null) {
for (File file : files) {
if (!file.delete()) {
System.err.println("DataLogManager: could not delete " + file);
// Delete all previously existing FRC_TBD_*.wpilog files. These only exist when the robot
// never connects to the DS, so they are very unlikely to have useful data and just clutter
// the filesystem.
File[] files =
new File(m_logDir)
.listFiles((d, name) -> name.startsWith("FRC_TBD_") && name.endsWith(".wpilog"));
if (files != null) {
for (File file : files) {
if (!file.delete()) {
System.err.println("DataLogManager: could not delete " + file);
}
}
}
m_log = new DataLog(m_logDir, makeLogFilename(filename), period);
m_messageLog = new StringLogEntry(m_log, "messages");

// Log all NT entries and connections
if (m_ntLoggerEnabled) {
startNtLog();
}
} else if (m_stopped) {
m_log.setFilename(makeLogFilename(filename));
m_log.resume();
m_stopped = false;
}

m_log = new DataLog(m_logDir, makeLogFilename(filename), period);
m_messageLog = new StringLogEntry(m_log, "messages");
m_thread.start();
if (m_thread == null) {
m_thread = new Thread(DataLogManager::logMain, "DataLogDS");
m_thread.setDaemon(true);
m_thread.start();
}
}

// Log all NT entries and connections
if (m_ntLoggerEnabled) {
startNtLog();
/** Stop data log manager. */
public static synchronized void stop() {
if (m_thread != null) {
m_thread.interrupt();
m_thread = null;
}
if (m_log != null) {
m_log.stop();
m_stopped = true;
}
}

Expand Down
11 changes: 10 additions & 1 deletion wpiutil/src/main/java/edu/wpi/first/util/datalog/DataLog.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,20 @@ public void pause() {
DataLogJNI.pause(m_impl);
}

/** Resumes appending of data records to the log. */
/**
* 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.
*/
public void resume() {
DataLogJNI.resume(m_impl);
}

/** Stops appending all records to the log, and closes the log file. */
public void stop() {
DataLogJNI.stop(m_impl);
}

/**
* Returns whether there is a data schema already registered with the given name.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public class DataLogJNI extends WPIUtilJNI {

static native void resume(long impl);

static native void stop(long impl);

static native void addSchema(long impl, String name, String type, byte[] schema, long timestamp);

static native void addSchemaString(
Expand Down
Loading

0 comments on commit f1a8282

Please sign in to comment.