/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 *
 */

#include "qpid/linearstore/journal/EmptyFilePoolPartition.h"

#include <iomanip>
#include "qpid/linearstore/journal/EmptyFilePool.h"
#include "qpid/linearstore/journal/jdir.h"
#include "qpid/linearstore/journal/JournalLog.h"
#include "qpid/linearstore/journal/slock.h"
#include <unistd.h>

namespace qpid {
namespace linearstore {
namespace journal {

// static
const std::string EmptyFilePoolPartition::s_efpTopLevelDir_("efp"); // Sets the top-level efp dir within a partition

EmptyFilePoolPartition::EmptyFilePoolPartition(const efpPartitionNumber_t partitionNum,
                                               const std::string& partitionDir,
                                               const bool overwriteBeforeReturnFlag,
                                               const bool truncateFlag,
                                               JournalLog& journalLogRef) :
                partitionNum_(partitionNum),
                partitionDir_(partitionDir),
                overwriteBeforeReturnFlag_(overwriteBeforeReturnFlag),
                truncateFlag_(truncateFlag),
                journalLogRef_(journalLogRef)
{
    validatePartitionDir();
}

EmptyFilePoolPartition::~EmptyFilePoolPartition() {
    slock l(efpMapMutex_);
    for (efpMapItr_t i = efpMap_.begin(); i != efpMap_.end(); ++i) {
        delete i->second;
    }
    efpMap_.clear();
}

void
EmptyFilePoolPartition::findEmptyFilePools() {
//std::cout << "*** EmptyFilePoolPartition::findEmptyFilePools(): Reading " << partitionDir_ << std::endl; // DEBUG
    std::string efpDir(partitionDir_ + "/" + s_efpTopLevelDir_);
    if (jdir::is_dir(efpDir)) {
        std::vector<std::string> dirList;
        jdir::read_dir(efpDir, dirList, true, false, false, true);
        for (std::vector<std::string>::iterator i = dirList.begin(); i != dirList.end(); ++i) {
            createEmptyFilePool(*i);
        }
    } else {
        std::ostringstream oss;
        oss << "Partition \"" << partitionDir_ << "\" does not contain top level EFP dir \"" << s_efpTopLevelDir_ << "\"";
        journalLogRef_.log(JournalLog::LOG_WARN, oss.str());
    }
}

EmptyFilePool* EmptyFilePoolPartition::getEmptyFilePool(const efpDataSize_kib_t efpDataSize_kib, const bool createIfNonExistent) {
    {
        slock l(efpMapMutex_);
        efpMapItr_t i = efpMap_.find(efpDataSize_kib);
        if (i != efpMap_.end())
            return i->second;
    }
    if (createIfNonExistent) {
        return createEmptyFilePool(efpDataSize_kib);
    }
    return 0;
}

void EmptyFilePoolPartition::getEmptyFilePools(std::vector<EmptyFilePool*>& efpList) {
    slock l(efpMapMutex_);
    for (efpMapItr_t i=efpMap_.begin(); i!=efpMap_.end(); ++i) {
        efpList.push_back(i->second);
    }
}

void EmptyFilePoolPartition::getEmptyFilePoolSizes_kib(std::vector<efpDataSize_kib_t>& efpDataSizesList_kib) const {
    slock l(efpMapMutex_);
    for (efpMapConstItr_t i=efpMap_.begin(); i!=efpMap_.end(); ++i) {
        efpDataSizesList_kib.push_back(i->first);
    }
}

std::string EmptyFilePoolPartition::getPartitionDirectory() const {
    return partitionDir_;
}

efpPartitionNumber_t EmptyFilePoolPartition::getPartitionNumber() const {
    return partitionNum_;
}

std::string EmptyFilePoolPartition::toString(const uint16_t indent) const {
    std::string indentStr(indent, ' ');
    std::stringstream oss;
    oss << "EFP Partition " <<  partitionNum_ << ":" << std::endl;
    oss << indentStr  << "EFP Partition Analysis (partition " << partitionNum_ << " at \"" << partitionDir_ << "\"):" << std::endl;
    if (efpMap_.empty()) {
        oss << indentStr << "<Partition empty, no EFPs found>" << std::endl;
    } else {
        oss << indentStr << std::setw(12) << "efp_size_kib"
                         << std::setw(12) << "num_files"
                         << std::setw(18) << "tot_capacity_kib" << std::endl;
        oss << indentStr << std::setw(12) << "------------"
                         << std::setw(12) << "----------"
                         << std::setw(18) << "----------------" << std::endl;
        {
            slock l(efpMapMutex_);
            for (efpMapConstItr_t i=efpMap_.begin(); i!= efpMap_.end(); ++i) {
                oss << indentStr << std::setw(12) << i->first
                                 << std::setw(12) << i->second->numEmptyFiles()
                                 << std::setw(18) << i->second->cumFileSize_kib() << std::endl;
            }
        }
    }
    return oss.str();
}

// static
std::string EmptyFilePoolPartition::getPartionDirectoryName(const efpPartitionNumber_t partitionNumber) {
    std::ostringstream oss;
    oss << "p" << std::setfill('0') << std::setw(3) << partitionNumber;
    return oss.str();
}

//static
efpPartitionNumber_t EmptyFilePoolPartition::getPartitionNumber(const std::string& name) {
    if (name.length() == 4 && name[0] == 'p' && ::isdigit(name[1]) && ::isdigit(name[2]) && ::isdigit(name[3])) {
        long pn = ::strtol(name.c_str() + 1, 0, 10);
        if (pn == 0 && errno) {
            return 0;
        } else {
            return (efpPartitionNumber_t)pn;
        }
    }
    return 0;
}

// --- protected functions ---

EmptyFilePool* EmptyFilePoolPartition::createEmptyFilePool(const efpDataSize_kib_t efpDataSize_kib) {
    std::string fqEfpDirectoryName(partitionDir_ + "/" + EmptyFilePoolPartition::s_efpTopLevelDir_ + "/" + EmptyFilePool::dirNameFromDataSize(efpDataSize_kib));
    return createEmptyFilePool(fqEfpDirectoryName);
}

EmptyFilePool* EmptyFilePoolPartition::createEmptyFilePool(const std::string fqEfpDirectoryName) {
    EmptyFilePool* efpp = 0;
    efpp = new EmptyFilePool(fqEfpDirectoryName, this, overwriteBeforeReturnFlag_, truncateFlag_, journalLogRef_);
    {
        slock l(efpMapMutex_);
        efpMap_[efpp->dataSize_kib()] = efpp;
    }
    if (efpp != 0) {
        efpp->initialize();
    }
    return efpp;
}

void EmptyFilePoolPartition::validatePartitionDir() {
    std::ostringstream ss;
    if (!jdir::is_dir(partitionDir_)) {
        ss << "Invalid partition directory: \'" << partitionDir_ << "\' is not a directory";
        throw jexception(jerrno::JERR_EFP_BADPARTITIONDIR, ss.str(), "EmptyFilePoolPartition", "validatePartitionDir");
    }

    // TODO: other validity checks here
}

}}}
