1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1997-2020. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21-define(DISK_LOG_NAME_TABLE, disk_log_names). 22-define(DISK_LOG_PID_TABLE, disk_log_pids). 23 24%% File format version 25-define(VERSION, 2). 26 27%% HEADSZ is the size of the file header, 28%% HEADERSZ is the size of the item header ( = ?SIZESZ + ?MAGICSZ). 29-define(HEADSZ, 8). 30-define(SIZESZ, 4). 31-define(MAGICSZ, 4). 32-define(HEADERSZ, 8). 33-define(MAGICHEAD, <<12,33,44,55>>). 34-define(MAGICINT, 203500599). %% ?MAGICHEAD = <<?MAGICINT:32>> 35-define(BIGMAGICHEAD, <<98,87,76,65>>). 36-define(BIGMAGICINT, 1649888321). %% ?BIGMAGICHEAD = <<?BIGMAGICINT:32>> 37-define(MIN_MD5_TERM, 65528).% (?MAX_CHUNK_SIZE - ?HEADERSZ) 38 39-define(MAX_FILES, 65000). 40-define(MAX_BYTES, ((1 bsl 64) - 1)). 41-define(MAX_CHUNK_SIZE, 65536). 42-define(MAX_FWRITE_CACHE, 65536). 43 44%% Object defines 45-define(LOGMAGIC, <<1,2,3,4>>). 46-define(OPENED, <<6,7,8,9>>). 47-define(CLOSED, <<99,88,77,11>>). 48 49%% Needed for the definition of #file_info{} 50%% Must use include_lib() so that we always can be sure to find 51%% file.hrl. A relative path will not work in an installed system. 52-include_lib("kernel/include/file.hrl"). 53 54%%------------------------------------------------------------------------ 55%% Types -- alphabetically 56%%------------------------------------------------------------------------ 57 58-type dlog_format() :: 'external' | 'internal'. 59-type dlog_format_type() :: 'halt_ext' | 'halt_int' | 'wrap_ext' | 'wrap_int'. 60-type dlog_head() :: 'none' | {'ok', binary()} | mfa(). 61-type dlog_head_opt() :: none | term() | iodata(). 62-type log() :: term(). % XXX: refine 63-type dlog_mode() :: 'read_only' | 'read_write'. 64-type dlog_name() :: atom() | string(). 65-type dlog_optattr() :: 'name' | 'file' | 'linkto' | 'repair' | 'type' 66 | 'format' | 'size' | 'notify' 67 | 'head' | 'head_func' | 'mode'. 68-type dlog_option() :: {name, Log :: log()} 69 | {file, FileName :: file:filename()} 70 | {linkto, LinkTo :: none | pid()} 71 | {repair, Repair :: true | false | truncate} 72 | {type, Type :: dlog_type()} 73 | {format, Format :: dlog_format()} 74 | {size, Size :: dlog_size()} 75 | {notify, boolean()} 76 | {head, Head :: dlog_head_opt()} 77 | {head_func, MFA :: {atom(), atom(), list()}} 78 | {quiet, boolean()} 79 | {mode, Mode :: dlog_mode()}. 80-type dlog_options() :: [dlog_option()]. 81-type dlog_repair() :: 'truncate' | boolean(). 82-type dlog_size() :: 'infinity' | pos_integer() 83 | {MaxNoBytes :: pos_integer(), 84 MaxNoFiles :: pos_integer()}. 85-type dlog_status() :: 'ok' | {'blocked', 'false' | [_]}. %QueueLogRecords 86-type dlog_type() :: 'halt' | 'wrap'. 87 88%%------------------------------------------------------------------------ 89%% Records 90%%------------------------------------------------------------------------ 91 92%% record of args for open 93-record(arg, {name = 0, 94 version = undefined, 95 file = none :: 'none' | file:filename(), 96 repair = true :: dlog_repair(), 97 size = infinity :: dlog_size(), 98 old_size = infinity :: dlog_size(), % read from size file 99 type = halt :: dlog_type(), 100 format = internal :: dlog_format(), 101 linkto = self() :: 'none' | pid(), 102 head = none, 103 mode = read_write :: dlog_mode(), 104 notify = false :: boolean(), 105 quiet = false :: boolean(), 106 options = [] :: dlog_options()}). 107 108-record(cache, %% Cache for logged terms (per file descriptor). 109 {fd :: file:fd(), %% File descriptor. 110 sz = 0 :: non_neg_integer(), %% Number of bytes in the cache. 111 c = [] :: iodata()} %% The cache. 112 ). 113 114-record(halt, %% For a halt log. 115 {fdc :: #cache{}, %% A cache record. 116 curB :: non_neg_integer(), %% Number of bytes on the file. 117 size :: dlog_size()} 118 ). 119 120-record(handle, %% For a wrap log. 121 {filename :: file:filename(), %% Same as log.filename 122 maxB :: pos_integer(), %% Max size of the files. 123 maxF :: pos_integer() | {pos_integer(),pos_integer()}, 124 %% When pos_integer(), maximum number of files. 125 %% The form {NewMaxF, OldMaxF} is used when the 126 %% number of wrap logs are decreased. The files 127 %% are not removed when the size is changed but 128 %% next time the files are to be used, i.e next 129 %% time the wrap log has filled the 130 %% Dir/Name.NewMaxF file. 131 curB :: non_neg_integer(), %% Number of bytes on current file. 132 curF :: integer(), %% Current file number. 133 cur_fdc :: #cache{}, %% Current file descriptor. 134 cur_name :: file:filename(), %% Current file name for error reports. 135 cur_cnt :: non_neg_integer(), %% Number of items on current file, 136 %% header inclusive. 137 acc_cnt :: non_neg_integer(), %% acc_cnt+cur_cnt is number of items 138 %% written since the log was opened. 139 firstPos :: non_neg_integer(), %% Start position for first item 140 %% (after header). 141 noFull :: non_neg_integer(), %% Number of overflows since last 142 %% use of info/1 on this log, or 143 %% since log was opened if info/1 144 %% has not yet been used on this log. 145 accFull :: non_neg_integer()} %% noFull+accFull is number of 146 %% oveflows since the log was opened. 147 ). 148 149-record(log, 150 {status = ok :: dlog_status(), 151 name :: dlog_name(), %% the key leading to this structure 152 blocked_by = none :: 'none' | pid(), %% pid of blocker 153 users = 0 :: non_neg_integer(), %% non-linked users 154 filename :: file:filename(), %% real name of the file 155 owners = [] :: [{pid(), boolean()}],%% [{pid, notify}] 156 type :: dlog_type(), 157 format :: dlog_format(), 158 format_type :: dlog_format_type(), 159 head = none, %% none | {head, H} | {M,F,A} 160 %% called when wraplog wraps 161 mode :: dlog_mode(), 162 size, %% value of open/1 option 'size' (never changed) 163 extra :: #halt{} | #handle{}, %% type of the log 164 version :: integer()} %% if wrap log file 165 ). 166 167-record(continuation, %% Chunk continuation. 168 {pid = self() :: pid(), 169 pos :: non_neg_integer() | {integer(), non_neg_integer()}, 170 b :: binary() | [] | pos_integer()} 171 ). 172 173-type dlog_cont() :: 'start' | #continuation{}. 174