Strip-chart daemon and related programs. scd maintains the database, records new data in it, and returns it on request from display clients. A single scd instance can manage a more or less unlimited number of data stores. sc fetches data from scd (by default) or records new data (with -record). scd is driven off a config file. The config file is divided into sections, with one section per data repository and per listen point. Each section is introduced with a lead-in line; further lines, up to the next lead-in line, describe the section in question. Lines containing nothing but whitespace, or whose first non-whitespace character is a #, are comments, and are ignored. ---- A data repository has a name, a filename, a data type, and a maximum time interval. The name is used to refer to the repository from other section; it can appear in log lines, but otherwise is entirely internal to the config file. It is not possible for two data repositories managed by the same scd instance to have the same name. The filename names the file where scd keeps data. Filenames are uninterpreted strings to scd; for example, the distinction between relative and absolute pathnames does not exist as far as scd is concerned - relative pathnames will be interpreted relative to scd's working directory (which scd does not change). The data type indicates what kind of data the repository holds (besides timestamps, which every repository holds). It can be "integer" (32-bit signed integers) or "float" (machine double-floats). All network protocol transports data encoded as text, so issues such as integer byte sex and floating-point representation do not arise. The maximum time interval is used to describe how much time has to pass between two samples being recorded for it to be considered a gap in the data. A repository section looks like repo NAME NAME is the repository's internal name. This line is the section's lead-in line; it must be first. The other lines must appear exactly once each and may appear in any order. NAME begins with the first non-whitespace character after "repo" and continues to the end of the line. NAME may not contain whitespace, because names appear whitespace-delimited elsewhere. file FILENAME FILENAME is the repository's filename. FILENAME begins with the first non-whitespace character after "file" and continues to the end of the line. There is no provision for filenames beginning with whitespace or containing newlines. type TYPE TYPE can be "int" or "float". gap TIME TIME is the maximum time interval. It consists of a time interval spec (see below). ---- A listen point has an indication of what operations are supported for its connections, one or more endpoint specs, and one or more mapping lines. The endpoint specs describe where data connections are accepted from; multiple endpoint lines accumulate, causing scd to listen on all of them. Map lines describe how repository names as sent by the client are interpreted. A listen point section looks like listen This is the section's lead-in line; it must be first. Permission lines specify what operations connections are allowed to perform. permit [OP [OP ...]] Lists the operations permitted to connections for this listen point. The OPs specify permitted operations; multiple permit lines accumulate. OP values can be new-data Permits receiving new data. fetch Permits fetching data from the data store. * Permits all operations. Endpoint lines specify where scd listens for connections. local PATH This specifies an AF_LOCAL endpoint. PATH is the pathname to be bound; it begins with the first non-whitespace character after "local" and continues to the end of the line; there is no provision for paths beginning with whitespace or containing newlines. If bind() fails and the path stat()s as a socket, it will be unlink()ed first - note the implications this has for symlinks. ip [ADDR/]PORT ip4 [ADDR/]PORT ip6 [ADDR/]PORT Specifies IPv4 and/or IPv6 endpoints. If the ADDR/ part is omitted, the PORT will be bound to INADDR_ANY for v4 and/or :: for v6; if not, ADDR will be resolved to one or more addresses (restricted to v4 or v6 for ip4 or ip6 lines) if it's not already a numeric address; all resulting addresses will be bound. (It is an error for ADDR to resolve to no addresses.) Mapping lines specify how repository names as seen by the network protocol map to repository sections in the config file. This mapping is done separately for each listen section. All map lines have a priority value ("PRIO" below), which is a decimal integer (it must fit in an int as a nonnegative value). When a repository name is received from the network, it is, conceptually, matched against all of that listen section's mapping lines. Of those which match, the highest priority value is determined; all lines having that priority which match then have their resulting section strings compared. If they are all the same, that string is used as the section name; if not, an error occurs. (If no mapping lines at all match, an error also occurs.) If the resulting section name does not name a defined repo section, an error occurs. map PRIO trivial Specifies that any internal repository name is accepted, under its internal name. This is equivalent to specifying a "map simple" line for each defined repository, giving its name twice. map PRIO error EXTNAME Specifies that protocol name EXTNAME is an error; if no higher-priority mapping overrides it, this repository name is an error. map PRIO simple EXTNAME INTNAME Specifies that protocol name EXTNAME is to be interpreted as referring to INTNAME. map PRIO regex /EXT/INT The / need not actually be a /; it is the first non-whitespace character after "regex", and serves to delimit the parts of the rest of the line. This specifies that any external name matching the regex EXT is to be mapped by replacing the match with INT, which is processed by replacing \d, where d is a digit, with the corresponding regex match; to support replacements above 9, d may also consist of parentheses surrounding a multi-digit number (for generality, single-digit numbers are also accepted in parentheses). \\ is interpreted as a literal \. Other sequences beginning with \ are errors; they are reserved for future expansion, and will produce some string, but exactly what string is specifically unspecified. ---- The network protocol is fairly simple. After the connection is established, the client sends either "new-data\0" if it intends to send new data or "fetch\0" if it wants to retrieve existing data. When sending new data, the "new-data\0" is followed with zero or more new data values. Each one is represented as NAME\0TIMESTAMP\0DATA\0, where NAME is the repository name, TIMESTAMP is the data capture timestamp (see below), and DATA is the data (encoded as ASCII text). The type of the data is not explicitly encoded; it is the admin's responsibility to provide matching configurations to the client and server. After all the data values an additional \0 follows as a terminator (this can be thought of as a zero-length NAME). The server replies to each data value with MESSAGE\0, where MESSAGE is zero-length if the data value was successfully stored and a human-readable explanation of why not if not. Upon receiving the terminating \0, the server closes the client->server data flow; after sending all response messages as well, the server drops the connection. When fetching data, the "fetch\0" is followed with NAME NAME ...\0BEGIN\0END\0, where each NAME is a repository name and BEGIN and END are timestamps (see below). This requests all data from any of the named repositories whose timestamps T satisfy BEGIN <= T < END; the data are returned as a stream of NAME\0TIMESTAMP\0DATA\0 records, where NAME is one of the names from the request and TIMESTAMP and DATA are as for new-data, above. After the final record an additional \0 follows (this can also be thought of as a zero-length NAME) as a termination indication. After receiving the final \0 of the request, the server closes the client->server data flow; after sending the \0 terminating the data, the server drops the connection. For any given repository, data is sent in storage order (which will usually, but not necessarily, be chronological order); the aggregate data stream is obtained by interleaving the various per-repository data streams such that, at any point, the next datum will have the earliest timestamp of any of the available data at that point. If there are multiple equal timestamps available at some point, which one is chosen is unspecified. Formally, given per-repository data sequences Si of lengths Li and an overall data stream so far that includes Ni elements from Si, the next datum comes from Sj for some j such that (a) Nj < Lj and (b) for all k for which Nk < Lk, timestamp(Sj[Nj+1]) <= timestamp(Sk[Nk+1]); if this definition can be satisfied by multiple distinct values of j, which one is used is explicitly unspecified. ---- A `timestamp' is an integer number of nanoseconds since the epoch, represented in ASCII decimal. ---- A time interval spec consists of alternating numbers and letters, where the letters specify units and the preceding numbers specify counts, as in "2d12h" or "120s". Ultimately, a time interval spec specifies a number of seconds. The letters and their corresponding units: y Years of 31556952 (365.2425*86400) seconds each. m Months of 2629746 (31556952/12) seconds each. w Weeks of 604800 (7*86400) seconds each. d Days of 86400 seconds each. h Hours of 3600 seconds each. m Minutes of 60 seconds each. s Seconds. If multiple letters are given, they must appear in the above order. The letter m is ambiguous between `months' and `minutes'. The disambiguation rules are: - If no m letters appear, there is nothing to disambiguate. - If two m letters appear, the first is months and the second is minutes. - If exactly one m appears: - If a w, d, or h appears, it disambiguates by position: an m before it is months, after, minutes. - Otherwise, if exactly one of y or s appears, y causes m to be months; s, minutes. - If none of the above disambiguates, an error occurs. Note that there is no limitation that the number of a unit must be no greater than necessary to form one of the next higher unit; for example, three hours may be specified as "3h", "10800s", or even mixed specifications such as "1h109m660s". ---- Copyright status: In jurisdictions where a copyright holder can explicitly release a work into the public domain, this program is in the public domain. In jurisdictions where this is not possible, the statements embedded in the various files that they are in the public domain should be interpreted as the closest available approximation, probably something like "you have an unlimited license to use this file in any way you care to".