/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Preparation and completion of hprof data generation.  The output is
 * written into two files and then combined.  This is necessary because
 * we generate some of the data (strings and classes) while we dump the
 * heap, and some analysis tools require that the class and string data
 * appear first.
 */

#include "Hprof.h"
#include "alloc/HeapInternal.h"
#include "alloc/Visit.h"

#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <time.h>

#define kHeadSuffix "-hptemp"

hprof_context_t *
hprofStartup(const char *outputFileName, int fd, bool directToDdms)
{
    hprofStartup_String();
    hprofStartup_Class();
#if WITH_HPROF_STACK
    hprofStartup_StackFrame();
    hprofStartup_Stack();
#endif

    hprof_context_t *ctx = malloc(sizeof(*ctx));
    if (ctx == NULL) {
        LOGE("hprof: can't allocate context.\n");
        return NULL;
    }

    /* pass in name or descriptor of the output file */
    hprofContextInit(ctx, strdup(outputFileName), fd, false, directToDdms);

    assert(ctx->memFp != NULL);

    return ctx;
}

/*
 * Finish up the hprof dump.  Returns true on success.
 */
bool
hprofShutdown(hprof_context_t *tailCtx)
{
    /* flush the "tail" portion of the output */
    hprofFlushCurrentRecord(tailCtx);

    /*
     * Create a new context struct for the start of the file.  We
     * heap-allocate it so we can share the "free" function.
     */
    hprof_context_t *headCtx = malloc(sizeof(*headCtx));
    if (headCtx == NULL) {
        LOGE("hprof: can't allocate context.\n");
        hprofFreeContext(tailCtx);
        return false;
    }
    hprofContextInit(headCtx, strdup(tailCtx->fileName), tailCtx->fd, true,
        tailCtx->directToDdms);

    LOGI("hprof: dumping heap strings to \"%s\".\n", tailCtx->fileName);
    hprofDumpStrings(headCtx);
    hprofDumpClasses(headCtx);

    /* Write a dummy stack trace record so the analysis
     * tools don't freak out.
     */
    hprofStartNewRecord(headCtx, HPROF_TAG_STACK_TRACE, HPROF_TIME);
    hprofAddU4ToRecord(&headCtx->curRec, HPROF_NULL_STACK_TRACE);
    hprofAddU4ToRecord(&headCtx->curRec, HPROF_NULL_THREAD);
    hprofAddU4ToRecord(&headCtx->curRec, 0);    // no frames

#if WITH_HPROF_STACK
    hprofDumpStackFrames(headCtx);
    hprofDumpStacks(headCtx);
#endif

    hprofFlushCurrentRecord(headCtx);

    hprofShutdown_Class();
    hprofShutdown_String();
#if WITH_HPROF_STACK
    hprofShutdown_Stack();
    hprofShutdown_StackFrame();
#endif

    /* flush to ensure memstream pointer and size are updated */
    fflush(headCtx->memFp);
    fflush(tailCtx->memFp);

    if (tailCtx->directToDdms) {
        /* send the data off to DDMS */
        struct iovec iov[2];
        iov[0].iov_base = headCtx->fileDataPtr;
        iov[0].iov_len = headCtx->fileDataSize;
        iov[1].iov_base = tailCtx->fileDataPtr;
        iov[1].iov_len = tailCtx->fileDataSize;
        dvmDbgDdmSendChunkV(CHUNK_TYPE("HPDS"), iov, 2);
    } else {
        /*
         * Open the output file, and copy the head and tail to it.
         */
        assert(headCtx->fd == tailCtx->fd);

        int outFd;
        if (headCtx->fd >= 0) {
            outFd = dup(headCtx->fd);
            if (outFd < 0) {
                LOGE("dup(%d) failed: %s\n", headCtx->fd, strerror(errno));
                /* continue to fail-handler below */
            }
        } else {
            outFd = open(tailCtx->fileName, O_WRONLY|O_CREAT|O_TRUNC, 0644);
            if (outFd < 0) {
                LOGE("can't open %s: %s\n", headCtx->fileName, strerror(errno));
                /* continue to fail-handler below */
            }
        }
        if (outFd < 0) {
            hprofFreeContext(headCtx);
            hprofFreeContext(tailCtx);
            return false;
        }

        int result;
        result = sysWriteFully(outFd, headCtx->fileDataPtr,
            headCtx->fileDataSize, "hprof-head");
        result |= sysWriteFully(outFd, tailCtx->fileDataPtr,
            tailCtx->fileDataSize, "hprof-tail");
        close(outFd);
        if (result != 0) {
            hprofFreeContext(headCtx);
            hprofFreeContext(tailCtx);
            return false;
        }
    }

    /* throw out a log message for the benefit of "runhat" */
    LOGI("hprof: heap dump completed (%dKB)\n",
        (headCtx->fileDataSize + tailCtx->fileDataSize + 1023) / 1024);

    hprofFreeContext(headCtx);
    hprofFreeContext(tailCtx);

    return true;
}

/*
 * Free any heap-allocated items in "ctx", and then free "ctx" itself.
 */
void
hprofFreeContext(hprof_context_t *ctx)
{
    assert(ctx != NULL);

    /* we don't own ctx->fd, do not close */

    if (ctx->memFp != NULL)
        fclose(ctx->memFp);
    free(ctx->curRec.body);
    free(ctx->fileName);
    free(ctx->fileDataPtr);
    free(ctx);
}

/*
 * Visitor invoked on every root reference.
 */
static void hprofRootVisitor(void *addr, u4 threadId, RootType type, void *arg)
{
    static const hprof_heap_tag_t xlate[] = {
        HPROF_ROOT_UNKNOWN,
        HPROF_ROOT_JNI_GLOBAL,
        HPROF_ROOT_JNI_LOCAL,
        HPROF_ROOT_JAVA_FRAME,
        HPROF_ROOT_NATIVE_STACK,
        HPROF_ROOT_STICKY_CLASS,
        HPROF_ROOT_THREAD_BLOCK,
        HPROF_ROOT_MONITOR_USED,
        HPROF_ROOT_THREAD_OBJECT,
        HPROF_ROOT_INTERNED_STRING,
        HPROF_ROOT_FINALIZING,
        HPROF_ROOT_DEBUGGER,
        HPROF_ROOT_REFERENCE_CLEANUP,
        HPROF_ROOT_VM_INTERNAL,
        HPROF_ROOT_JNI_MONITOR,
    };
    hprof_context_t *ctx;

    assert(arg != NULL);
    assert(type < NELEM(xlate));
    ctx = arg;
    ctx->gcScanState = xlate[type];
    ctx->gcThreadSerialNumber = threadId;
    hprofMarkRootObject(ctx, addr, 0);
    ctx->gcScanState = 0;
    ctx->gcThreadSerialNumber = 0;
}

/*
 * Visitor invoked on every heap object.
 */
static void hprofBitmapCallback(void *ptr, void *arg)
{
    Object *obj;
    hprof_context_t *ctx;

    assert(ptr != NULL);
    assert(arg != NULL);
    obj = ptr;
    ctx = arg;
    hprofDumpHeapObject(ctx, obj);
}

/*
 * Walk the roots and heap writing heap information to the specified
 * file.
 *
 * If "fd" is >= 0, the output will be written to that file descriptor.
 * Otherwise, "fileName" is used to create an output file.
 *
 * If "directToDdms" is set, the other arguments are ignored, and data is
 * sent directly to DDMS.
 *
 * Returns 0 on success, or an error code on failure.
 */
int hprofDumpHeap(const char* fileName, int fd, bool directToDdms)
{
    hprof_context_t *ctx;
    int success;

    assert(fileName != NULL);
    dvmLockHeap();
    dvmSuspendAllThreads(SUSPEND_FOR_HPROF);
    ctx = hprofStartup(fileName, fd, directToDdms);
    if (ctx == NULL) {
        return -1;
    }
    dvmVisitRoots(hprofRootVisitor, ctx);
    dvmHeapBitmapWalk(dvmHeapSourceGetLiveBits(), hprofBitmapCallback, ctx);
    hprofFinishHeapDump(ctx);
//TODO: write a HEAP_SUMMARY record
    success = hprofShutdown(ctx) ? 0 : -1;
    dvmResumeAllThreads(SUSPEND_FOR_HPROF);
    dvmUnlockHeap();
    return success;
}
