#!/usr/bin/python2
#
# Copyright 2015 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
# Refer to the README and COPYING files for full details of the license
#

"""
Usage: logdb dbname logfile ...

Import vdsm log files into log database dbname.
"""

import sqlite3
import sys


CREATE_TABLE = """
create table if not exists messages(
    timestamp datetime,
    level text,
    logger text,
    thread text,
    module text,
    lineno int,
    func text,
    text text
);
"""

DROP_INDEXES = """
drop index if exists timestamp;
drop index if exists level;
drop index if exists thread;
drop index if exists module;
drop index if exists func;
"""

CREATE_INDEXES = """
create index timestamp on messages (timestamp);
create index level on messages (level);
create index thread on messages (thread);
create index module on messages (module);
create index func on messages (func);
"""


def main(args):
    if len(args) < 2:
        print __doc__
        sys.exit(2)

    dbname = args.pop(0)
    with sqlite3.connect(dbname) as con:
        con.execute(CREATE_TABLE)
        con.executescript(DROP_INDEXES)
        for logfile in args:
            with open(logfile) as f:
                for msg in parse(f):
                    con.execute("insert into messages values "
                                "(?,?,?,?,?,?,?,?)", msg)
        con.executescript(CREATE_INDEXES)
        con.commit()


def parse(logfile):
    msg = None
    for line in logfile:
        line = line.rstrip()
        try:
            # thread::level::timestamp::module::lineno::logger::(func) message
            thread, level, timestamp, module, lineno, logger, rest = \
                line.split("::", 6)
        except ValueError:
            # Some message text has multiple lines
            if msg:
                msg[-1] += "\n" + line
        else:
            # Y-m-d H-M-S,msec -> Y-m-d H-M-S.msec
            timestamp = timestamp.replace(",", ".")
            # (func) text
            try:
                func, text = rest.split(" ", 1)
            except ValueError:
                func, text = rest, ""
            func = func[1:-1]
            if msg:
                yield tuple(msg)
            msg = [timestamp, level, logger, thread, module, lineno, func,
                   text]
    if msg:
        yield tuple(msg)


if __name__ == "__main__":
    main(sys.argv[1:])
