=head1 NAME

makehistory - Initialize or rebuild INN history database

=head1 SYNOPSIS

B<makehistory> [B<-abFIOSx>] [B<-f> I<filename>] [B<-l> I<count>]
[B<-L> I<load-average>] [B<-s> I<size>] [B<-T> I<tmpdir>]

=head1 DESCRIPTION

B<makehistory> rebuilds the history database, which contains a list of
message-IDs of articles already seen by the server.  It can also be used
to rebuild the overview database.

Note that, when the C<hisv6> history storage method is configured, even though
the I<dbz> indices for the F<history> file are also rebuilt by B<makehistory>,
it is useful to run makedbz(8) after makehistory(8) in order to improve the
efficiency of the indices (B<makehistory> does not know how large to make the
hash table at first run, unless the size is given by the B<-s> flag).

The default location of the history database is I<pathhistory>/F<history>
for the C<hisv6> storage method, and I<pathhistory>/F<history.sqlite> for the
C<hissqlite> storage method; to specify an alternate location, use the B<-f>
flag.

By default, B<makehistory> will scan the entire spool, using the storage
manager, and write a history line for every article.  To also generate
overview information, use the B<-O> flag.

If a malformed article is found in the news spool, in a way which prevents its
integration into the history or overview data, a log line will be output and
the malformed article will just be skipped.

When the C<hissqlite> history storage method is configured, B<makehistory>
writes the new history into a hissqlite database just as it does for C<hisv6>,
and the makedbz(8) step above does not apply.  It commits the writes in large
batched transactions rather than one per article, which makes the rebuild
substantially faster; this relies on B<makehistory> being the only history
writer, which its use already requires (see the B<-a> flag description).
A from-spool rebuild cannot recover I<remembered> Message-IDs, so to
migrate an existing C<hisv6> history into hissqlite without losing them, use
hissqlite-convert(8) instead.  See hissqlite(5).

=head1 OVERVIEW REBUILD

I<WARNING>: If you're trying to rebuild the overview database, be sure to
stop innd(8) and delete or zero out the existing database before you start
for the best results.  An overview rebuild should not be done while the
server is running.  Unless the existing overview is deleted, you may end
up with problems like out-of-order overview entries, excessively large
overview buffers, and the like.

If I<ovmethod> in F<inn.conf> is C<ovdb>, you must have the ovdb processes
running while rebuilding overview.  ovdb needs them available while
writing overview entries.  You can start them by hand separate from the
rest of the server by running B<ovdb_init>; see ovdb_init(8) for more
details.

Similarly, if I<ovmethod> in F<inn.conf> is C<ovsqlite>, you must
have the B<ovsqlite-server> process running while rebuilding overview.
See ovsqlite-server(8) for more details and how to start it by hand.

Rebuilding overview data is as straight-forward as:

=over 4

=item 1.

Checking that the configuration file of the new overview storage method is
present in I<pathetc> and fits your needs (F<buffindexed.conf>, F<ovdb.conf>
or F<ovsqlite.conf>).  Note that the tradindexed overview storage method does
not have a dedicated configuration file.

=item 2.

Making sure that INN is stopped (C<rc.news stop> as the news user, or
whichever command you're using).

=item 3.

Setting the new overview storage method in the I<ovmethod> parameter
in F<inn.conf>.

=item 4.

Making sure that the directory specified by the I<pathoverview> parameter in
F<inn.conf> exists and is empty (or contains freshly created buffindexed
buffers, if using that overview storage method).  Otherwise, rename
the current directory (to back up existing overview data) and re-create
I<pathoverview> as the news user.

=item 5.

Starting B<ovdb_init> or B<ovsqlite-server> as the news user if the new
overview storage method is respectively ovdb or ovsqlite.

=item 6.

Running C<makehistory -O -x -F> and waiting for the command to finish.
(You may notice a few logs about articles for which overview data cannot be
inserted into the new overview storage method.  As long as there aren't tons
of them, it is normal, notably because there is an internal limit in the
length of overview data generated by B<makehistory>, contrary to B<innd>.
Unfortunately, these rare articles won't be present in the new overview.)

=item 7.

Stopping ovdb or ovsqlite helper programs if you started them during the
previous steps (running C<rc.news stop> as the news user will stop them;
do not mind the messages related to the fact that the news server was not
running).

=item 8.

Starting INN and checking the logs to make sure everything is fine.
You will normally notice that the F<active> file is renumbered
(B<rc.news> takes care of that when run after an overview rebuild;
otherwise, manually run C<ctlinnd renumber ''>).

=back

=head1 OPTIONS

=over 4

=item B<-a>

Append to the history database rather than generating a new one.  If you
append to the main history database, make sure innd(8) is throttled or not
running, or you can corrupt the history.

=item B<-b>

Delete any messages found in the spool that do not have valid Message-ID
header fields in them.

=item B<-F>

Fork a separate process to flush overview data to disk rather than doing
it directly.  The advantage of this is that it allows B<makehistory> to
continue to collect more data from the spool while the first batch of data
is being written to the overview database.  The disadvantage is that up to
twice as much temporary disk space will be used for the generated overview
data.  This option only makes sense in combination with B<-O>.  With
buffindexed, the B<overchan> program is invoked to write overview.

=item B<-f> I<filename>

Rather than writing directly to the default F<history> or F<history.sqlite>
databases in I<pathhistory>, instead write to I<filename>, also in
I<pathhistory>.

=item B<-I>

Don't store overview data for articles numbered lower than the lowest
article number in F<active>.  This is useful if there are for whatever
reason old articles on disk that shouldn't be available to readers or put
into the overview database.

=item B<-l> I<count>

This option specifies how many articles to process before writing the
accumulated overview information out to the overview database.  The
default is C<10000>.  Since overview write performance is faster with
sorted data, each "batch" gets sorted.  Increasing the batch size
with this option may further improve write performance, at the cost
of longer sort times.  Also, temporary space will be needed to store
the overview batches.  At a rough estimate, about 300 * I<count> bytes
of temporary space will be required (not counting temp files created
by sort(1)).  See the description of the B<-T> option for how to
specify the temporary storage location.  This option has no effect
with buffindexed, because buffindexed does not need sorted
overview and no batching is done.

=item B<-L> I<load-average>

Temporarily pause activities if the system load average exceeds the
specified level I<load-average>.  This allows B<makehistory> to run
on a system being used for other purposes without monopolizing system
resources and thus making the response time for other applications
unacceptably slow.  Using nice(1) does not help much for that because
the problem comes from disk I/O usage, and ionice(1) is not always
available or efficient.

=item B<-O>

Create the overview database as well as the history database.  Overview
information is only required if the server supports readers; it is not
needed for a transit-only server (see I<enableoverview> in inn.conf(5)).
If you are using the buffindexed overview storage method, erase all of
your overview buffers before running B<makehistory> with B<-O>.

=item B<-S>

Rather than storing the overview data into the overview database, just write
it to standard output in a form suitable for feeding to B<overchan> later
if wished.  When this option is used, B<-F>, B<-I>, B<-l>, and B<-T> are
ignored.  This option only makes sense in combination with B<-O>.

=item B<-s> I<size>

Size the C<hisv6> history database for approximately I<size> key-value pairs
(i.e. lines in F<history>).  Accurately specifying the size is an optimization
that will create a more efficient database.  (The size should be the estimated
eventual number of articles, typically the size of the old F<history> file,
in lines.)  This has no effect for a C<hissqlite> history database as the
B-tree grows itself when needed; there is no fixed-size table to presize and
no rebuild-to-grow.

By default when C<hisv6> is used, B<makehistory> will create a database
optimized for handling about 6,000,000 articles (or 500,000 if the slower
tagged hash format is used).  This size does not limit the number of articles
the news server can store in its F<history> file.  It will just get slower
when that optimal size is exceeded, until the next run of B<news.daily> which
will appropriately resize it.

=item B<-T> I<tmpdir>

If B<-O> is given, B<makehistory> needs a location to write temporary
overview data.  By default, it uses I<pathtmp>, set in F<inn.conf>, but if
this option is given, the provided I<tmpdir> is used instead.  This is
also used for temporary files created by sort(1) (which is invoked in the
process of writing overview information since sorted overview information
writes faster).  By default, B<sort> usually uses your system temporary
directory; see the sort(1) man page on your system to be sure.

=item B<-x>

If this option is given, B<makehistory> won't write out history entries.
This is useful mostly for building overview without generating a new history
database.

=back

=head1 EXAMPLES

Here's a typical example of rebuilding the entire C<hisv6> history and overview
database, removing broken articles in the news spool.  This uses the
default temporary file locations and should be done while B<innd> isn't
running (or is throttled).

    makehistory -b -f history.n -O -l 30000 -I

This will rebuild the overview (if using buffindexed, erase the
existing overview buffers before running this command) and leave a new
F<history> file as C<history.n> in I<pathhistory>.  To preserve all of the
history entries from the old F<history> file that correspond to rejected
articles or expired articles, follow the above command with:

    cd <pathhistory>
    awk 'NF == 2 { print }' < history >> history.n

(replacing the path with your I<pathhistory>, if it isn't the default).  Then
look over the new F<history> file for problems and run:

    makedbz -s `wc -l < history.n` -f history.n

Then rename all of the files matching C<history.n.*> to C<history.*>,
replacing the current history database and indices.  After that, it's safe
to unthrottle B<innd>.

For a simpler example with C<hisv6>:

    makehistory -b -f history.n -I -O

will scan the spool, removing broken articles and generating history and
overview entries for articles missing from history.

With C<hissqlite>, just run:

    makehistory -b -I -O

To pre-size the C<hisv6> F<history> file for 100,000,000 articles, and generate
overview data at the same time, you may directly use the following command:

    makehistory -O -s 100000000

You then do not need running B<makedbz> as the F<history> file has already
been generated and optimized for the expected number of articles.

To just rebuild overview (whathever history method you use):

    makehistory -O -x -F

=head1 FILES

=over 4

=item I<pathhistory>/history

This is the default output file for B<makehistory> with the C<hisv6> history
storage method.

=item I<pathhistory>/history.sqlite

This is the default output file for B<makehistory> with the C<hissqlite>
history storage method.

=item I<pathtmp>

Where temporary files are written unless B<-T> is given.

=back

=head1 HISTORY

Originally written by Rich $alz <rsalz@uunet.uu.net> for InterNetNews and
updated by various other people since.

=head1 SEE ALSO

active(5), ctlinnd(8), hissqlite(5), hissqlite-convert(8), history(5),
inn.conf(5), innd(8), libinn_dbz(3), makedbz(8), ovdb_init(8), overchan(8),
ovsqlite-server(8).

=cut
