#!/usr/bin/env dnsjit
-- DNS Reply Tool (drool)
--
-- Copyright (c) 2017-2021, OARC, Inc.
-- Copyright (c) 2017, Comcast Corporation
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
--
-- 1. Redistributions of source code must retain the above copyright
--    notice, this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
--    notice, this list of conditions and the following disclaimer in
--    the documentation and/or other materials provided with the
--    distribution.
--
-- 3. Neither the name of the copyright holder nor the names of its
--    contributors may be used to endorse or promote products derived
--    from this software without specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-- FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-- ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
package.path = package.path .. ";/usr/share/drool/lib/?.lua"

local clock = require("dnsjit.lib.clock")
local log = require("dnsjit.core.log").new("drool")
local getopt = require("dnsjit.lib.getopt").new({
    { "V", "version", false, "Print version and exit", "?" },
    { "v", "verbose", 0, "Enable and increase verbosity for each time given", "?+" },
    { nil, "json", false, "Output statistics as JSON", "?" },
    { nil, "csv", false, "Output statistics as CSV", "?" },
})
getopt.usage_desc = arg[1] .. " command [options...] <arguments...>"

local cmds = {
    replay = "drool.replay",
    respdiff = "drool.respdiff",
}

if not arg[2] or not cmds[arg[2]] then
    getopt:parse()

    if getopt:val("help") then
        getopt:usage()
        os.exit(0)
    end
    if getopt:val("version") then
        print("drool version 2.0.0")
        os.exit(0)
    end
    if arg[2] then
        log:critical("Command "..arg[2].." not found")
    end

    getopt:usage()
    os.exit(-1)
end

local cmd = require(cmds[arg[2]]).new(getopt)
getopt:parse()

if getopt:val("help") then
    getopt:usage()
    os.exit(0)
end

local v = getopt:val("v")
if v > 0 then
    require("dnsjit.core.log").enable("warning")
end
if v > 1 then
    require("dnsjit.core.log").enable("notice")
end
if v > 2 then
    require("dnsjit.core.log").enable("info")
end
if v > 3 then
    require("dnsjit.core.log").enable("debug")
end

cmd:getopt(getopt)
cmd:setup()
local start_sec, start_nsec = clock:monotonic()
cmd:run()
local end_sec, end_nsec = clock:monotonic()
cmd:finish()
local fin_sec, fin_nsec = clock:monotonic()

local runtime = 0
if end_sec > start_sec then
    runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
elseif end_sec == start_sec and end_nsec > start_nsec then
    runtime = (end_nsec - start_nsec) / 1000000000
end

local finish = 0
if fin_sec > end_sec then
    finish = ((fin_sec - end_sec) - 1) + ((1000000000 - end_nsec + fin_nsec)/1000000000)
elseif fin_sec == end_sec and fin_nsec > end_nsec then
    finish = (fin_nsec - end_nsec) / 1000000000
end

if getopt:val("json") then
    print("{")
    print("  \"runtime\": " .. runtime .. ",")
    print("  \"finish\": " .. finish .. ",")
    print("  \"packets\": " .. cmd.packets .. ",")
    print("  \"queries\": " .. cmd.queries .. ",")
    print("  \"sent\": " .. cmd.sent .. ",")
    print("  \"received\": " .. cmd.received .. ",")
    print("  \"responses\": " .. cmd.responses .. ",")
    print("  \"timeouts\": " .. cmd.timeouts .. ",")
    print("  \"errors\": " .. cmd.errors)
    print("}")
elseif getopt:val("csv") then
    print("runtime,finish,packets,queries,sent,received,responses,timeouts,errors")
    print(runtime ..","..
        finish ..","..
        cmd.packets ..","..
        cmd.queries ..","..
        cmd.sent ..","..
        cmd.received ..","..
        cmd.responses ..","..
        cmd.timeouts ..","..
        cmd.errors)
else
    print("runtime", runtime+finish, "run", runtime, "finish", finish)
    print("", "total", "/sec")
    print("packets", cmd.packets, cmd.packets/runtime)
    print("queries", cmd.queries, cmd.queries/runtime)
    print("sent", cmd.sent, cmd.sent/runtime)
    print("received", cmd.received, cmd.received/runtime)
    print("responses", cmd.responses, cmd.responses/runtime)
    print("timeouts", cmd.timeouts)
    print("errors", cmd.errors)
end
