#!/bin/bash
set -u

DIR="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
MYSQLITE3="$DIR"/sqlite3

# check number of arguments
if [ $# -ne 1 ]; then
    echo " usage: ${BASH_SOURCE[0]} [SQLite DB file exported from NSys QDREP file]"
    exit 1
fi

# check if file exists
if [ ! -f "$1" ]
then
    echo "$1 file not found. Exiting"
    exit 1
fi

# check if file opened is DB; if not, exit
# The sqlite3 file format is defined at https://www.sqlite.org/draft/fileformat.html
HEADER=$(head -c 16 "$1" | tr '\0' '\n')
if [ "$HEADER" != "SQLite format 3" ]
then
    echo "$1 is not an SQlite DB file. Exiting."
    exit 1
fi

# check if DB contains OpenMP event tables; if not, exit
GET_TABLE_COUNT()
{
    echo $("$MYSQLITE3" "$1" "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='$2'");
}

THREAD_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_THREAD")
PARALLEL_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_PARALLEL")
SYNC_REGION_WAIT_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_SYNC_REGION_WAIT")
SYNC_REGION_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_SYNC_REGION")
TASK_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_TASK")
MASTER_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_MASTER")
REDUCTION_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_REDUCTION")
TASK_CREATE_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_TASK_CREATE")
TASK_SCHEDULE_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_TASK_SCHEDULE")
CANCEL_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_CANCEL")
MUTEX_WAIT_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_MUTEX_WAIT")
CRITICAL_SECTION_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_CRITICAL_SECTION")
MUTEX_RELEASED_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_MUTEX_RELEASED")
LOCK_INIT_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_LOCK_INIT")
LOCK_DESTROY_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_LOCK_DESTROY")
WORKSHARE_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_WORKSHARE")
DISPATCH_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_DISPATCH")
FLUSH_TABLE_COUNT=$(GET_TABLE_COUNT "$1" "OPENMP_EVENT_KIND_FLUSH")

TOTAL_TABLE_COUNT=$((THREAD_TABLE_COUNT + PARALLEL_TABLE_COUNT + \
    SYNC_REGION_WAIT_TABLE_COUNT + SYNC_REGION_TABLE_COUNT + TASK_TABLE_COUNT + \
    REDUCTION_TABLE_COUNT + TASK_CREATE_TABLE_COUNT + TASK_SCHEDULE_TABLE_COUNT + \
    CANCEL_TABLE_COUNT + MUTEX_WAIT_TABLE_COUNT + CRITICAL_SECTION_TABLE_COUNT + \
    MUTEX_RELEASED_TABLE_COUNT + LOCK_INIT_TABLE_COUNT + LOCK_DESTROY_TABLE_COUNT + \
    WORKSHARE_TABLE_COUNT + DISPATCH_TABLE_COUNT + FLUSH_TABLE_COUNT))

if [ $TOTAL_TABLE_COUNT -eq 0 ]
then
    echo "OpenMP events were not collected."
    exit 0
fi

# check if openMPEventStats table exists
if [ "$("$MYSQLITE3" "$1" "SELECT name FROM sqlite_master WHERE type='table' AND name='openMPEventStats';")" != "openMPEventStats" ]
then
    printf "\nGenerating OpenMP event Statistics...\n"

    GENERATE_SUMMARY="""PRAGMA SYNCHRONOUS=OFF;
    CREATE TABLE openMPEventStats (nameId INTEGER, num INTEGER, min INTEGER, max INTEGER, avg INTEGER, total INTEGER);
    """

    GENERATE_FROM_EVENT_TYPE()
    {
        COUNTER_NAME="$1_TABLE_COUNT"
        # check if table exists before selecting. we cannot select from nonexistent table.
        if [ ${!COUNTER_NAME} -gt 0 ]
        then
            GENERATE_SUMMARY+="INSERT INTO openMPEventStats SELECT nameId, count(nameId), min(end-start), max(end-start), avg(end-start), sum(end-start) FROM OPENMP_EVENT_KIND_$1 GROUP BY nameId;"
        fi
    }

    GENERATE_FROM_EVENT_TYPE "THREAD"
    GENERATE_FROM_EVENT_TYPE "PARALLEL"
    GENERATE_FROM_EVENT_TYPE "SYNC_REGION_WAIT"
    GENERATE_FROM_EVENT_TYPE "SYNC_REGION"
    GENERATE_FROM_EVENT_TYPE "TASK"
    GENERATE_FROM_EVENT_TYPE "MASTER"
    GENERATE_FROM_EVENT_TYPE "REDUCTION"
    GENERATE_FROM_EVENT_TYPE "TASK_CREATE"
    GENERATE_FROM_EVENT_TYPE "TASK_SCHEDULE"
    GENERATE_FROM_EVENT_TYPE "CANCEL"
    GENERATE_FROM_EVENT_TYPE "MUTEX_WAIT"
    GENERATE_FROM_EVENT_TYPE "CRITICAL_SECTION"
    GENERATE_FROM_EVENT_TYPE "MUTEX_RELEASED"
    GENERATE_FROM_EVENT_TYPE "LOCK_INIT"
    GENERATE_FROM_EVENT_TYPE "LOCK_DESTROY"
    GENERATE_FROM_EVENT_TYPE "WORKSHARE"
    GENERATE_FROM_EVENT_TYPE "DISPATCH"
    GENERATE_FROM_EVENT_TYPE "FLUSH"

    "$MYSQLITE3" "$1" "$GENERATE_SUMMARY"
fi

printf "OpenMP event Statistics (nanoseconds)\n\n"
TOTALTIME=$("$MYSQLITE3" "$1" "SELECT sum(total) FROM openMPEventStats");
echo -e ".width -7 -14 -10 -14 -14 -14 80 \n SELECT
    round((total*100.0)/$TOTALTIME,1) as 'Time(%)', total as 'Total Time',
    num as Count, round(avg,1) as 'Average', min as 'Minimum',
    max as 'Maximum', value as Name
    FROM openMPEventStats INNER JOIN StringIds ON StringIds.id = openMPEventStats.nameId
    ORDER BY total DESC;" | "$MYSQLITE3" -column -header "$1"

printf "\n\n"
