/*
 * 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();

    hprof_context_t *ctx = (hprof_context_t *)malloc(sizeof(*ctx));
    if (ctx == NULL) {
        LOGE("hprof: can't allocate context.");
        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 = (hprof_context_t *)malloc(sizeof(*headCtx));
    if (headCtx == NULL) {
        LOGE("hprof: can't allocate context.");
        hprofFreeContext(tailCtx);
        return false;
    }
    hprofContextInit(headCtx, strdup(tailCtx->fileName), tailCtx->fd, true,
        tailCtx->directToDdms);

    LOGI("hprof: dumping heap strings to \"%s\".", 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

    hprofFlushCurrentRecord(headCtx);

    hprofShutdown_Class();
    hprofShutdown_String();

    /* 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", 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", 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)",
        (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;
    Object *obj;

    assert(addr != NULL);
    assert(arg != NULL);
    assert(type < NELEM(xlate));
    obj = *(Object **)addr;
    if (obj == NULL) {
        return;
    }
    ctx = (hprof_context_t *)arg;
    ctx->gcScanState = xlate[type];
    ctx->gcThreadSerialNumber = threadId;
    hprofMarkRootObject(ctx, obj, 0);
    ctx->gcScanState = 0;
    ctx->gcThreadSerialNumber = 0;
}

/*
 * Visitor invoked on every heap object.
 */
static void hprofBitmapCallback(Object *obj, void *arg)
{
    assert(obj != NULL);
    assert(arg != NULL);
    hprof_context_t *ctx = (hprof_context_t *)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;
}
