/*
 * Copyright (C) 2017 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.
 */

#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER

#include "CacheTracker.h"

#include <fts.h>
#include <sys/xattr.h>
#include <utils/Trace.h>

#include <android-base/logging.h>
#include <android-base/stringprintf.h>

#include "QuotaUtils.h"
#include "utils.h"

using android::base::StringPrintf;

namespace android {
namespace installd {

CacheTracker::CacheTracker(userid_t userId, appid_t appId, const std::string& uuid)
      : cacheUsed(0),
        cacheQuota(0),
        mUserId(userId),
        mAppId(appId),
        mItemsLoaded(false),
        mUuid(uuid) {
}

CacheTracker::~CacheTracker() {
}

std::string CacheTracker::toString() {
    return StringPrintf("UID=%d used=%" PRId64 " quota=%" PRId64 " ratio=%d",
            multiuser_get_uid(mUserId, mAppId), cacheUsed, cacheQuota, getCacheRatio());
}

void CacheTracker::addDataPath(const std::string& dataPath) {
    mDataPaths.push_back(dataPath);
}

void CacheTracker::loadStats() {
    ATRACE_BEGIN("loadStats quota");
    cacheUsed = 0;
    if (loadQuotaStats()) {
        return;
    }
    ATRACE_END();

    ATRACE_BEGIN("loadStats tree");
    cacheUsed = 0;
    for (const auto& path : mDataPaths) {
        auto cachePath = read_path_inode(path, "cache", kXattrInodeCache);
        auto codeCachePath = read_path_inode(path, "code_cache", kXattrInodeCodeCache);
        calculate_tree_size(cachePath, &cacheUsed);
        calculate_tree_size(codeCachePath, &cacheUsed);
    }
    ATRACE_END();
}

bool CacheTracker::loadQuotaStats() {
    int cacheGid = multiuser_get_cache_gid(mUserId, mAppId);
    if (IsQuotaSupported(mUuid) && cacheGid != -1) {
        int64_t space;
        if ((space = GetOccupiedSpaceForGid(mUuid, cacheGid)) != -1) {
            cacheUsed += space;
        } else {
            return false;
        }

        if ((space = get_occupied_app_cache_space_external(mUuid, mUserId, mAppId)) != -1) {
            cacheUsed += space;
        } else {
            return false;
        }
        return true;
    } else {
        return false;
    }
}

void CacheTracker::loadItemsFrom(const std::string& path) {
    FTS *fts;
    FTSENT *p;
    char *argv[] = { (char*) path.c_str(), nullptr };
    if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) {
        PLOG(WARNING) << "Failed to fts_open " << path;
        return;
    }
    while ((p = fts_read(fts)) != nullptr) {
        if (p->fts_level == 0) continue;

        // Create tracking nodes for everything we encounter
        switch (p->fts_info) {
        case FTS_D:
        case FTS_DEFAULT:
        case FTS_F:
        case FTS_SL:
        case FTS_SLNONE: {
            auto item = std::shared_ptr<CacheItem>(new CacheItem(p));
            p->fts_pointer = static_cast<void*>(item.get());
            items.push_back(item);
        }
        }

        switch (p->fts_info) {
        case FTS_D: {
            auto item = static_cast<CacheItem*>(p->fts_pointer);
            item->group |= (getxattr(p->fts_path, kXattrCacheGroup, nullptr, 0) >= 0);
            item->tombstone |= (getxattr(p->fts_path, kXattrCacheTombstone, nullptr, 0) >= 0);

            // When group, immediately collect all files under tree
            if (item->group) {
                while ((p = fts_read(fts)) != nullptr) {
                    if (p->fts_info == FTS_DP && p->fts_level == item->level) break;
                    switch (p->fts_info) {
                    case FTS_D:
                    case FTS_DEFAULT:
                    case FTS_F:
                    case FTS_SL:
                    case FTS_SLNONE:
                        item->size += p->fts_statp->st_blocks * 512;
                        item->modified = std::max(item->modified, p->fts_statp->st_mtime);
                    }
                }
            }
        }
        }

        // Bubble up modified time to parent
        CHECK(p != nullptr);
        switch (p->fts_info) {
        case FTS_DP:
        case FTS_DEFAULT:
        case FTS_F:
        case FTS_SL:
        case FTS_SLNONE: {
            auto item = static_cast<CacheItem*>(p->fts_pointer);
            auto parent = static_cast<CacheItem*>(p->fts_parent->fts_pointer);
            if (parent) {
                parent->modified = std::max(parent->modified, item->modified);
            }
        }
        }
    }
    fts_close(fts);
}

void CacheTracker::loadItems() {
    items.clear();

    ATRACE_BEGIN("loadItems");
    for (const auto& path : mDataPaths) {
        loadItemsFrom(read_path_inode(path, "cache", kXattrInodeCache));
        loadItemsFrom(read_path_inode(path, "code_cache", kXattrInodeCodeCache));
    }
    ATRACE_END();

    ATRACE_BEGIN("sortItems");
    auto cmp = [](std::shared_ptr<CacheItem> left, std::shared_ptr<CacheItem> right) {
        // TODO: sort dotfiles last
        // TODO: sort code_cache last
        if (left->modified != right->modified) {
            return (left->modified > right->modified);
        }
        if (left->level != right->level) {
            return (left->level < right->level);
        }
        return left->directory;
    };
    std::stable_sort(items.begin(), items.end(), cmp);
    ATRACE_END();
}

void CacheTracker::ensureItems() {
    if (mItemsLoaded) {
        return;
    } else {
        loadItems();
        mItemsLoaded = true;
    }
}

int CacheTracker::getCacheRatio() {
    if (cacheQuota == 0) {
        return 0;
    } else {
        return (cacheUsed * 10000) / cacheQuota;
    }
}

}  // namespace installd
}  // namespace android
