/*
 * Copyright (C) 2015 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 "NetworkCacheBlobStorage.h"

#include "Logging.h"
#include "NetworkCacheFileSystem.h"
#include <fcntl.h>
#include <wtf/FileSystem.h>
#include <wtf/RunLoop.h>
#include <wtf/SHA1.h>

#if !OS(WINDOWS)
#include <sys/stat.h>
#endif

namespace WebKit {
namespace NetworkCache {

BlobStorage::BlobStorage(const String& blobDirectoryPath, Salt salt)
    : m_blobDirectoryPath(blobDirectoryPath)
    , m_salt(salt)
{
}

String BlobStorage::blobDirectoryPathIsolatedCopy() const
{
    return m_blobDirectoryPath.isolatedCopy();
}

void BlobStorage::synchronize()
{
    ASSERT(!RunLoop::isMain());

    auto blobDirectoryPath = blobDirectoryPathIsolatedCopy();
    FileSystem::makeAllDirectories(blobDirectoryPath);

    m_approximateSize = 0;
    auto blobDirectory = blobDirectoryPath;
    traverseDirectory(blobDirectory, [this, &blobDirectory](const String& name, DirectoryEntryType type) {
        if (type != DirectoryEntryType::File)
            return;
        auto path = FileSystem::pathByAppendingComponent(blobDirectory, name);
        auto filePath = FileSystem::fileSystemRepresentation(path);
        struct stat stat;
        ::stat(filePath.data(), &stat);
        // No clients left for this blob.
        if (stat.st_nlink == 1)
            unlink(filePath.data());
        else
            m_approximateSize += stat.st_size;
    });

    LOG(NetworkCacheStorage, "(NetworkProcess) blob synchronization completed approximateSize=%zu", approximateSize());
}

String BlobStorage::blobPathForHash(const SHA1::Digest& hash) const
{
    auto hashAsString = SHA1::hexDigest(hash);
    return FileSystem::pathByAppendingComponent(blobDirectoryPathIsolatedCopy(), String::fromUTF8(hashAsString));
}

BlobStorage::Blob BlobStorage::add(const String& path, const Data& data)
{
    ASSERT(!RunLoop::isMain());

    auto hash = computeSHA1(data, m_salt);
    if (data.isEmpty())
        return { data, hash };

    String blobPath = blobPathForHash(hash);
    
    FileSystem::deleteFile(path);

    bool blobExists = FileSystem::fileExists(blobPath);
    if (blobExists) {
        FileSystem::makeSafeToUseMemoryMapForPath(blobPath);
        auto existingData = mapFile(blobPath);
        if (bytesEqual(existingData, data)) {
            if (!FileSystem::hardLink(blobPath, path))
                WTFLogAlways("Failed to create hard link from %s to %s", blobPath.utf8().data(), path.utf8().data());
            return { existingData, hash };
        }
        FileSystem::deleteFile(blobPath);
    }

    auto mappedData = data.mapToFile(blobPath);
    if (mappedData.isNull())
        return { };

    if (!FileSystem::hardLink(blobPath, path))
        WTFLogAlways("Failed to create hard link from %s to %s", blobPath.utf8().data(), path.utf8().data());

    m_approximateSize += mappedData.size();

    return { mappedData, hash };
}

BlobStorage::Blob BlobStorage::get(const String& path)
{
    ASSERT(!RunLoop::isMain());

    auto linkPath = FileSystem::fileSystemRepresentation(path);
    auto data = mapFile(linkPath.data());

    return { data, computeSHA1(data, m_salt) };
}

void BlobStorage::remove(const String& path)
{
    ASSERT(!RunLoop::isMain());

    FileSystem::deleteFile(path);
}

unsigned BlobStorage::shareCount(const String& path)
{
    ASSERT(!RunLoop::isMain());

    auto linkPath = FileSystem::fileSystemRepresentation(path);
    struct stat stat;
    if (::stat(linkPath.data(), &stat) < 0)
        return 0;
    // Link count is 2 in the single client case (the blob file and a link).
    return stat.st_nlink - 1;
}

}
}
