/*
 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. 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.
 * 
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
 *
 */

#include "config.h"
#include "WebMemorySampler.h"

#if ENABLE(MEMORY_SAMPLER)

#include <wtf/text/CString.h>

using namespace WebCore;

namespace WebKit {


WebMemorySampler* WebMemorySampler::shared()
{
    static WebMemorySampler* sharedMemorySampler;
    if (!sharedMemorySampler)
        sharedMemorySampler = new WebMemorySampler();
    return sharedMemorySampler;
}

WebMemorySampler::WebMemorySampler() 
    : m_separator(String("\t"))  
    , m_sampleTimer(this, &WebMemorySampler::sampleTimerFired)
    , m_stopTimer(this, &WebMemorySampler::stopTimerFired)
    , m_isRunning(false)
    , m_runningTime(0)
{
}

void WebMemorySampler::start(const double interval) 
{
    if (m_isRunning) 
        return;
    
    initializeTempLogFile();
    initializeTimers(interval);
}

void WebMemorySampler::start(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval) 
{
    if (m_isRunning) 
        return;
    
    // If we are on a system without SandboxExtension the handle and filename will be empty
    if (sampleLogFilePath.isEmpty()) {
        start(interval);
        return;
    }
        
    initializeSandboxedLogFile(sampleLogFileHandle, sampleLogFilePath);
    initializeTimers(interval);
   
}

void WebMemorySampler::initializeTimers(double interval)
{
    m_sampleTimer.startRepeating(1);
    printf("Started memory sampler for process %s", processName().utf8().data());
    if (interval > 0) {
        m_stopTimer.startOneShot(interval);
        printf(" for a interval of %g seconds", interval);
    }
    printf("; Sampler log file stored at: %s\n", m_sampleLogFilePath.utf8().data());
    m_runningTime = interval;
    m_isRunning = true;
}

void WebMemorySampler::stop() 
{
    if (!m_isRunning) 
        return;
    m_sampleTimer.stop();
    m_sampleLogFile = 0;
    printf("Stopped memory sampler for process %s\n", processName().utf8().data());
    // Flush stdout buffer so python script can be guaranteed to read up to this point.
    fflush(stdout);
    m_isRunning = false;
    
    if(m_stopTimer.isActive())
        m_stopTimer.stop();
    
    if (m_sampleLogSandboxExtension) {
        m_sampleLogSandboxExtension->invalidate();
        m_sampleLogSandboxExtension = 0;
    }    
}

bool WebMemorySampler::isRunning() const
{
    return m_isRunning;
}
    
void WebMemorySampler::initializeTempLogFile()
{
    m_sampleLogFilePath = openTemporaryFile(processName(), m_sampleLogFile);
    writeHeaders();
}

void WebMemorySampler::initializeSandboxedLogFile(const SandboxExtension::Handle& sampleLogSandboxHandle, const String& sampleLogFilePath)
{
    m_sampleLogSandboxExtension = SandboxExtension::create(sampleLogSandboxHandle);
    if (m_sampleLogSandboxExtension)
        m_sampleLogSandboxExtension->consume();
    m_sampleLogFilePath = sampleLogFilePath;
    m_sampleLogFile = openFile(m_sampleLogFilePath, OpenForWrite);
    writeHeaders();
}

void WebMemorySampler::writeHeaders()
{
    String processDetails = String("Process: ");
    processDetails.append(processName());
    processDetails.append(String("\n"));
    writeToFile(m_sampleLogFile, processDetails.utf8().data(), processDetails.utf8().length());
    
    String header; 
    WebMemoryStatistics stats = sampleWebKit();
    if (!stats.keys.isEmpty()) {
        for (size_t i = 0; i < stats.keys.size(); ++i) {
            header.append(m_separator);
            header.append(stats.keys[i].utf8().data());
        }
    }
    header.append(String("\n"));
    writeToFile(m_sampleLogFile, header.utf8().data(), header.utf8().length());
}

void WebMemorySampler::sampleTimerFired(Timer<WebMemorySampler>*)
{
    appendCurrentMemoryUsageToFile(m_sampleLogFile); 
}

void WebMemorySampler::stopTimerFired(Timer<WebMemorySampler>*)
{
    if (!m_isRunning)
        return;
    printf("%g seconds elapsed. Stopping memory sampler...\n", m_runningTime);
    stop();
}

void WebMemorySampler::appendCurrentMemoryUsageToFile(PlatformFileHandle& file)
{
    // Collect statistics from allocators and get RSIZE metric
    String statString; 
    WebMemoryStatistics memoryStats = sampleWebKit();

    if (!memoryStats.values.isEmpty()) {
        statString.append(m_separator);
        for (size_t i = 0; i < memoryStats.values.size(); ++i) {
            statString.append(m_separator);
            statString.append(String::format("%lu", memoryStats.values[i]));
        }
    }
    statString.append(String("\n"));
    writeToFile(m_sampleLogFile, statString.utf8().data(), statString.utf8().length());
}

}

#endif
