emr_track.create/emr_track.import with override = TRUE force exactly that read, by touching every track list file so the overridden copy can be picked up again. The overriding write therefore undid itself:
.nrtrack file that emr_track.exists could not see and that made every later rebuild fail with File ... already exists;emr_track.rm removed the overridden copy, in another db, instead of the overriding one.TrackInfo::dbs, the list of other dbs holding a copy of a track, being dropped whenever a track was loaded on its own rather than through a full reload. It is now rebuilt from the filesystem, which also repairs entries recorded by earlier versions.emr_track.dbs no longer reports a db that is no longer connected.rename:
emr_track.attr.set took no lock at all, while being a read-modify-write of both the per-track file and the db's aggregate attributes cache. Two setters on different tracks never contended, and the loser's attribute disappeared from the cache that fresh sessions read.fcntl lock the process holds on it. The helper is now reentrant.readdir and stat - staged .tmp files and NFS silly-rename entries are transient and are now skipped."", whitespace, a bare comment), where R_ParseVector reports PARSE_OK but returns a zero-length list; the literal NULL, which parses to a length-1 list whose only element is R_NilValue; and - the largest set - anything parse() outright rejects (";", "track +", "foo(", an unterminated string), where the R error was swallowed by R_tryEval inside get_expression_vars() and the C++ caller carried on to crash later. Measured across 29 degenerate inputs: 22 crashed the R process before, none do now, and legitimate expressions are unaffected.emr_track.create and emr_track.import can now rewrite a track in its own db when override = TRUE. Previously override only covered shadowing a track from another db, and rewriting in place required emr_track.rm() first - which left the track missing for the whole rebuild, so anything reading it in that window failed.rename(2) replaces the target atomically, so a concurrent reader always sees either the complete previous track or the complete new one. emr_track.import already staged, but unlinked the target before the move, which reopened the same window.emr_track.rm() followed by a fresh write: the track's attributes, variables and file permissions are kept, so anything the previous write set and the new one does not will survive the rewrite. Remove the track first if you need a clean slate.emr_track.rm, emr_track.mv and emr_track.addto.pipe.Rd documenting usage for re-exported %>%.Rf_findVar with R_getVar/R_getVarEx for R 4.6.0 compatibility.std::rel_ops usage and fixed enum arithmetic.Rf_GetOption in the C++ code.Rf_ prefix in the c++ code.emr_track.mv did not move track attributes.emr_extract when tidy=TRUE.emr_time2posix, emr_posix2time, emr_time2char and emr_char2time functions.emr_track.var.set on the same track.emr_filters.info that returns filters information given a filter expression (e.g. f1 | f2).emr_track.info.emr_vtrack.create with func="exists" returned NA instead of 0 when the track didn't have any value at the iterator interval.emr_vtrack.name and emr_vtrack.create_from_name.emr_vtrack.name and emr_vtrack.create_from_name allow creating virtual tracks
with standard names.emr_track.create with expr=''naryn database. See emr_entries.ls, emr_entries.get, emr_entries.set, emr_entries.rm and emr_entries.reload.string_to_var and var_to_string functions to generate valid variable names from strings.emr_track.rm can now accept multiple tracks as input.patients.dob.emr_track.rm returned an error when given character(0).rchk warnings.stime and etime.emr_traceback function.naryn. You can access them using .naryn::EMR_ROOTS etc.emr_track.exists function.emr_track.attr.set in batch mode.emr_track.attr.set and emr_track.attr.rm.include_missing parameter emr_track.attr.export allowing missing tracks and attributes.emr_filter.createemr_time functions failed when there was an NA in an integer vector.emr_track.attr.get returned attribute name instead of value.emr_track.var.get now returns NULL when variable doesn't exist.db_id parameter to emr_track.lsemr_filter.name and emr_filter.create_from_name allow creating filters
with standard names.emr_track.logical.create when values are a list of length 1.emr_filter.create and emr_vtrack.create now return silently the name of the filter/vtrack.emr_track.addto.emr_dist and emr_cor now have a dataframe parameter that returns the results in a tidy format.emr_dist when right=FALSE and values were a fraction.emr_monthly_iterator, emr_yearly_iteratordevtools ecosystem: roxygen documentation and testthat for tests.NEWS.md file to track changes to the package.New iterator type: beat iterator aligned to the time that appears in a data frame or a track (aka birthday). Syntax:
iterator=list(period, data.frame(id=..., time=...))
iterator=list(period, trackname)
Note: each id must appear only once in the data frame / track.