disk_log(3erl) Erlang Module Definition disk_log(3erl)
NAME
disk_log - A disk-based term logging facility.
DESCRIPTION
disk_log is a disk-based term logger that enables efficient logging of
items on files.
Two types of logs are supported:
halt logs:
Appends items to a single file, which size can be limited by the
disk_log module.
wrap logs:
Uses a sequence of wrap log files of limited size. As a wrap log
file is filled up, further items are logged on to the next file in
the sequence, starting all over with the first file when the last
file is filled up.
For efficiency reasons, items are always written to files as binaries.
Two formats of the log files are supported:
internal format:
Supports automatic repair of log files that are not properly closed
and enables efficient reading of logged items in chunks using a set
of functions defined in this module. This is the only way to read
internally formatted logs. An item logged to an internally format-
ted log must not occupy more than 4 GB of disk space (the size must
fit in 4 bytes).
external format:
Leaves it up to the user to read and interpret the logged data. The
disk_log module cannot repair externally formatted logs.
For each open disk log, one process handles requests made to the disk
log. This process is created when open/1 is called, provided there ex-
ists no process handling the disk log. A process that opens a disk log
can be an owner or an anonymous user of the disk log. Each owner is
linked to the disk log process, and an owner can close the disk log ei-
ther explicitly (by calling close/1 or lclose/1,2) or by terminating.
Owners can subscribe to notifications, messages of the form {disk_log,
Node, Log, Info}, which are sent from the disk log process when certain
events occur, see the functions and in particular the open/1 option no-
tify. A log can have many owners, but a process cannot own a log more
than once. However, the same process can open the log as a user more
than once.
For a disk log process to close its file properly and terminate, it
must be closed by its owners and once by some non-owner process for
each time the log was used anonymously. The users are counted and there
must not be any users left when the disk log process terminates.
Items can be logged synchronously by using functions log/2, blog/2,
log_terms/2, and blog_terms/2. For each of these functions, the caller
is put on hold until the items are logged (but not necessarily written,
use sync/1 to ensure that). By adding an a to each of the mentioned
function names, we get functions that log items asynchronously. Asyn-
chronous functions do not wait for the disk log process to write the
items to the file, but return the control to the caller more or less
immediately.
When using the internal format for logs, use functions log/2,
log_terms/2, alog/2, and alog_terms/2. These functions log one or more
Erlang terms. By prefixing each of the functions with a b (for "bi-
nary"), we get the corresponding blog() functions for the external for-
mat. These functions log one or more chunks of bytes. For example, to
log the string "hello" in ASCII format, you can use disk_log:blog(Log,
"hello"), or disk_log:blog(Log, list_to_binary("hello")). The two al-
ternatives are equally efficient.
The blog() functions can also be used for internally formatted logs,
but in this case they must be called with binaries constructed with
calls to term_to_binary/1. There is no check to ensure this, it is en-
tirely the responsibility of the caller. If these functions are called
with binaries that do not correspond to Erlang terms, the chunk/2,3 and
automatic repair functions fail. The corresponding terms (not the bina-
ries) are returned when chunk/2,3 is called.
Note:
The distributed disk log feature has been deprecated. This feature has
also been scheduled for removal in OTP 24.
A collection of open disk logs with the same name running on different
nodes is said to be a distributed disk log if requests made to any of
the logs are automatically made to the other logs as well. The members
of such a collection are called individual distributed disk logs, or
just distributed disk logs if there is no risk of confusion. There is
no order between the members of such a collection. For example, logged
terms are not necessarily written to the node where the request was
made before written to the other nodes. However, a few functions do not
make requests to all members of distributed disk logs, namely info/1,
chunk/2,3, bchunk/2,3, chunk_step/3, and lclose/1,2.
An open disk log that is not a distributed disk log is said to be a lo-
cal disk log. A local disk log is only accessible from the node where
the disk log process runs, whereas a distributed disk log is accessible
from all nodes in the Erlang system, except for those nodes where a lo-
cal disk log with the same name as the distributed disk log exists. All
processes on nodes that have access to a local or distributed disk log
can log items or otherwise change, inspect, or close the log.
It is not guaranteed that all log files of a distributed disk log con-
tain the same log items. No attempt is made to synchronize the contents
of the files. However, as long as at least one of the involved nodes is
alive at each time, all items are logged. When logging items to a dis-
tributed log, or otherwise trying to change the log, the replies from
individual logs are ignored. If all nodes are down, the disk log func-
tions reply with a nonode error.
Note:
In some applications, it can be unacceptable that replies from individ-
ual logs are ignored. An alternative in such situations is to use many
local disk logs instead of one distributed disk log, and implement the
distribution without use of the disk_log module.
Errors are reported differently for asynchronous log attempts and other
uses of the disk_log module. When used synchronously, this module
replies with an error message, but when called asynchronously, this
module does not know where to send the error message. Instead, owners
subscribing to notifications receive an error_status message.
The disk_log module does not report errors to the error_logger module.
It is up to the caller to decide whether to employ the error logger.
Function format_error/1 can be used to produce readable messages from
error replies. However, information events are sent to the error logger
in two situations, namely when a log is repaired, or when a file is
missing while reading chunks.
Error message no_such_log means that the specified disk log is not
open. Nothing is said about whether the disk log files exist or not.
Note:
If an attempt to reopen or truncate a log fails (see reopen/2,3 and
truncate/1,2) the disk log process terminates immediately. Before the
process terminates, links to owners and blocking processes (see
block/1,2) are removed. The effect is that the links work in one direc-
tion only. Any process using a disk log must check for error message
no_such_log if some other process truncates or reopens the log simulta-
neously.
DATA TYPES
log() = term()
dlog_size() =
infinity |
integer() >= 1 |
{MaxNoBytes :: integer() >= 1, MaxNoFiles :: integer() >= 1}
dlog_format() = external | internal
dlog_head_opt() = none | term() | iodata()
dlog_mode() = read_only | read_write
dlog_type() = halt | wrap
continuation()
Chunk continuation returned by chunk/2,3, bchunk/2,3, or
chunk_step/3.
invalid_header() = term()
file_error() = term()
EXPORTS
accessible_logs() -> {[LocalLog], [DistributedLog]}
Types:
LocalLog = DistributedLog = log()
Returns the names of the disk logs accessible on the current
node. The first list contains local disk logs and the second
list contains distributed disk logs.
alog(Log, Term) -> notify_ret()
balog(Log, Bytes) -> notify_ret()
Types:
Log = log()
Term = term()
Bytes = iodata()
notify_ret() = ok | {error, no_such_log}
Asynchronously append an item to a disk log. alog/2 is used for
internally formatted logs and balog/2 for externally formatted
logs. balog/2 can also be used for internally formatted logs if
the binary is constructed with a call to term_to_binary/1.
Owners subscribing to notifications receive message read_only,
blocked_log, or format_external if the item cannot be written on
the log, and possibly one of the messages wrap, full, or er-
ror_status if an item is written on the log. Message error_sta-
tus is sent if something is wrong with the header function or if
a file error occurs.
alog_terms(Log, TermList) -> notify_ret()
balog_terms(Log, ByteList) -> notify_ret()
Types:
Log = log()
TermList = [term()]
ByteList = [iodata()]
notify_ret() = ok | {error, no_such_log}
Asynchronously append a list of items to a disk log.
alog_terms/2 is used for internally formatted logs and ba-
log_terms/2 for externally formatted logs. balog_terms/2 can
also be used for internally formatted logs if the binaries are
constructed with calls to term_to_binary/1.
Owners subscribing to notifications receive message read_only,
blocked_log, or format_external if the items cannot be written
on the log, and possibly one or more of the messages wrap, full,
and error_status if items are written on the log. Message er-
ror_status is sent if something is wrong with the header func-
tion or if a file error occurs.
block(Log) -> ok | {error, block_error_rsn()}
block(Log, QueueLogRecords) -> ok | {error, block_error_rsn()}
Types:
Log = log()
QueueLogRecords = boolean()
block_error_rsn() = no_such_log | nonode | {blocked_log, log()}
With a call to block/1,2 a process can block a log. If the
blocking process is not an owner of the log, a temporary link is
created between the disk log process and the blocking process.
The link ensures that the disk log is unblocked if the blocking
process terminates without first closing or unblocking the log.
Any process can probe a blocked log with info/1 or close it with
close/1. The blocking process can also use functions chunk/2,3,
bchunk/2,3, chunk_step/3, and unblock/1 without being affected
by the block. Any other attempt than those mentioned so far to
update or read a blocked log suspends the calling process until
the log is unblocked or returns error message {blocked_log,
Log}, depending on whether the value of QueueLogRecords is true
or false. QueueLogRecords defaults to true, which is used by
block/1.
change_header(Log, Header) -> ok | {error, Reason}
Types:
Log = log()
Header =
{head, dlog_head_opt()} |
{head_func, MFA :: {atom(), atom(), list()}}
Reason =
no_such_log | nonode |
{read_only_mode, Log} |
{blocked_log, Log} |
{badarg, head}
Changes the value of option head or head_func for an owner of a
disk log.
change_notify(Log, Owner, Notify) -> ok | {error, Reason}
Types:
Log = log()
Owner = pid()
Notify = boolean()
Reason =
no_such_log | nonode |
{blocked_log, Log} |
{badarg, notify} |
{not_owner, Owner}
Changes the value of option notify for an owner of a disk log.
change_size(Log, Size) -> ok | {error, Reason}
Types:
Log = log()
Size = dlog_size()
Reason =
no_such_log | nonode |
{read_only_mode, Log} |
{blocked_log, Log} |
{new_size_too_small, Log, CurrentSize :: integer() >= 1}
|
{badarg, size} |
{file_error, file:filename(), file_error()}
Changes the size of an open log. For a halt log, the size can
always be increased, but it cannot be decreased to something
less than the current file size.
For a wrap log, both the size and the number of files can always
be increased, as long as the number of files does not exceed
65000. If the maximum number of files is decreased, the change
is not valid until the current file is full and the log wraps to
the next file. The redundant files are removed the next time the
log wraps around, that is, starts to log to file number 1.
As an example, assume that the old maximum number of files is 10
and that the new maximum number of files is 6. If the current
file number is not greater than the new maximum number of files,
files 7-10 are removed when file 6 is full and the log starts to
write to file number 1 again. Otherwise, the files greater than
the current file are removed when the current file is full (for
example, if the current file is 8, files 9 and 10 are removed).
The files between the new maximum number of files and the cur-
rent file (that is, files 7 and 8) are removed the next time
file 6 is full.
If the size of the files is decreased, the change immediately
affects the current log. It does not change the size of log
files already full until the next time they are used.
If the log size is decreased, for example, to save space, func-
tion inc_wrap_file/1 can be used to force the log to wrap.
chunk(Log, Continuation) -> chunk_ret()
chunk(Log, Continuation, N) -> chunk_ret()
bchunk(Log, Continuation) -> bchunk_ret()
bchunk(Log, Continuation, N) -> bchunk_ret()
Types:
Log = log()
Continuation = start | continuation()
N = integer() >= 1 | infinity
chunk_ret() =
{Continuation2 :: continuation(), Terms :: [term()]} |
{Continuation2 :: continuation(),
Terms :: [term()],
Badbytes :: integer() >= 0} |
eof |
{error, Reason :: chunk_error_rsn()}
bchunk_ret() =
{Continuation2 :: continuation(), Binaries :: [binary()]} |
{Continuation2 :: continuation(),
Binaries :: [binary()],
Badbytes :: integer() >= 0} |
eof |
{error, Reason :: chunk_error_rsn()}
chunk_error_rsn() =
no_such_log |
{format_external, log()} |
{blocked_log, log()} |
{badarg, continuation} |
{not_internal_wrap, log()} |
{corrupt_log_file, FileName :: file:filename()} |
{file_error, file:filename(), file_error()}
Efficiently reads the terms that are appended to an internally
formatted log. It minimizes disk I/O by reading 64 kilobyte
chunks from the file. Functions bchunk/2,3 return the binaries
read from the file, they do not call binary_to_term(). Apart
from that, they work just like chunk/2,3.
The first time chunk() (or bchunk()) is called, an initial con-
tinuation, the atom start, must be provided. If a disk log
process is running on the current node, terms are read from that
log. Otherwise, an individual distributed log on some other node
is chosen, if such a log exists.
When chunk/3 is called, N controls the maximum number of terms
that are read from the log in each chunk. Defaults to infinity,
which means that all the terms contained in the 64 kilobyte
chunk are read. If less than N terms are returned, this does not
necessarily mean that the end of the file is reached.
chunk() returns a tuple {Continuation2, Terms}, where Terms is a
list of terms found in the log. Continuation2 is yet another
continuation, which must be passed on to any subsequent calls to
chunk(). With a series of calls to chunk(), all terms from a log
can be extracted.
chunk() returns a tuple {Continuation2, Terms, Badbytes} if the
log is opened in read-only mode and the read chunk is corrupt.
Badbytes is the number of bytes in the file found not to be Er-
lang terms in the chunk. Notice that the log is not repaired.
When trying to read chunks from a log opened in read-write mode,
tuple {corrupt_log_file, FileName} is returned if the read chunk
is corrupt.
chunk() returns eof when the end of the log is reached, or {er-
ror, Reason} if an error occurs. If a wrap log file is missing,
a message is output on the error log.
When chunk/2,3 is used with wrap logs, the returned continuation
might not be valid in the next call to chunk(). This is because
the log can wrap and delete the file into which the continuation
points. To prevent this, the log can be blocked during the
search.
chunk_info(Continuation) -> InfoList | {error, Reason}
Types:
Continuation = continuation()
InfoList = [{node, Node :: node()}, ...]
Reason = {no_continuation, Continuation}
Returns the pair {node, Node}, describing the chunk continuation
returned by chunk/2,3, bchunk/2,3, or chunk_step/3.
Terms are read from the disk log running on Node.
chunk_step(Log, Continuation, Step) ->
{ok, any()} | {error, Reason}
Types:
Log = log()
Continuation = start | continuation()
Step = integer()
Reason =
no_such_log | end_of_log |
{format_external, Log} |
{blocked_log, Log} |
{badarg, continuation} |
{file_error, file:filename(), file_error()}
Can be used with chunk/2,3 and bchunk/2,3 to search through an
internally formatted wrap log. It takes as argument a continua-
tion as returned by chunk/2,3, bchunk/2,3, or chunk_step/3, and
steps forward (or backward) Step files in the wrap log. The con-
tinuation returned, points to the first log item in the new cur-
rent file.
If atom start is specified as continuation, a disk log to read
terms from is chosen. A local or distributed disk log on the
current node is preferred to an individual distributed log on
some other node.
If the wrap log is not full because all files are not yet used,
{error, end_of_log} is returned if trying to step outside the
log.
close(Log) -> ok | {error, close_error_rsn()}
Types:
Log = log()
close_error_rsn() =
no_such_log | nonode |
{file_error, file:filename(), file_error()}
Closes a local or distributed disk log properly. An internally
formatted log must be closed before the Erlang system is
stopped. Otherwise, the log is regarded as unclosed and the au-
tomatic repair procedure is activated next time the log is
opened.
The disk log process is not terminated as long as there are own-
ers or users of the log. All owners must close the log, possibly
by terminating. Also, any other process, not only the processes
that have opened the log anonymously, can decrement the users
counter by closing the log. Attempts to close a log by a process
that is not an owner are ignored if there are no users.
If the log is blocked by the closing process, the log is also
unblocked.
format_error(Error) -> io_lib:chars()
Types:
Error = term()
Given the error returned by any function in this module, this
function returns a descriptive string of the error in English.
For file errors, function format_error/1 in module file is
called.
inc_wrap_file(Log) -> ok | {error, inc_wrap_error_rsn()}
Types:
Log = log()
inc_wrap_error_rsn() =
no_such_log | nonode |
{read_only_mode, log()} |
{blocked_log, log()} |
{halt_log, log()} |
{invalid_header, invalid_header()} |
{file_error, file:filename(), file_error()}
invalid_header() = term()
Forces the internally formatted disk log to start logging to the
next log file. It can be used, for example, with change_size/2
to reduce the amount of disk space allocated by the disk log.
Owners subscribing to notifications normally receive a wrap mes-
sage, but if an error occurs with a reason tag of invalid_header
or file_error, an error_status message is sent.
info(Log) -> InfoList | {error, no_such_log}
Types:
Log = log()
InfoList = [dlog_info()]
dlog_info() =
{name, Log :: log()} |
{file, File :: file:filename()} |
{type, Type :: dlog_type()} |
{format, Format :: dlog_format()} |
{size, Size :: dlog_size()} |
{mode, Mode :: dlog_mode()} |
{owners, [{pid(), Notify :: boolean()}]} |
{users, Users :: integer() >= 0} |
{status,
Status :: ok | {blocked, QueueLogRecords :: boolean()}} |
{node, Node :: node()} |
{distributed, Dist :: local | [node()]} |
{head,
Head ::
none | {head, term()} | (MFA :: {atom(), atom(), list()})} |
{no_written_items, NoWrittenItems :: integer() >= 0} |
{full, Full :: boolean} |
{no_current_bytes, integer() >= 0} |
{no_current_items, integer() >= 0} |
{no_items, integer() >= 0} |
{current_file, integer() >= 1} |
{no_overflows,
{SinceLogWasOpened :: integer() >= 0,
SinceLastInfo :: integer() >= 0}}
Returns a list of {Tag, Value} pairs describing the log. If a
disk log process is running on the current node, that log is
used as source of information, otherwise an individual distrib-
uted log on some other node is chosen, if such a log exists.
The following pairs are returned for all logs:
{name, Log}:
Log is the log name as specified by the open/1 option name.
{file, File}:
For halt logs File is the filename, and for wrap logs File
is the base name.
{type, Type}:
Type is the log type as specified by the open/1 option type.
{format, Format}:
Format is the log format as specified by the open/1 option
format.
{size, Size}:
Size is the log size as specified by the open/1 option size,
or the size set by change_size/2. The value set by
change_size/2 is reflected immediately.
{mode, Mode}:
Mode is the log mode as specified by the open/1 option mode.
{owners, [{pid(), Notify}]}:
Notify is the value set by the open/1 option notify or func-
tion change_notify/3 for the owners of the log.
{users, Users}:
Users is the number of anonymous users of the log, see the
open/1 option linkto.
{status, Status}:
Status is ok or {blocked, QueueLogRecords} as set by func-
tions block/1,2 and unblock/1.
{node, Node}:
The information returned by the current invocation of func-
tion info/1 is gathered from the disk log process running on
Node.
{distributed, Dist}:
If the log is local on the current node, Dist has the value
local, otherwise all nodes where the log is distributed are
returned as a list.
Warning:
The distributed disk log feature has been deprecated. This
feature has also been scheduled for removal in OTP 24.
The following pairs are returned for all logs opened in
read_write mode:
{head, Head}:
Depending on the value of the open/1 options head and
head_func, or set by function change_header/2, the value of
Head is none (default), {head, H} (head option), or {M,F,A}
(head_func option).
{no_written_items, NoWrittenItems}:
NoWrittenItems is the number of items written to the log
since the disk log process was created.
The following pair is returned for halt logs opened in
read_write mode:
{full, Full}:
Full is true or false depending on whether the halt log is
full or not.
The following pairs are returned for wrap logs opened in
read_write mode:
{no_current_bytes, integer() >= 0}:
The number of bytes written to the current wrap log file.
{no_current_items, integer() >= 0}:
The number of items written to the current wrap log file,
header inclusive.
{no_items, integer() >= 0}:
The total number of items in all wrap log files.
{current_file, integer()}:
The ordinal for the current wrap log file in the range
1..MaxNoFiles, where MaxNoFiles is specified by the open/1
option size or set by change_size/2.
{no_overflows, {SinceLogWasOpened, SinceLastInfo}}:
SinceLogWasOpened (SinceLastInfo) is the number of times a
wrap log file has been filled up and a new one is opened or
inc_wrap_file/1 has been called since the disk log was last
opened (info/1 was last called). The first time info/2 is
called after a log was (re)opened or truncated, the two val-
ues are equal.
Notice that functions chunk/2,3, bchunk/2,3, and chunk_step/3 do
not affect any value returned by info/1.
lclose(Log) -> ok | {error, lclose_error_rsn()}
lclose(Log, Node) -> ok | {error, lclose_error_rsn()}
Types:
Log = log()
Node = node()
lclose_error_rsn() =
no_such_log | {file_error, file:filename(), file_error()}
lclose/1 closes a local log or an individual distributed log on
the current node.
lclose/2 closes an individual distributed log on the specified
node if the node is not the current one.
lclose(Log) is equivalent to lclose(Log, node()). See also
close/1.
If no log with the specified name exist on the specified node,
no_such_log is returned.
log(Log, Term) -> ok | {error, Reason :: log_error_rsn()}
blog(Log, Bytes) -> ok | {error, Reason :: log_error_rsn()}
Types:
Log = log()
Term = term()
Bytes = iodata()
log_error_rsn() =
no_such_log | nonode |
{read_only_mode, log()} |
{format_external, log()} |
{blocked_log, log()} |
{full, log()} |
{invalid_header, invalid_header()} |
{file_error, file:filename(), file_error()}
Synchronously appends a term to a disk log. Returns ok or {er-
ror, Reason} when the term is written to disk. If the log is
distributed, ok is returned, unless all nodes are down. Terms
are written by the ordinary write() function of the operating
system. Hence, it is not guaranteed that the term is written to
disk, it can linger in the operating system kernel for a while.
To ensure that the item is written to disk, function sync/1 must
be called.
log/2 is used for internally formatted logs, and blog/2 for ex-
ternally formatted logs. blog/2 can also be used for internally
formatted logs if the binary is constructed with a call to
term_to_binary/1.
Owners subscribing to notifications are notified of an error
with an error_status message if the error reason tag is in-
valid_header or file_error.
log_terms(Log, TermList) ->
ok | {error, Reason :: log_error_rsn()}
blog_terms(Log, BytesList) ->
ok | {error, Reason :: log_error_rsn()}
Types:
Log = log()
TermList = [term()]
BytesList = [iodata()]
log_error_rsn() =
no_such_log | nonode |
{read_only_mode, log()} |
{format_external, log()} |
{blocked_log, log()} |
{full, log()} |
{invalid_header, invalid_header()} |
{file_error, file:filename(), file_error()}
Synchronously appends a list of items to the log. It is more ef-
ficient to use these functions instead of functions log/2 and
blog/2. The specified list is split into as large sublists as
possible (limited by the size of wrap log files), and each sub-
list is logged as one single item, which reduces the overhead.
log_terms/2 is used for internally formatted logs, and
blog_terms/2 for externally formatted logs. blog_terms/2 can
also be used for internally formatted logs if the binaries are
constructed with calls to term_to_binary/1.
Owners subscribing to notifications are notified of an error
with an error_status message if the error reason tag is in-
valid_header or file_error.
open(ArgL) -> open_ret() | dist_open_ret()
Types:
ArgL = dlog_options()
dlog_options() = [dlog_option()]
dlog_option() =
{name, Log :: log()} |
{file, FileName :: file:filename()} |
{linkto, LinkTo :: none | pid()} |
{repair, Repair :: true | false | truncate} |
{type, Type :: dlog_type()} |
{format, Format :: dlog_format()} |
{size, Size :: dlog_size()} |
{distributed, Nodes :: [node()]} |
{notify, boolean()} |
{head, Head :: dlog_head_opt()} |
{head_func, MFA :: {atom(), atom(), list()}} |
{quiet, boolean()} |
{mode, Mode :: dlog_mode()}
open_ret() = ret() | {error, open_error_rsn()}
ret() =
{ok, Log :: log()} |
{repaired,
Log :: log(),
{recovered, Rec :: integer() >= 0},
{badbytes, Bad :: integer() >= 0}}
dist_open_ret() =
{[{node(), ret()}], [{node(), {error, dist_error_rsn()}}]}
dist_error_rsn() = nodedown | open_error_rsn()
open_error_rsn() =
no_such_log |
{badarg, term()} |
{size_mismatch,
CurrentSize :: dlog_size(),
NewSize :: dlog_size()} |
{arg_mismatch,
OptionName :: dlog_optattr(),
CurrentValue :: term(),
Value :: term()} |
{name_already_open, Log :: log()} |
{open_read_write, Log :: log()} |
{open_read_only, Log :: log()} |
{need_repair, Log :: log()} |
{not_a_log_file, FileName :: file:filename()} |
{invalid_index_file, FileName :: file:filename()} |
{invalid_header, invalid_header()} |
{file_error, file:filename(), file_error()} |
{node_already_open, Log :: log()}
dlog_optattr() =
name | file | linkto | repair | type | format | size |
distributed | notify | head | head_func | mode
dlog_size() =
infinity |
integer() >= 1 |
{MaxNoBytes :: integer() >= 1, MaxNoFiles :: integer() >= 1}
Parameter ArgL is a list of the following options:
{name, Log}:
Specifies the log name. This name must be passed on as a pa-
rameter in all subsequent logging operations. A name must
always be supplied.
{file, FileName}:
Specifies the name of the file to be used for logged terms.
If this value is omitted and the log name is an atom or a
string, the filename defaults to lists:concat([Log, ".LOG"])
for halt logs.
For wrap logs, this is the base name of the files. Each file
in a wrap log is called <base_name>.N, where N is an inte-
ger. Each wrap log also has two files called <base_name>.idx
and <base_name>.siz.
{linkto, LinkTo}:
If LinkTo is a pid, it becomes an owner of the log. If
LinkTo is none, the log records that it is used anonymously
by some process by incrementing the users counter. By de-
fault, the process that calls open/1 owns the log.
{repair, Repair}:
If Repair is true, the current log file is repaired, if
needed. As the restoration is initiated, a message is output
on the error log. If false is specified, no automatic repair
is attempted. Instead, the tuple {error, {need_repair, Log}}
is returned if an attempt is made to open a corrupt log
file. If truncate is specified, the log file becomes trun-
cated, creating an empty log. Defaults to true, which has no
effect on logs opened in read-only mode.
{type, Type}:
The log type. Defaults to halt.
{format, Format}:
Disk log format. Defaults to internal.
{size, Size}:
Log size.
When a halt log has reached its maximum size, all attempts
to log more items are rejected. Defaults to infinity, which
for halt implies that there is no maximum size.
For wrap logs, parameter Size can be a pair {MaxNoBytes,
MaxNoFiles} or infinity. In the latter case, if the files of
an existing wrap log with the same name can be found, the
size is read from the existing wrap log, otherwise an error
is returned.
Wrap logs write at most MaxNoBytes bytes on each file and
use MaxNoFiles files before starting all over with the first
wrap log file. Regardless of MaxNoBytes, at least the header
(if there is one) and one item are written on each wrap log
file before wrapping to the next file.
When opening an existing wrap log, it is not necessary to
supply a value for option Size, but any supplied value must
equal the current log size, otherwise the tuple {error,
{size_mismatch, CurrentSize, NewSize}} is returned.
{distributed, Nodes}:
This option can be used for adding members to a distributed
disk log. Defaults to [], which means that the log is local
on the current node.
Warning:
The distributed disk log feature has been deprecated. This
feature has also been scheduled for removal in OTP 24.
{notify, boolean()}:
If true, the log owners are notified when certain log events
occur. Defaults to false. The owners are sent one of the
following messages when an event occurs:
{disk_log, Node, Log, {wrap, NoLostItems}}:
Sent when a wrap log has filled up one of its files and a
new file is opened. NoLostItems is the number of previ-
ously logged items that were lost when truncating existing
files.
{disk_log, Node, Log, {truncated, NoLostItems}}:
Sent when a log is truncated or reopened. For halt logs
NoLostItems is the number of items written on the log
since the disk log process was created. For wrap logs
NoLostItems is the number of items on all wrap log files.
{disk_log, Node, Log, {read_only, Items}}:
Sent when an asynchronous log attempt is made to a log
file opened in read-only mode. Items is the items from the
log attempt.
{disk_log, Node, Log, {blocked_log, Items}}:
Sent when an asynchronous log attempt is made to a blocked
log that does not queue log attempts. Items is the items
from the log attempt.
{disk_log, Node, Log, {format_external, Items}}:
Sent when function alog/2 or alog_terms/2 is used for in-
ternally formatted logs. Items is the items from the log
attempt.
{disk_log, Node, Log, full}:
Sent when an attempt to log items to a wrap log would
write more bytes than the limit set by option size.
{disk_log, Node, Log, {error_status, Status}}:
Sent when the error status changes. The error status is
defined by the outcome of the last attempt to log items to
the log, or to truncate the log, or the last use of func-
tion sync/1, inc_wrap_file/1, or change_size/2. Status is
either ok or {error, Error}, the former is the initial
value.
{head, Head}:
Specifies a header to be written first on the log file. If
the log is a wrap log, the item Head is written first in
each new file. Head is to be a term if the format is inter-
nal, otherwise a sequence of bytes. Defaults to none, which
means that no header is written first on the file.
{head_func, {M,F,A}}:
Specifies a function to be called each time a new log file
is opened. The call M:F(A) is assumed to return {ok, Head}.
The item Head is written first in each file. Head is to be a
term if the format is internal, otherwise a sequence of
bytes.
{mode, Mode}:
Specifies if the log is to be opened in read-only or read-
write mode. Defaults to read_write.
{quiet, Boolean}:
Specifies if messages will be sent to error_logger on recov-
erable errors with the log files. Defaults to false.
open/1 returns {ok, Log} if the log file is successfully opened.
If the file is successfully repaired, the tuple {repaired, Log,
{recovered, Rec}, {badbytes, Bad}} is returned, where Rec is the
number of whole Erlang terms found in the file and Bad is the
number of bytes in the file that are non-Erlang terms. If the
parameter distributed is specified, open/1 returns a list of
successful replies and a list of erroneous replies. Each reply
is tagged with the node name.
When a disk log is opened in read-write mode, any existing log
file is checked for. If there is none, a new empty log is cre-
ated, otherwise the existing file is opened at the position af-
ter the last logged item, and the logging of items starts from
there. If the format is internal and the existing file is not
recognized as an internally formatted log, a tuple {error,
{not_a_log_file, FileName}} is returned.
open/1 cannot be used for changing the values of options of an
open log. When there are prior owners or users of a log, all op-
tion values except name, linkto, and notify are only checked
against the values supplied before as option values to function
open/1, change_header/2, change_notify/3, or change_size/2.
Thus, none of the options except name is mandatory. If some
specified value differs from the current value, a tuple {error,
{arg_mismatch, OptionName, CurrentValue, Value}} is returned.
Note:
If an owner attempts to open a log as owner once again, it is
acknowledged with the return value {ok, Log}, but the state of
the disk log is not affected.
If a log with a specified name is local on some node, and one
tries to open the log distributed on the same node, the tuple
{error, {node_already_open, Log}} is returned. The same tuple is
returned if the log is distributed on some node, and one tries
to open the log locally on the same node. Opening individual
distributed disk logs for the first time adds those logs to a
(possibly empty) distributed disk log. The supplied option val-
ues are used on all nodes mentioned by option distributed. Indi-
vidual distributed logs know nothing about each other's option
values, so each node can be given unique option values by creat-
ing a distributed log with many calls to open/1.
A log file can be opened more than once by giving different val-
ues to option name or by using the same file when distributing a
log on different nodes. It is up to the user of module disk_log
to ensure that not more than one disk log process has write ac-
cess to any file, otherwise the file can be corrupted.
If an attempt to open a log file for the first time fails, the
disk log process terminates with the EXIT message {{failed,Rea-
son},[{disk_log,open,1}]}. The function returns {error, Reason}
for all other errors.
pid2name(Pid) -> {ok, Log} | undefined
Types:
Pid = pid()
Log = log()
Returns the log name given the pid of a disk log process on the
current node, or undefined if the specified pid is not a disk
log process.
This function is meant to be used for debugging only.
reopen(Log, File) -> ok | {error, reopen_error_rsn()}
reopen(Log, File, Head) -> ok | {error, reopen_error_rsn()}
breopen(Log, File, BHead) -> ok | {error, reopen_error_rsn()}
Types:
Log = log()
File = file:filename()
Head = term()
BHead = iodata()
reopen_error_rsn() =
no_such_log | nonode |
{read_only_mode, log()} |
{blocked_log, log()} |
{same_file_name, log()} |
{invalid_index_file, file:filename()} |
{invalid_header, invalid_header()} |
{file_error, file:filename(), file_error()}
Renames the log file to File and then recreates a new log file.
If a wrap log exists, File is used as the base name of the re-
named files. By default the header given to open/1 is written
first in the newly opened log file, but if argument Head or
BHead is specified, this item is used instead. The header argu-
ment is used only once. Next time a wrap log file is opened, the
header given to open/1 is used.
reopen/2,3 are used for internally formatted logs, and breopen/3
for externally formatted logs.
Owners subscribing to notifications receive a truncate message.
Upon failure to reopen the log, the disk log process terminates
with the EXIT message {{failed,Error},[{disk_log,Fun,Arity}]}.
Other processes having requests queued receive the message
{disk_log, Node, {error, disk_log_stopped}}.
sync(Log) -> ok | {error, sync_error_rsn()}
Types:
Log = log()
sync_error_rsn() =
no_such_log | nonode |
{read_only_mode, log()} |
{blocked_log, log()} |
{file_error, file:filename(), file_error()}
Ensures that the contents of the log are written to the disk.
This is usually a rather expensive operation.
truncate(Log) -> ok | {error, trunc_error_rsn()}
truncate(Log, Head) -> ok | {error, trunc_error_rsn()}
btruncate(Log, BHead) -> ok | {error, trunc_error_rsn()}
Types:
Log = log()
Head = term()
BHead = iodata()
trunc_error_rsn() =
no_such_log | nonode |
{read_only_mode, log()} |
{blocked_log, log()} |
{invalid_header, invalid_header()} |
{file_error, file:filename(), file_error()}
Removes all items from a disk log. If argument Head or BHead is
specified, this item is written first in the newly truncated
log, otherwise the header given to open/1 is used. The header
argument is used only once. Next time a wrap log file is opened,
the header given to open/1 is used.
truncate/1,2 are used for internally formatted logs, and btrun-
cate/2 for externally formatted logs.
Owners subscribing to notifications receive a truncate message.
If the attempt to truncate the log fails, the disk log process
terminates with the EXIT message {{failed,Rea-
son},[{disk_log,Fun,Arity}]}. Other processes having requests
queued receive the message {disk_log, Node, {error,
disk_log_stopped}}.
unblock(Log) -> ok | {error, unblock_error_rsn()}
Types:
Log = log()
unblock_error_rsn() =
no_such_log | nonode |
{not_blocked, log()} |
{not_blocked_by_pid, log()}
Unblocks a log. A log can only be unblocked by the blocking
process.
SEE ALSO
file(3erl), pg2(3erl), wrap_log_reader(3erl)
Ericsson AB kernel 7.0 disk_log(3erl)