001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.util.datalog; 006 007/** 008 * A data log. The log file is created immediately upon construction with a temporary filename. The 009 * file may be renamed at any time using the setFilename() function. 010 * 011 * <p>The data log is periodically flushed to disk. It can also be explicitly flushed to disk by 012 * using the flush() function. 013 * 014 * <p>The finish() function is needed only to indicate in the log that a particular entry is no 015 * longer being used (it releases the name to ID mapping). The finish() function is not required to 016 * be called for data to be flushed to disk; entries in the log are written as append() calls are 017 * being made. In fact, finish() does not need to be called at all. 018 * 019 * <p>DataLog calls are thread safe. DataLog uses a typical multiple-supplier, single-consumer 020 * setup. Writes to the log are atomic, but there is no guaranteed order in the log when multiple 021 * threads are writing to it; whichever thread grabs the write mutex first will get written first. 022 * For this reason (as well as the fact that timestamps can be set to arbitrary values), records in 023 * the log are not guaranteed to be sorted by timestamp. 024 */ 025public final class DataLog implements AutoCloseable { 026 /** 027 * Construct a new Data Log. The log will be initially created with a temporary filename. 028 * 029 * @param dir directory to store the log 030 * @param filename filename to use; if none provided, a random filename is generated of the form 031 * "wpilog_{}.wpilog" 032 * @param period time between automatic flushes to disk, in seconds; this is a time/storage 033 * tradeoff 034 * @param extraHeader extra header data 035 */ 036 public DataLog(String dir, String filename, double period, String extraHeader) { 037 m_impl = DataLogJNI.create(dir, filename, period, extraHeader); 038 } 039 040 /** 041 * Construct a new Data Log. The log will be initially created with a temporary filename. 042 * 043 * @param dir directory to store the log 044 * @param filename filename to use; if none provided, a random filename is generated of the form 045 * "wpilog_{}.wpilog" 046 * @param period time between automatic flushes to disk, in seconds; this is a time/storage 047 * tradeoff 048 */ 049 public DataLog(String dir, String filename, double period) { 050 this(dir, filename, period, ""); 051 } 052 053 /** 054 * Construct a new Data Log. The log will be initially created with a temporary filename. 055 * 056 * @param dir directory to store the log 057 * @param filename filename to use; if none provided, a random filename is generated of the form 058 * "wpilog_{}.wpilog" 059 */ 060 public DataLog(String dir, String filename) { 061 this(dir, filename, 0.25); 062 } 063 064 /** 065 * Construct a new Data Log. The log will be initially created with a temporary filename. 066 * 067 * @param dir directory to store the log 068 */ 069 public DataLog(String dir) { 070 this(dir, "", 0.25); 071 } 072 073 /** Construct a new Data Log. The log will be initially created with a temporary filename. */ 074 public DataLog() { 075 this(""); 076 } 077 078 /** 079 * Change log filename. 080 * 081 * @param filename filename 082 */ 083 public void setFilename(String filename) { 084 DataLogJNI.setFilename(m_impl, filename); 085 } 086 087 /** Explicitly flushes the log data to disk. */ 088 public void flush() { 089 DataLogJNI.flush(m_impl); 090 } 091 092 /** 093 * Pauses appending of data records to the log. While paused, no data records are saved (e.g. 094 * AppendX is a no-op). Has no effect on entry starts / finishes / metadata changes. 095 */ 096 public void pause() { 097 DataLogJNI.pause(m_impl); 098 } 099 100 /** Resumes appending of data records to the log. */ 101 public void resume() { 102 DataLogJNI.resume(m_impl); 103 } 104 105 /** 106 * Start an entry. Duplicate names are allowed (with the same type), and result in the same index 107 * being returned (start/finish are reference counted). A duplicate name with a different type 108 * will result in an error message being printed to the console and 0 being returned (which will 109 * be ignored by the append functions). 110 * 111 * @param name Name 112 * @param type Data type 113 * @param metadata Initial metadata (e.g. data properties) 114 * @param timestamp Time stamp (0 to indicate now) 115 * @return Entry index 116 */ 117 public int start(String name, String type, String metadata, long timestamp) { 118 return DataLogJNI.start(m_impl, name, type, metadata, timestamp); 119 } 120 121 /** 122 * Start an entry. Duplicate names are allowed (with the same type), and result in the same index 123 * being returned (start/finish are reference counted). A duplicate name with a different type 124 * will result in an error message being printed to the console and 0 being returned (which will 125 * be ignored by the append functions). 126 * 127 * @param name Name 128 * @param type Data type 129 * @param metadata Initial metadata (e.g. data properties) 130 * @return Entry index 131 */ 132 public int start(String name, String type, String metadata) { 133 return start(name, type, metadata, 0); 134 } 135 136 /** 137 * Start an entry. Duplicate names are allowed (with the same type), and result in the same index 138 * being returned (start/finish are reference counted). A duplicate name with a different type 139 * will result in an error message being printed to the console and 0 being returned (which will 140 * be ignored by the append functions). 141 * 142 * @param name Name 143 * @param type Data type 144 * @return Entry index 145 */ 146 public int start(String name, String type) { 147 return start(name, type, ""); 148 } 149 150 /** 151 * Finish an entry. 152 * 153 * @param entry Entry index 154 * @param timestamp Time stamp (0 to indicate now) 155 */ 156 public void finish(int entry, long timestamp) { 157 DataLogJNI.finish(m_impl, entry, timestamp); 158 } 159 160 /** 161 * Finish an entry. 162 * 163 * @param entry Entry index 164 */ 165 public void finish(int entry) { 166 finish(entry, 0); 167 } 168 169 /** 170 * Updates the metadata for an entry. 171 * 172 * @param entry Entry index 173 * @param metadata New metadata for the entry 174 * @param timestamp Time stamp (0 to indicate now) 175 */ 176 public void setMetadata(int entry, String metadata, long timestamp) { 177 DataLogJNI.setMetadata(m_impl, entry, metadata, timestamp); 178 } 179 180 /** 181 * Updates the metadata for an entry. 182 * 183 * @param entry Entry index 184 * @param metadata New metadata for the entry 185 */ 186 public void setMetadata(int entry, String metadata) { 187 setMetadata(entry, metadata, 0); 188 } 189 190 /** 191 * Appends a raw record to the log. 192 * 193 * @param entry Entry index, as returned by start() 194 * @param data Byte array to record 195 * @param timestamp Time stamp (0 to indicate now) 196 */ 197 public void appendRaw(int entry, byte[] data, long timestamp) { 198 DataLogJNI.appendRaw(m_impl, entry, data, timestamp); 199 } 200 201 @Override 202 public void close() { 203 DataLogJNI.close(m_impl); 204 m_impl = 0; 205 } 206 207 /** 208 * Appends a boolean record to the log. 209 * 210 * @param entry Entry index, as returned by start() 211 * @param value Boolean value to record 212 * @param timestamp Time stamp (0 to indicate now) 213 */ 214 public void appendBoolean(int entry, boolean value, long timestamp) { 215 DataLogJNI.appendBoolean(m_impl, entry, value, timestamp); 216 } 217 218 /** 219 * Appends an integer record to the log. 220 * 221 * @param entry Entry index, as returned by start() 222 * @param value Integer value to record 223 * @param timestamp Time stamp (0 to indicate now) 224 */ 225 public void appendInteger(int entry, long value, long timestamp) { 226 DataLogJNI.appendInteger(m_impl, entry, value, timestamp); 227 } 228 229 /** 230 * Appends a float record to the log. 231 * 232 * @param entry Entry index, as returned by start() 233 * @param value Float value to record 234 * @param timestamp Time stamp (0 to indicate now) 235 */ 236 public void appendFloat(int entry, float value, long timestamp) { 237 DataLogJNI.appendFloat(m_impl, entry, value, timestamp); 238 } 239 240 /** 241 * Appends a double record to the log. 242 * 243 * @param entry Entry index, as returned by start() 244 * @param value Double value to record 245 * @param timestamp Time stamp (0 to indicate now) 246 */ 247 public void appendDouble(int entry, double value, long timestamp) { 248 DataLogJNI.appendDouble(m_impl, entry, value, timestamp); 249 } 250 251 /** 252 * Appends a string record to the log. 253 * 254 * @param entry Entry index, as returned by start() 255 * @param value String value to record 256 * @param timestamp Time stamp (0 to indicate now) 257 */ 258 public void appendString(int entry, String value, long timestamp) { 259 DataLogJNI.appendString(m_impl, entry, value, timestamp); 260 } 261 262 /** 263 * Appends a boolean array record to the log. 264 * 265 * @param entry Entry index, as returned by start() 266 * @param arr Boolean array to record 267 * @param timestamp Time stamp (0 to indicate now) 268 */ 269 public void appendBooleanArray(int entry, boolean[] arr, long timestamp) { 270 DataLogJNI.appendBooleanArray(m_impl, entry, arr, timestamp); 271 } 272 273 /** 274 * Appends an integer array record to the log. 275 * 276 * @param entry Entry index, as returned by start() 277 * @param arr Integer array to record 278 * @param timestamp Time stamp (0 to indicate now) 279 */ 280 public void appendIntegerArray(int entry, long[] arr, long timestamp) { 281 DataLogJNI.appendIntegerArray(m_impl, entry, arr, timestamp); 282 } 283 284 /** 285 * Appends a float array record to the log. 286 * 287 * @param entry Entry index, as returned by start() 288 * @param arr Float array to record 289 * @param timestamp Time stamp (0 to indicate now) 290 */ 291 public void appendFloatArray(int entry, float[] arr, long timestamp) { 292 DataLogJNI.appendFloatArray(m_impl, entry, arr, timestamp); 293 } 294 295 /** 296 * Appends a double array record to the log. 297 * 298 * @param entry Entry index, as returned by start() 299 * @param arr Double array to record 300 * @param timestamp Time stamp (0 to indicate now) 301 */ 302 public void appendDoubleArray(int entry, double[] arr, long timestamp) { 303 DataLogJNI.appendDoubleArray(m_impl, entry, arr, timestamp); 304 } 305 306 /** 307 * Appends a string array record to the log. 308 * 309 * @param entry Entry index, as returned by start() 310 * @param arr String array to record 311 * @param timestamp Time stamp (0 to indicate now) 312 */ 313 public void appendStringArray(int entry, String[] arr, long timestamp) { 314 DataLogJNI.appendStringArray(m_impl, entry, arr, timestamp); 315 } 316 317 public long getImpl() { 318 return m_impl; 319 } 320 321 private long m_impl; 322}