# The rolling buffer

The rolling buffer is a buffer where log events [io/log], their arguments and
their [lib/time] stamps are stored. When the buffer is full, we roll back to the
beginning, overwriting previous contents.

This buffer is suitable for generic handling because it can mix and match
multiple types of log events in the same buffer.

Storage-wise, the buffer is implemented as an array of records of fixed size.
This means that regardless of the number of arguments of each logged item, each
of them use a fixed size. That size is determined when the logroll is created.
Events with more arguments are truncated.

This design is not memory-efficient, but it's fast.

## Example usage

  needs io/log mem/logroll
  100 3 newlogroll const myroll \
  myroll rollhandler handleall
  \ let some events happen
  10 myroll .logroll \ prints 10 latest events of the roll
  -1 myroll .logroll \ prints all events of the roll

## API

### Structures

struct LogRollItem {
  uint ts ;
  *LogEvent event ;
  [void,0] args ;
}

The structure of each item within a LogRoller, that is, a pointer to the event
type, a timestamp and a list of "nargs" arguments.

"args" is stored in reverse order. For example, if logroll received:

  arg1 arg2 arg3 MYEVENT

then the "args" array's first item is arg3.

struct LogRoll {
  uint maxargs rowcnt logcnt ;
  [void,0] buf( ;
}

maxargs  The maximum number of arguments the logged events can have.
rowcnt   The capacity of this roll in terms of row count.
logcnt   The total number of events logged, *including the overwritten* ones.
         "logcnt rowcnt mod" is the index of the row we're going to write to
         next.
buf(     The buffer.

### Words

newlogroll ( rowcount maxargs -- lr )
  Create a new LogRoll buffer and yield it.

idx>item ( idx lr -- lri )
  Yield a pointer to the item at index "idx" in "absolute" terms, that is, as
  if the array was infinite. When logcnt-idx is bigger than rowcntm the yielded
  item will be an overwritten one.

logroll ( ... logevent lr -- ... logevent )
  Log an event into the log roll. You should bind this routine to your logroll
  instance before passing it to "handleall" or "handleevent".

.logroll ( n lr -- )
  Print the latest "n" items from the roll.
