/*
 * 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/quota.h>
#include <sys/xattr.h>
#include <utils/Trace.h>

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

#include "utils.h"

using android::base::StringPrintf;

namespace android {
namespace installd {

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

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);
    int extCacheGid = multiuser_get_ext_cache_gid(mUserId, mAppId);
    if (!mQuotaDevice.empty() && cacheGid != -1 && extCacheGid != -1) {
        struct dqblk dq;
        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid,
                reinterpret_cast<char*>(&dq)) != 0) {
            if (errno != ESRCH) {
                PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
            }
            return false;
        } else {
            cacheUsed += dq.dqb_curspace;
        }

        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), extCacheGid,
                reinterpret_cast<char*>(&dq)) != 0) {
            if (errno != ESRCH) {
                PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
            }
            return false;
        } else {
            cacheUsed += dq.dqb_curspace;
        }
        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, NULL))) {
        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
