<commit_before>// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "attribute_writer_factory.h"
#include "emptysearchview.h"
#include "fast_access_doc_subdb.h"
#include "fast_access_document_retriever.h"
#include "document_subdb_initializer.h"
#include "reconfig_params.h"
#include "i_document_subdb_owner.h"
#include <vespa/searchcore/proton/attribute/attribute_collection_spec_factory.h>
#include <vespa/searchcore/proton/attribute/attribute_factory.h>
#include <vespa/searchcore/proton/attribute/attribute_manager_initializer.h>
#include <vespa/searchcore/proton/attribute/filter_attribute_manager.h>
#include <vespa/searchcore/proton/attribute/sequential_attributes_initializer.h>
#include <vespa/searchcore/proton/common/alloc_config.h>
#include <vespa/searchcore/proton/matching/sessionmanager.h>
#include <vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.h>
#include <vespa/searchcore/proton/reprocessing/reprocess_documents_task.h>
#include <vespa/searchlib/docstore/document_store_visitor_progress.h>
#include <vespa/log/log.h>
LOG_SETUP(".proton.server.fast_access_doc_subdb");

using proton::matching::SessionManager;
using search::AttributeGuard;
using search::AttributeVector;
using search::SerialNum;
using search::index::Schema;
using proton::initializer::InitializerTask;
using searchcorespi::IFlushTarget;

namespace proton {

namespace {

struct AttributeGuardComp
{
    vespalib::string name;

    AttributeGuardComp(const vespalib::string &n)
        : name(n)
    { }

    bool operator()(const AttributeGuard &rhs) const {
        return name == rhs->getName();
    };
};

proton::IAttributeManager::SP
extractAttributeManager(const FastAccessFeedView::SP &feedView)
{
    const IAttributeWriter::SP &writer = feedView->getAttributeWriter();
    return writer->getAttributeManager();
}

}

InitializerTask::SP
FastAccessDocSubDB::createAttributeManagerInitializer(const DocumentDBConfig &configSnapshot,
                                                      SerialNum configSerialNum,
                                                      InitializerTask::SP documentMetaStoreInitTask,
                                                      DocumentMetaStore::SP documentMetaStore,
                                                      std::shared_ptr<AttributeManager::SP> attrMgrResult) const
{
    AllocStrategy alloc_strategy = configSnapshot.get_alloc_config().make_alloc_strategy(_subDbType);
    IAttributeFactory::SP attrFactory = std::make_shared<AttributeFactory>();
    AttributeManager::SP baseAttrMgr =
            std::make_shared<AttributeManager>(_baseDir + "/attribute",
                                               getSubDbName(),
                                               configSnapshot.getTuneFileDocumentDBSP()->_attr,
                                               _fileHeaderContext,
                                               _writeService.attributeFieldWriter(),
                                               _writeService.shared(),
                                               attrFactory,
                                               _hwInfo);
    return std::make_shared<AttributeManagerInitializer>(configSerialNum,
                                                         documentMetaStoreInitTask,
                                                         documentMetaStore,
                                                         baseAttrMgr,
                                                         (_hasAttributes ? configSnapshot.getAttributesConfig() : AttributesConfig()),
                                                         alloc_strategy,
                                                         _fastAccessAttributesOnly,
                                                         _writeService.master(),
                                                         attrMgrResult);
}

void
FastAccessDocSubDB::setupAttributeManager(AttributeManager::SP attrMgrResult)
{
    if (_addMetrics) {
        // register attribute metrics
        std::vector<AttributeGuard> list;
        attrMgrResult->getAttributeListAll(list);
        for (const auto &attr : list) {
            const AttributeVector &v = *attr;
            _metricsWireService.addAttribute(_subAttributeMetrics, v.getName());
        }
    }
    _initAttrMgr = attrMgrResult;
}

AttributeCollectionSpec::UP
FastAccessDocSubDB::createAttributeSpec(const AttributesConfig &attrCfg, const AllocStrategy& alloc_strategy, SerialNum serialNum) const
{
    uint32_t docIdLimit(_dms->getCommittedDocIdLimit());
    AttributeCollectionSpecFactory factory(alloc_strategy, _fastAccessAttributesOnly);
    return factory.create(attrCfg, docIdLimit, serialNum);
}

void
FastAccessDocSubDB::initFeedView(IAttributeWriter::SP writer, const DocumentDBConfig &configSnapshot)
{
    // Called by executor thread
    auto feedView = std::make_shared<FastAccessFeedView>(
            getStoreOnlyFeedViewContext(configSnapshot),
            getFeedViewPersistentParams(),
            FastAccessFeedView::Context(std::move(writer), _docIdLimit));

    _fastAccessFeedView.set(feedView);
    _iFeedView.set(_fastAccessFeedView.get());
}

AttributeManager::SP
FastAccessDocSubDB::getAndResetInitAttributeManager()
{
    AttributeManager::SP retval = _initAttrMgr;
    _initAttrMgr.reset();
    return retval;
}

IFlushTarget::List
FastAccessDocSubDB::getFlushTargetsInternal()
{
    IFlushTarget::List retval(Parent::getFlushTargetsInternal());
    IFlushTarget::List tmp(getAttributeManager()->getFlushTargets());
    retval.insert(retval.end(), tmp.begin(), tmp.end());
    return retval;
}

void
FastAccessDocSubDB::pruneRemovedFields(SerialNum serialNum)
{
    getAttributeManager()->pruneRemovedFields(serialNum);
}

void
FastAccessDocSubDB::reconfigureAttributeMetrics(const proton::IAttributeManager &newMgr,
                                                const proton::IAttributeManager &oldMgr)
{
    std::set<vespalib::string> toAdd;
    std::set<vespalib::string> toRemove;
    std::vector<AttributeGuard> newList;
    std::vector<AttributeGuard> oldList;
    newMgr.getAttributeList(newList);
    oldMgr.getAttributeList(oldList);
    for (const auto &newAttr : newList) {
        if (std::find_if(oldList.begin(),
                         oldList.end(),
                         AttributeGuardComp(newAttr->getName())) ==
            oldList.end()) {
            toAdd.insert(newAttr->getName());
        }
    }
    for (const auto &oldAttr : oldList) {
        if (std::find_if(newList.begin(),
                         newList.end(),
                         AttributeGuardComp(oldAttr->getName())) ==
            newList.end()) {
            toRemove.insert(oldAttr->getName());
        }
    }
    for (const auto &attrName : toAdd) {
        LOG(debug, "reconfigureAttributeMetrics(): addAttribute='%s'", attrName.c_str());
        _metricsWireService.addAttribute(_subAttributeMetrics, attrName);
    }
    for (const auto &attrName : toRemove) {
        LOG(debug, "reconfigureAttributeMetrics(): removeAttribute='%s'", attrName.c_str());
        _metricsWireService.removeAttribute(_subAttributeMetrics, attrName);
    }
}

IReprocessingTask::UP
FastAccessDocSubDB::createReprocessingTask(IReprocessingInitializer &initializer,
                                           const std::shared_ptr<const document::DocumentTypeRepo> &docTypeRepo) const
{
    uint32_t docIdLimit = _metaStoreCtx->get().getCommittedDocIdLimit();
    assert(docIdLimit > 0);
    return std::make_unique<ReprocessDocumentsTask>(initializer, getSummaryManager(), docTypeRepo,
                                                    getSubDbName(), docIdLimit);
}

FastAccessDocSubDB::FastAccessDocSubDB(const Config &cfg, const Context &ctx)
    : Parent(cfg._storeOnlyCfg, ctx._storeOnlyCtx),
      _hasAttributes(cfg._hasAttributes),
      _fastAccessAttributesOnly(cfg._fastAccessAttributesOnly),
      _initAttrMgr(),
      _fastAccessFeedView(),
      _subAttributeMetrics(ctx._subAttributeMetrics),
      _addMetrics(cfg._addMetrics),
      _metricsWireService(ctx._metricsWireService),
      _docIdLimit(0)
{ }

FastAccessDocSubDB::~FastAccessDocSubDB() = default;

DocumentSubDbInitializer::UP
FastAccessDocSubDB::createInitializer(const DocumentDBConfig &configSnapshot, SerialNum configSerialNum,
                                      const IndexConfig &indexCfg) const
{
    auto result = Parent::createInitializer(configSnapshot, configSerialNum, indexCfg);
    auto attrMgrInitTask = createAttributeManagerInitializer(configSnapshot, configSerialNum,
                                                             result->getDocumentMetaStoreInitTask(),
                                                             result->result().documentMetaStore()->documentMetaStore(),
                                                             result->writableResult().writableAttributeManager());
    result->addDependency(attrMgrInitTask);
    return result;
}

void
FastAccessDocSubDB::setup(const DocumentSubDbInitializerResult &initResult)
{
    Parent::setup(initResult);
    setupAttributeManager(initResult.attributeManager());
    _docIdLimit.set(_dms->getCommittedDocIdLimit());
}

void
FastAccessDocSubDB::initViews(const DocumentDBConfig &configSnapshot,
                              const SessionManager::SP &sessionManager)
{
    // Called by executor thread
    (void) sessionManager;
    _iSearchView.set(std::make_shared<EmptySearchView>());
    auto writer = std::make_shared<AttributeWriter>(getAndResetInitAttributeManager());
    {
        std::lock_guard<std::mutex> guard(_configMutex);
        initFeedView(std::move(writer), configSnapshot);
    }
}

IReprocessingTask::List
FastAccessDocSubDB::applyConfig(const DocumentDBConfig &newConfigSnapshot, const DocumentDBConfig &oldConfigSnapshot,
                                SerialNum serialNum, const ReconfigParams &params, IDocumentDBReferenceResolver &resolver)
{
    (void) resolver;

    AllocStrategy alloc_strategy = newConfigSnapshot.get_alloc_config().make_alloc_strategy(_subDbType);
    reconfigure(newConfigSnapshot.getStoreConfig(), alloc_strategy);
    IReprocessingTask::List tasks;
    /*
     * If attribute manager should change then document retriever
     * might have to rewrite a different set of fields.  If document
     * type repo has changed then the new repo is needed to handle
     * documents using new fields, e.g. when moving documents from notready
     * to ready document sub db.
     */
    if (params.shouldAttributeManagerChange() ||
        params.shouldAttributeWriterChange() ||
        newConfigSnapshot.getDocumentTypeRepoSP().get() != oldConfigSnapshot.getDocumentTypeRepoSP().get()) {
        FastAccessDocSubDBConfigurer configurer(_fastAccessFeedView,
                std::make_unique<AttributeWriterFactory>(), getSubDbName());
        proton::IAttributeManager::SP oldMgr = extractAttributeManager(_fastAccessFeedView.get());
        AttributeCollectionSpec::UP attrSpec =
            createAttributeSpec(newConfigSnapshot.getAttributesConfig(), alloc_strategy, serialNum);
        IReprocessingInitializer::UP initializer =
                configurer.reconfigure(newConfigSnapshot, oldConfigSnapshot, *attrSpec);
        if (initializer->hasReprocessors()) {
            tasks.push_back(IReprocessingTask::SP(createReprocessingTask(*initializer,
                    newConfigSnapshot.getDocumentTypeRepoSP()).release()));
        }
        if (_addMetrics) {
            proton::IAttributeManager::SP newMgr = extractAttributeManager(_fastAccessFeedView.get());
            reconfigureAttributeMetrics(*newMgr, *oldMgr);
        }
        _iFeedView.set(_fastAccessFeedView.get());
        if (isNodeRetired()) {
            reconfigureAttributesConsideringNodeState();
        }
    }
    return tasks;
}

proton::IAttributeManager::SP
FastAccessDocSubDB::getAttributeManager() const
{
    return extractAttributeManager(_fastAccessFeedView.get());
}

IDocumentRetriever::UP
FastAccessDocSubDB::getDocumentRetriever()
{
    FastAccessFeedView::SP feedView = _fastAccessFeedView.get();
    proton::IAttributeManager::SP attrMgr = extractAttributeManager(feedView);
    return std::make_unique<FastAccessDocumentRetriever>(feedView, attrMgr);
}

void
FastAccessDocSubDB::onReplayDone()
{
    // Called by document db executor thread
    Parent::onReplayDone();
    // Normalize attribute vector sizes
    uint32_t docIdLimit = _metaStoreCtx->get().getCommittedDocIdLimit();
    assert(docIdLimit > 0);
    _docIdLimit.set(docIdLimit);
    IFeedView::SP feedView = _iFeedView.get();
    IAttributeWriter::SP attrWriter = static_cast<FastAccessFeedView &>(*feedView).getAttributeWriter();
    attrWriter->onReplayDone(docIdLimit);
}

void
FastAccessDocSubDB::onReprocessDone(SerialNum serialNum)
{
    IFeedView::SP feedView = _iFeedView.get();
    IAttributeWriter::SP attrWriter = static_cast<FastAccessFeedView &>(*feedView).getAttributeWriter();
    attrWriter->forceCommit(serialNum, std::shared_ptr<vespalib::IDestructorCallback>());
    _writeService.attributeFieldWriter().sync_all();
    _writeService.summary().sync();
    Parent::onReprocessDone(serialNum);
}

SerialNum
FastAccessDocSubDB::getOldestFlushedSerial()
{
    SerialNum lowest(Parent::getOldestFlushedSerial());
    proton::IAttributeManager::SP attrMgr(getAttributeManager());
    lowest = std::min(lowest, attrMgr->getOldestFlushedSerialNumber());
    return lowest;
}

SerialNum
FastAccessDocSubDB::getNewestFlushedSerial()
{
    SerialNum highest(Parent::getNewestFlushedSerial());
    proton::IAttributeManager::SP attrMgr(getAttributeManager());
    highest = std::max(highest, attrMgr->getNewestFlushedSerialNumber());
    return highest;
}

} // namespace proton
<commit_msg>Avoid sync_all<commit_after>// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "attribute_writer_factory.h"
#include "emptysearchview.h"
#include "fast_access_doc_subdb.h"
#include "fast_access_document_retriever.h"
#include "document_subdb_initializer.h"
#include "reconfig_params.h"
#include "i_document_subdb_owner.h"
#include <vespa/searchcore/proton/attribute/attribute_collection_spec_factory.h>
#include <vespa/searchcore/proton/attribute/attribute_factory.h>
#include <vespa/searchcore/proton/attribute/attribute_manager_initializer.h>
#include <vespa/searchcore/proton/attribute/filter_attribute_manager.h>
#include <vespa/searchcore/proton/attribute/sequential_attributes_initializer.h>
#include <vespa/searchcore/proton/common/alloc_config.h>
#include <vespa/searchcore/proton/matching/sessionmanager.h>
#include <vespa/searchcore/proton/reprocessing/attribute_reprocessing_initializer.h>
#include <vespa/searchcore/proton/reprocessing/reprocess_documents_task.h>
#include <vespa/searchlib/docstore/document_store_visitor_progress.h>
#include <vespa/vespalib/util/destructor_callbacks.h>

#include <vespa/log/log.h>
LOG_SETUP(".proton.server.fast_access_doc_subdb");

using proton::matching::SessionManager;
using search::AttributeGuard;
using search::AttributeVector;
using search::SerialNum;
using search::index::Schema;
using proton::initializer::InitializerTask;
using searchcorespi::IFlushTarget;

namespace proton {

namespace {

struct AttributeGuardComp
{
    vespalib::string name;

    AttributeGuardComp(const vespalib::string &n)
        : name(n)
    { }

    bool operator()(const AttributeGuard &rhs) const {
        return name == rhs->getName();
    };
};

proton::IAttributeManager::SP
extractAttributeManager(const FastAccessFeedView::SP &feedView)
{
    const IAttributeWriter::SP &writer = feedView->getAttributeWriter();
    return writer->getAttributeManager();
}

}

InitializerTask::SP
FastAccessDocSubDB::createAttributeManagerInitializer(const DocumentDBConfig &configSnapshot,
                                                      SerialNum configSerialNum,
                                                      InitializerTask::SP documentMetaStoreInitTask,
                                                      DocumentMetaStore::SP documentMetaStore,
                                                      std::shared_ptr<AttributeManager::SP> attrMgrResult) const
{
    AllocStrategy alloc_strategy = configSnapshot.get_alloc_config().make_alloc_strategy(_subDbType);
    IAttributeFactory::SP attrFactory = std::make_shared<AttributeFactory>();
    AttributeManager::SP baseAttrMgr =
            std::make_shared<AttributeManager>(_baseDir + "/attribute",
                                               getSubDbName(),
                                               configSnapshot.getTuneFileDocumentDBSP()->_attr,
                                               _fileHeaderContext,
                                               _writeService.attributeFieldWriter(),
                                               _writeService.shared(),
                                               attrFactory,
                                               _hwInfo);
    return std::make_shared<AttributeManagerInitializer>(configSerialNum,
                                                         documentMetaStoreInitTask,
                                                         documentMetaStore,
                                                         baseAttrMgr,
                                                         (_hasAttributes ? configSnapshot.getAttributesConfig() : AttributesConfig()),
                                                         alloc_strategy,
                                                         _fastAccessAttributesOnly,
                                                         _writeService.master(),
                                                         attrMgrResult);
}

void
FastAccessDocSubDB::setupAttributeManager(AttributeManager::SP attrMgrResult)
{
    if (_addMetrics) {
        // register attribute metrics
        std::vector<AttributeGuard> list;
        attrMgrResult->getAttributeListAll(list);
        for (const auto &attr : list) {
            const AttributeVector &v = *attr;
            _metricsWireService.addAttribute(_subAttributeMetrics, v.getName());
        }
    }
    _initAttrMgr = attrMgrResult;
}

AttributeCollectionSpec::UP
FastAccessDocSubDB::createAttributeSpec(const AttributesConfig &attrCfg, const AllocStrategy& alloc_strategy, SerialNum serialNum) const
{
    uint32_t docIdLimit(_dms->getCommittedDocIdLimit());
    AttributeCollectionSpecFactory factory(alloc_strategy, _fastAccessAttributesOnly);
    return factory.create(attrCfg, docIdLimit, serialNum);
}

void
FastAccessDocSubDB::initFeedView(IAttributeWriter::SP writer, const DocumentDBConfig &configSnapshot)
{
    // Called by executor thread
    auto feedView = std::make_shared<FastAccessFeedView>(
            getStoreOnlyFeedViewContext(configSnapshot),
            getFeedViewPersistentParams(),
            FastAccessFeedView::Context(std::move(writer), _docIdLimit));

    _fastAccessFeedView.set(feedView);
    _iFeedView.set(_fastAccessFeedView.get());
}

AttributeManager::SP
FastAccessDocSubDB::getAndResetInitAttributeManager()
{
    AttributeManager::SP retval = _initAttrMgr;
    _initAttrMgr.reset();
    return retval;
}

IFlushTarget::List
FastAccessDocSubDB::getFlushTargetsInternal()
{
    IFlushTarget::List retval(Parent::getFlushTargetsInternal());
    IFlushTarget::List tmp(getAttributeManager()->getFlushTargets());
    retval.insert(retval.end(), tmp.begin(), tmp.end());
    return retval;
}

void
FastAccessDocSubDB::pruneRemovedFields(SerialNum serialNum)
{
    getAttributeManager()->pruneRemovedFields(serialNum);
}

void
FastAccessDocSubDB::reconfigureAttributeMetrics(const proton::IAttributeManager &newMgr,
                                                const proton::IAttributeManager &oldMgr)
{
    std::set<vespalib::string> toAdd;
    std::set<vespalib::string> toRemove;
    std::vector<AttributeGuard> newList;
    std::vector<AttributeGuard> oldList;
    newMgr.getAttributeList(newList);
    oldMgr.getAttributeList(oldList);
    for (const auto &newAttr : newList) {
        if (std::find_if(oldList.begin(),
                         oldList.end(),
                         AttributeGuardComp(newAttr->getName())) ==
            oldList.end()) {
            toAdd.insert(newAttr->getName());
        }
    }
    for (const auto &oldAttr : oldList) {
        if (std::find_if(newList.begin(),
                         newList.end(),
                         AttributeGuardComp(oldAttr->getName())) ==
            newList.end()) {
            toRemove.insert(oldAttr->getName());
        }
    }
    for (const auto &attrName : toAdd) {
        LOG(debug, "reconfigureAttributeMetrics(): addAttribute='%s'", attrName.c_str());
        _metricsWireService.addAttribute(_subAttributeMetrics, attrName);
    }
    for (const auto &attrName : toRemove) {
        LOG(debug, "reconfigureAttributeMetrics(): removeAttribute='%s'", attrName.c_str());
        _metricsWireService.removeAttribute(_subAttributeMetrics, attrName);
    }
}

IReprocessingTask::UP
FastAccessDocSubDB::createReprocessingTask(IReprocessingInitializer &initializer,
                                           const std::shared_ptr<const document::DocumentTypeRepo> &docTypeRepo) const
{
    uint32_t docIdLimit = _metaStoreCtx->get().getCommittedDocIdLimit();
    assert(docIdLimit > 0);
    return std::make_unique<ReprocessDocumentsTask>(initializer, getSummaryManager(), docTypeRepo,
                                                    getSubDbName(), docIdLimit);
}

FastAccessDocSubDB::FastAccessDocSubDB(const Config &cfg, const Context &ctx)
    : Parent(cfg._storeOnlyCfg, ctx._storeOnlyCtx),
      _hasAttributes(cfg._hasAttributes),
      _fastAccessAttributesOnly(cfg._fastAccessAttributesOnly),
      _initAttrMgr(),
      _fastAccessFeedView(),
      _subAttributeMetrics(ctx._subAttributeMetrics),
      _addMetrics(cfg._addMetrics),
      _metricsWireService(ctx._metricsWireService),
      _docIdLimit(0)
{ }

FastAccessDocSubDB::~FastAccessDocSubDB() = default;

DocumentSubDbInitializer::UP
FastAccessDocSubDB::createInitializer(const DocumentDBConfig &configSnapshot, SerialNum configSerialNum,
                                      const IndexConfig &indexCfg) const
{
    auto result = Parent::createInitializer(configSnapshot, configSerialNum, indexCfg);
    auto attrMgrInitTask = createAttributeManagerInitializer(configSnapshot, configSerialNum,
                                                             result->getDocumentMetaStoreInitTask(),
                                                             result->result().documentMetaStore()->documentMetaStore(),
                                                             result->writableResult().writableAttributeManager());
    result->addDependency(attrMgrInitTask);
    return result;
}

void
FastAccessDocSubDB::setup(const DocumentSubDbInitializerResult &initResult)
{
    Parent::setup(initResult);
    setupAttributeManager(initResult.attributeManager());
    _docIdLimit.set(_dms->getCommittedDocIdLimit());
}

void
FastAccessDocSubDB::initViews(const DocumentDBConfig &configSnapshot,
                              const SessionManager::SP &sessionManager)
{
    // Called by executor thread
    (void) sessionManager;
    _iSearchView.set(std::make_shared<EmptySearchView>());
    auto writer = std::make_shared<AttributeWriter>(getAndResetInitAttributeManager());
    {
        std::lock_guard<std::mutex> guard(_configMutex);
        initFeedView(std::move(writer), configSnapshot);
    }
}

IReprocessingTask::List
FastAccessDocSubDB::applyConfig(const DocumentDBConfig &newConfigSnapshot, const DocumentDBConfig &oldConfigSnapshot,
                                SerialNum serialNum, const ReconfigParams &params, IDocumentDBReferenceResolver &resolver)
{
    (void) resolver;

    AllocStrategy alloc_strategy = newConfigSnapshot.get_alloc_config().make_alloc_strategy(_subDbType);
    reconfigure(newConfigSnapshot.getStoreConfig(), alloc_strategy);
    IReprocessingTask::List tasks;
    /*
     * If attribute manager should change then document retriever
     * might have to rewrite a different set of fields.  If document
     * type repo has changed then the new repo is needed to handle
     * documents using new fields, e.g. when moving documents from notready
     * to ready document sub db.
     */
    if (params.shouldAttributeManagerChange() ||
        params.shouldAttributeWriterChange() ||
        newConfigSnapshot.getDocumentTypeRepoSP().get() != oldConfigSnapshot.getDocumentTypeRepoSP().get()) {
        FastAccessDocSubDBConfigurer configurer(_fastAccessFeedView,
                std::make_unique<AttributeWriterFactory>(), getSubDbName());
        proton::IAttributeManager::SP oldMgr = extractAttributeManager(_fastAccessFeedView.get());
        AttributeCollectionSpec::UP attrSpec =
            createAttributeSpec(newConfigSnapshot.getAttributesConfig(), alloc_strategy, serialNum);
        IReprocessingInitializer::UP initializer =
                configurer.reconfigure(newConfigSnapshot, oldConfigSnapshot, *attrSpec);
        if (initializer->hasReprocessors()) {
            tasks.push_back(IReprocessingTask::SP(createReprocessingTask(*initializer,
                    newConfigSnapshot.getDocumentTypeRepoSP()).release()));
        }
        if (_addMetrics) {
            proton::IAttributeManager::SP newMgr = extractAttributeManager(_fastAccessFeedView.get());
            reconfigureAttributeMetrics(*newMgr, *oldMgr);
        }
        _iFeedView.set(_fastAccessFeedView.get());
        if (isNodeRetired()) {
            reconfigureAttributesConsideringNodeState();
        }
    }
    return tasks;
}

proton::IAttributeManager::SP
FastAccessDocSubDB::getAttributeManager() const
{
    return extractAttributeManager(_fastAccessFeedView.get());
}

IDocumentRetriever::UP
FastAccessDocSubDB::getDocumentRetriever()
{
    FastAccessFeedView::SP feedView = _fastAccessFeedView.get();
    proton::IAttributeManager::SP attrMgr = extractAttributeManager(feedView);
    return std::make_unique<FastAccessDocumentRetriever>(feedView, attrMgr);
}

void
FastAccessDocSubDB::onReplayDone()
{
    // Called by document db executor thread
    Parent::onReplayDone();
    // Normalize attribute vector sizes
    uint32_t docIdLimit = _metaStoreCtx->get().getCommittedDocIdLimit();
    assert(docIdLimit > 0);
    _docIdLimit.set(docIdLimit);
    IFeedView::SP feedView = _iFeedView.get();
    IAttributeWriter::SP attrWriter = static_cast<FastAccessFeedView &>(*feedView).getAttributeWriter();
    attrWriter->onReplayDone(docIdLimit);
}

void
FastAccessDocSubDB::onReprocessDone(SerialNum serialNum)
{
    IFeedView::SP feedView = _iFeedView.get();
    IAttributeWriter::SP attrWriter = static_cast<FastAccessFeedView &>(*feedView).getAttributeWriter();
    vespalib::Gate gate;
    {
        auto onDone = std::make_shared<vespalib::GateCallback>(gate);
        attrWriter->forceCommit(serialNum, onDone);
        _writeService.summary().execute(vespalib::makeLambdaTask([done = std::move(onDone)]() { (void) done; }));
    }
    gate.await();
    Parent::onReprocessDone(serialNum);
}

SerialNum
FastAccessDocSubDB::getOldestFlushedSerial()
{
    SerialNum lowest(Parent::getOldestFlushedSerial());
    proton::IAttributeManager::SP attrMgr(getAttributeManager());
    lowest = std::min(lowest, attrMgr->getOldestFlushedSerialNumber());
    return lowest;
}

SerialNum
FastAccessDocSubDB::getNewestFlushedSerial()
{
    SerialNum highest(Parent::getNewestFlushedSerial());
    proton::IAttributeManager::SP attrMgr(getAttributeManager());
    highest = std::max(highest, attrMgr->getNewestFlushedSerialNumber());
    return highest;
}

} // namespace proton
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2012.  All rights reserved
 */
#ifndef _Stroika_Foundation_Containers_Tally_Array_inl_
#define _Stroika_Foundation_Containers_Tally_Array_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

#include    "Private/Array.h"

#include    "../../Memory/BlockAllocated.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Containers {
            namespace   Concrete {

                using namespace Private;

                template    <typename T>
                class   Tally_Array<T>::Rep_ : public Tally<T>::_IRep {
                private:
                    typedef typename    Tally<T>::_IRep inherited;

                public:
                    Rep_ ();

                public:
                    DECLARE_USE_BLOCK_ALLOCATION (Rep_);

                    // Iterable<T>::_IRep overrides
                public:
#if     qCompilerAndStdLib_IllUnderstoodTemplateConfusionOverTBug
                    virtual typename Iterable<TallyEntry<T>>::_SharedPtrIRep    Clone () const override {
                        return typename Iterable<TallyEntry<T>>::_SharedPtrIRep (new Rep_ (*this));
                    }
#else
                    virtual typename Iterable<TallyEntry<T>>::_SharedPtrIRep    Clone () const override;
#endif // qCompilerAndStdLib_IllUnderstoodTemplateConfusionOverTBug

                    virtual size_t                                              GetLength () const override;
                    virtual bool                                                IsEmpty () const override;
                    virtual Iterator<TallyEntry<T>>                             MakeIterator () const override;
                    virtual void                                                Apply (typename Rep_::_APPLY_ARGTYPE doToElement) const override;
                    virtual Iterator<TallyEntry<T>>                             ApplyUntilTrue (typename Rep_::_APPLYUNTIL_ARGTYPE doToElement) const override;

                    // Tally<T>::_IRep overrides
                public:
                    virtual bool                                    Contains (T item) const override;
                    virtual void                                    Compact () override;
                    virtual void                                    RemoveAll () override;
                    virtual void                                    Add (T item, size_t count) override;
                    virtual void                                    Remove (T item, size_t count) override;
                    virtual size_t                                  TallyOf (T item) const override;
                    virtual shared_ptr<typename Iterator<T>::IRep>  MakeBagIterator () const override;
                    virtual typename Tally<T>::TallyMutator         MakeTallyMutator () override;

                private:
                    nonvirtual  void    RemoveAt_ (size_t index);

                private:
                    Array_Patch<TallyEntry<T>> fData_;

                    DEFINE_CONSTEXPR_CONSTANT(size_t, kNotFound_, (size_t) - 1);

                    nonvirtual  size_t  Find_ (TallyEntry<T>& item) const;

                    friend  class Tally_Array<T>::MutatorRep_;
                };

                template    <typename T>
                class  Tally_Array<T>::MutatorRep_ : public Tally<T>::TallyMutator::IRep {
                private:
                    typedef     typename Tally<T>::TallyMutator::IRep  inherited;

                public:
                    MutatorRep_ (typename Tally_Array<T>::Rep_& owner);

                public:
                    DECLARE_USE_BLOCK_ALLOCATION (MutatorRep_);

                public:
                    virtual bool            More (TallyEntry<T>* current, bool advance) override;
                    virtual bool            StrongEquals (const typename Iterator<TallyEntry<T> >::IRep* rhs) const override;
                    virtual shared_ptr<typename Iterator<TallyEntry<T> >::IRep> Clone () const override;

                public:
                    virtual void    RemoveCurrent () override;
                    virtual void    UpdateCount (size_t newCount) override;

                private:
                    ForwardArrayMutator_Patch<TallyEntry<T> >   fIterator;
                    friend  class   Tally_Array<T>::Rep_;
                };

                /*
                 ********************************************************************************
                 *************************** Tally_Array<T>::MutatorRep_ ************************
                 ********************************************************************************
                 */
                template    <class  T>
                Tally_Array<T>::MutatorRep_::MutatorRep_ (typename Tally_Array<T>::Rep_& owner)
                    : inherited ()
                    , fIterator (owner.fData_)
                {
                }
                template    <class  T>
                bool    Tally_Array<T>::MutatorRep_::More (TallyEntry<T>* current, bool advance)
                {
                    return (fIterator.More (current, advance));
                }
                template    <typename T>
                bool    Tally_Array<T>::MutatorRep_::StrongEquals (const typename Iterator<TallyEntry<T> >::IRep* rhs) const
                {
                    AssertNotImplemented ();
                    return false;
                }
                template    <typename T>
                shared_ptr<typename Iterator<TallyEntry<T> >::IRep> Tally_Array<T>::MutatorRep_::Clone () const
                {
                    return shared_ptr<typename Iterator<TallyEntry<T> >::IRep> (new MutatorRep_ (*this));
                }
                template    <typename T>
                void    Tally_Array<T>::MutatorRep_::RemoveCurrent ()
                {
                    fIterator.RemoveCurrent ();
                }
                template    <typename T>
                void    Tally_Array<T>::MutatorRep_::UpdateCount (size_t newCount)
                {
                    if (newCount == 0) {
                        fIterator.RemoveCurrent ();
                    }
                    else {
                        TallyEntry<T>   c   =   fIterator.Current ();
                        c.fCount = newCount;
                        fIterator.UpdateCurrent (c);
                    }
                }

                /*
                 ********************************************************************************
                 *************************** Tally_Array<T>::Rep_ *******************************
                 ********************************************************************************
                 */
                template    <typename T>
                inline  Tally_Array<T>::Rep_::Rep_ ()
                    : inherited ()
                    , fData_ ()
                {
                }
                template    <typename T>
                size_t  Tally_Array<T>::Rep_::GetLength () const
                {
                    return (fData_.GetLength ());
                }
                template    <typename T>
                bool  Tally_Array<T>::Rep_::IsEmpty () const
                {
                    return (fData_.GetLength () == 0);
                }
                template    <typename T>
                Iterator<TallyEntry<T>> Tally_Array<T>::Rep_::MakeIterator () const
                {
                    // const cast cuz this mutator won't really be used to change anything - except stuff like
                    // link list of owned iterators
                    Iterator<TallyEntry<T>> tmp = Iterator<TallyEntry<T>> (typename Iterator<TallyEntry<T>>::SharedByValueRepType (shared_ptr<typename Iterator<TallyEntry<T>>::IRep> (new MutatorRep_ (*const_cast<Rep_*> (this)))));
                    tmp++;  //tmphack - redo iterator impl itself
                    return tmp;
                }
                template    <typename T>
                void      Tally_Array<T>::Rep_::Apply (typename Rep_::_APPLY_ARGTYPE doToElement) const
                {
                    return _Apply (doToElement);
                }
                template    <typename T>
                Iterator<TallyEntry<T>>     Tally_Array<T>::Rep_::ApplyUntilTrue (typename Rep_::_APPLYUNTIL_ARGTYPE doToElement) const
                {
                    return _ApplyUntilTrue (doToElement);
                }
                template    <typename T>
                bool    Tally_Array<T>::Rep_::Contains (T item) const
                {
                    TallyEntry<T> tmp (item);
                    return (bool (Find_ (tmp) != kNotFound_));
                }
                template    <typename T>
                void    Tally_Array<T>::Rep_::Compact ()
                {
                    fData_.Compact ();
                }
#if     !qCompilerAndStdLib_IllUnderstoodTemplateConfusionOverTBug
                template    <typename T>
                typename Iterable<TallyEntry<T>>::_SharedPtrIRep    Tally_Array<T>::Rep_::Clone () const
                {
                    return typename Iterable<TallyEntry<T>>::_SharedPtrIRep (new Rep_ (*this));
                }
#endif
                template    <typename T>
                void    Tally_Array<T>::Rep_::Add (T item, size_t count)
                {
                    TallyEntry<T> tmp (item, count);
                    size_t index = Find_ (tmp);
                    if (index == kNotFound_) {
                        fData_.InsertAt (tmp, GetLength ());
                    }
                    else {
                        tmp.fCount += count;
                        fData_.SetAt (tmp, index);
                    }
                }
                template    <typename T>
                void    Tally_Array<T>::Rep_::Remove (T item, size_t count)
                {
                    TallyEntry<T> tmp (item);
                    size_t index = Find_ (tmp);
                    if (index != kNotFound_) {
                        Assert (index < GetLength ());
                        Assert (tmp.fCount >= count);
                        tmp.fCount -= count;
                        if (tmp.fCount == 0) {
                            RemoveAt_ (index);
                        }
                        else {
                            fData_.SetAt (tmp, index);
                        }
                    }
                }
                template    <typename T>
                void    Tally_Array<T>::Rep_::RemoveAll ()
                {
                    fData_.RemoveAll ();
                }
                template    <typename T>
                size_t  Tally_Array<T>::Rep_::TallyOf (T item) const
                {
                    TallyEntry<T> tmp (item);
                    size_t index = Find_ (tmp);
                    Require (index >= 0);
                    Require (index < GetLength ());
                    return (tmp.fCount);
                }
                template    <typename T>
                shared_ptr<typename Iterator<T>::IRep>    Tally_Array<T>::Rep_::MakeBagIterator () const
                {
                    return shared_ptr<typename Iterator<T>::IRep> (new typename Tally_Array<T>::_TallyEntryToItemIterator (MakeIterator ()));
                }
                template    <typename T>
                typename Tally<T>::TallyMutator   Tally_Array<T>::Rep_::MakeTallyMutator ()
                {
                    return TallyMutator (new MutatorRep_ (*this));
                }
                template    <typename T>
                void    Tally_Array<T>::Rep_::RemoveAt_ (size_t index)
                {
                    fData_.RemoveAt (index);
                }
                template    <typename T>
                size_t  Tally_Array<T>::Rep_::Find_ (TallyEntry<T>& item) const
                {
                    size_t length = fData_.GetLength ();
                    for (size_t i = 0; i < length; i++) {
                        if (fData_.GetAt (i).fItem == item.fItem) {
                            item = fData_.GetAt (i);
                            return (i);
                        }
                    }
                    return kNotFound_;
                }

                /*
                 ********************************************************************************
                 ********************************* Tally_Array<T> *******************************
                 ********************************************************************************
                 */
                template    <typename T>
                Tally_Array<T>::Tally_Array ()
                    : Tally<T> (new Rep_ ())
                {
                }
                template    <typename T>    Tally_Array<T>::Tally_Array (const T* start, const T* end)
                    : Tally<T> (new Rep_ ())
                {
                    SetCapacity (size);
                    AddItems (start, end);
                }
                template    <typename T>
                inline  Tally_Array<T>::Tally_Array (const Tally_Array<T>& src) :
                    Tally<T> (src)
                {
                }
                template    <typename T>
                Tally_Array<T>::Tally_Array (const Tally<T>& src) :
                    Tally<T> (new Rep_ ())
                {
                    SetCapacity (src.GetLength ());
                    operator+= (src);
                }
                template    <typename T>
                inline  Tally_Array<T>& Tally_Array<T>::operator= (const Tally_Array<T>& src)
                {
                    Tally<T>::operator= (src);
                    return (*this);
                }
                template    <typename T>
                inline  const typename Tally_Array<T>::Rep_&    Tally_Array<T>::GetRep_ () const
                {
                    return reinterpret_cast<const Tally_Array<T>::Rep_&> (this->_GetRep ());
                }
                template    <typename T>
                inline  typename Tally_Array<T>::Rep_&  Tally_Array<T>::GetRep_ ()
                {
                    return reinterpret_cast<Tally_Array<T>::Rep_&> (this->_GetRep ());
                }
                template    <typename T>
                size_t  Tally_Array<T>::GetCapacity () const
                {
                    return (this->GetRep ().fData_.GetCapacity ());
                }
                template    <typename T>
                void    Tally_Array<T>::SetCapacity (size_t slotsAlloced)
                {
                    this->GetRep ().fData_.SetCapacity (slotsAlloced);
                }

            }
        }
    }
}

#endif  /* _Stroika_Foundation_Containers_Tally_Array_inl_ */

<commit_msg>fixed call to Tally_Array CTOR - no more AddItems - just Add()<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2012.  All rights reserved
 */
#ifndef _Stroika_Foundation_Containers_Tally_Array_inl_
#define _Stroika_Foundation_Containers_Tally_Array_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

#include    "Private/Array.h"

#include    "../../Memory/BlockAllocated.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Containers {
            namespace   Concrete {

                using namespace Private;

                template    <typename T>
                class   Tally_Array<T>::Rep_ : public Tally<T>::_IRep {
                private:
                    typedef typename    Tally<T>::_IRep inherited;

                public:
                    Rep_ ();

                public:
                    DECLARE_USE_BLOCK_ALLOCATION (Rep_);

                    // Iterable<T>::_IRep overrides
                public:
#if     qCompilerAndStdLib_IllUnderstoodTemplateConfusionOverTBug
                    virtual typename Iterable<TallyEntry<T>>::_SharedPtrIRep    Clone () const override {
                        return typename Iterable<TallyEntry<T>>::_SharedPtrIRep (new Rep_ (*this));
                    }
#else
                    virtual typename Iterable<TallyEntry<T>>::_SharedPtrIRep    Clone () const override;
#endif // qCompilerAndStdLib_IllUnderstoodTemplateConfusionOverTBug

                    virtual size_t                                              GetLength () const override;
                    virtual bool                                                IsEmpty () const override;
                    virtual Iterator<TallyEntry<T>>                             MakeIterator () const override;
                    virtual void                                                Apply (typename Rep_::_APPLY_ARGTYPE doToElement) const override;
                    virtual Iterator<TallyEntry<T>>                             ApplyUntilTrue (typename Rep_::_APPLYUNTIL_ARGTYPE doToElement) const override;

                    // Tally<T>::_IRep overrides
                public:
                    virtual bool                                    Contains (T item) const override;
                    virtual void                                    Compact () override;
                    virtual void                                    RemoveAll () override;
                    virtual void                                    Add (T item, size_t count) override;
                    virtual void                                    Remove (T item, size_t count) override;
                    virtual size_t                                  TallyOf (T item) const override;
                    virtual shared_ptr<typename Iterator<T>::IRep>  MakeBagIterator () const override;
                    virtual typename Tally<T>::TallyMutator         MakeTallyMutator () override;

                private:
                    nonvirtual  void    RemoveAt_ (size_t index);

                private:
                    Array_Patch<TallyEntry<T>> fData_;

                    DEFINE_CONSTEXPR_CONSTANT(size_t, kNotFound_, (size_t) - 1);

                    nonvirtual  size_t  Find_ (TallyEntry<T>& item) const;

                    friend  class Tally_Array<T>::MutatorRep_;
                };

                template    <typename T>
                class  Tally_Array<T>::MutatorRep_ : public Tally<T>::TallyMutator::IRep {
                private:
                    typedef     typename Tally<T>::TallyMutator::IRep  inherited;

                public:
                    MutatorRep_ (typename Tally_Array<T>::Rep_& owner);

                public:
                    DECLARE_USE_BLOCK_ALLOCATION (MutatorRep_);

                public:
                    virtual bool            More (TallyEntry<T>* current, bool advance) override;
                    virtual bool            StrongEquals (const typename Iterator<TallyEntry<T> >::IRep* rhs) const override;
                    virtual shared_ptr<typename Iterator<TallyEntry<T> >::IRep> Clone () const override;

                public:
                    virtual void    RemoveCurrent () override;
                    virtual void    UpdateCount (size_t newCount) override;

                private:
                    ForwardArrayMutator_Patch<TallyEntry<T> >   fIterator;
                    friend  class   Tally_Array<T>::Rep_;
                };

                /*
                 ********************************************************************************
                 *************************** Tally_Array<T>::MutatorRep_ ************************
                 ********************************************************************************
                 */
                template    <class  T>
                Tally_Array<T>::MutatorRep_::MutatorRep_ (typename Tally_Array<T>::Rep_& owner)
                    : inherited ()
                    , fIterator (owner.fData_)
                {
                }
                template    <class  T>
                bool    Tally_Array<T>::MutatorRep_::More (TallyEntry<T>* current, bool advance)
                {
                    return (fIterator.More (current, advance));
                }
                template    <typename T>
                bool    Tally_Array<T>::MutatorRep_::StrongEquals (const typename Iterator<TallyEntry<T> >::IRep* rhs) const
                {
                    AssertNotImplemented ();
                    return false;
                }
                template    <typename T>
                shared_ptr<typename Iterator<TallyEntry<T> >::IRep> Tally_Array<T>::MutatorRep_::Clone () const
                {
                    return shared_ptr<typename Iterator<TallyEntry<T> >::IRep> (new MutatorRep_ (*this));
                }
                template    <typename T>
                void    Tally_Array<T>::MutatorRep_::RemoveCurrent ()
                {
                    fIterator.RemoveCurrent ();
                }
                template    <typename T>
                void    Tally_Array<T>::MutatorRep_::UpdateCount (size_t newCount)
                {
                    if (newCount == 0) {
                        fIterator.RemoveCurrent ();
                    }
                    else {
                        TallyEntry<T>   c   =   fIterator.Current ();
                        c.fCount = newCount;
                        fIterator.UpdateCurrent (c);
                    }
                }

                /*
                 ********************************************************************************
                 *************************** Tally_Array<T>::Rep_ *******************************
                 ********************************************************************************
                 */
                template    <typename T>
                inline  Tally_Array<T>::Rep_::Rep_ ()
                    : inherited ()
                    , fData_ ()
                {
                }
                template    <typename T>
                size_t  Tally_Array<T>::Rep_::GetLength () const
                {
                    return (fData_.GetLength ());
                }
                template    <typename T>
                bool  Tally_Array<T>::Rep_::IsEmpty () const
                {
                    return (fData_.GetLength () == 0);
                }
                template    <typename T>
                Iterator<TallyEntry<T>> Tally_Array<T>::Rep_::MakeIterator () const
                {
                    // const cast cuz this mutator won't really be used to change anything - except stuff like
                    // link list of owned iterators
                    Iterator<TallyEntry<T>> tmp = Iterator<TallyEntry<T>> (typename Iterator<TallyEntry<T>>::SharedByValueRepType (shared_ptr<typename Iterator<TallyEntry<T>>::IRep> (new MutatorRep_ (*const_cast<Rep_*> (this)))));
                    tmp++;  //tmphack - redo iterator impl itself
                    return tmp;
                }
                template    <typename T>
                void      Tally_Array<T>::Rep_::Apply (typename Rep_::_APPLY_ARGTYPE doToElement) const
                {
                    return _Apply (doToElement);
                }
                template    <typename T>
                Iterator<TallyEntry<T>>     Tally_Array<T>::Rep_::ApplyUntilTrue (typename Rep_::_APPLYUNTIL_ARGTYPE doToElement) const
                {
                    return _ApplyUntilTrue (doToElement);
                }
                template    <typename T>
                bool    Tally_Array<T>::Rep_::Contains (T item) const
                {
                    TallyEntry<T> tmp (item);
                    return (bool (Find_ (tmp) != kNotFound_));
                }
                template    <typename T>
                void    Tally_Array<T>::Rep_::Compact ()
                {
                    fData_.Compact ();
                }
#if     !qCompilerAndStdLib_IllUnderstoodTemplateConfusionOverTBug
                template    <typename T>
                typename Iterable<TallyEntry<T>>::_SharedPtrIRep    Tally_Array<T>::Rep_::Clone () const
                {
                    return typename Iterable<TallyEntry<T>>::_SharedPtrIRep (new Rep_ (*this));
                }
#endif
                template    <typename T>
                void    Tally_Array<T>::Rep_::Add (T item, size_t count)
                {
                    TallyEntry<T> tmp (item, count);
                    size_t index = Find_ (tmp);
                    if (index == kNotFound_) {
                        fData_.InsertAt (tmp, GetLength ());
                    }
                    else {
                        tmp.fCount += count;
                        fData_.SetAt (tmp, index);
                    }
                }
                template    <typename T>
                void    Tally_Array<T>::Rep_::Remove (T item, size_t count)
                {
                    TallyEntry<T> tmp (item);
                    size_t index = Find_ (tmp);
                    if (index != kNotFound_) {
                        Assert (index < GetLength ());
                        Assert (tmp.fCount >= count);
                        tmp.fCount -= count;
                        if (tmp.fCount == 0) {
                            RemoveAt_ (index);
                        }
                        else {
                            fData_.SetAt (tmp, index);
                        }
                    }
                }
                template    <typename T>
                void    Tally_Array<T>::Rep_::RemoveAll ()
                {
                    fData_.RemoveAll ();
                }
                template    <typename T>
                size_t  Tally_Array<T>::Rep_::TallyOf (T item) const
                {
                    TallyEntry<T> tmp (item);
                    size_t index = Find_ (tmp);
                    Require (index >= 0);
                    Require (index < GetLength ());
                    return (tmp.fCount);
                }
                template    <typename T>
                shared_ptr<typename Iterator<T>::IRep>    Tally_Array<T>::Rep_::MakeBagIterator () const
                {
                    return shared_ptr<typename Iterator<T>::IRep> (new typename Tally_Array<T>::_TallyEntryToItemIterator (MakeIterator ()));
                }
                template    <typename T>
                typename Tally<T>::TallyMutator   Tally_Array<T>::Rep_::MakeTallyMutator ()
                {
                    return TallyMutator (new MutatorRep_ (*this));
                }
                template    <typename T>
                void    Tally_Array<T>::Rep_::RemoveAt_ (size_t index)
                {
                    fData_.RemoveAt (index);
                }
                template    <typename T>
                size_t  Tally_Array<T>::Rep_::Find_ (TallyEntry<T>& item) const
                {
                    size_t length = fData_.GetLength ();
                    for (size_t i = 0; i < length; i++) {
                        if (fData_.GetAt (i).fItem == item.fItem) {
                            item = fData_.GetAt (i);
                            return (i);
                        }
                    }
                    return kNotFound_;
                }

                /*
                 ********************************************************************************
                 ********************************* Tally_Array<T> *******************************
                 ********************************************************************************
                 */
                template    <typename T>
                Tally_Array<T>::Tally_Array ()
                    : Tally<T> (new Rep_ ())
                {
                }
                template    <typename T>    Tally_Array<T>::Tally_Array (const T* start, const T* end)
                    : Tally<T> (new Rep_ ())
                {
                    SetCapacity (size);
                    Add (start, end);
                }
                template    <typename T>
                inline  Tally_Array<T>::Tally_Array (const Tally_Array<T>& src) :
                    Tally<T> (src)
                {
                }
                template    <typename T>
                Tally_Array<T>::Tally_Array (const Tally<T>& src) :
                    Tally<T> (new Rep_ ())
                {
                    SetCapacity (src.GetLength ());
                    operator+= (src);
                }
                template    <typename T>
                inline  Tally_Array<T>& Tally_Array<T>::operator= (const Tally_Array<T>& src)
                {
                    Tally<T>::operator= (src);
                    return (*this);
                }
                template    <typename T>
                inline  const typename Tally_Array<T>::Rep_&    Tally_Array<T>::GetRep_ () const
                {
                    return reinterpret_cast<const Tally_Array<T>::Rep_&> (this->_GetRep ());
                }
                template    <typename T>
                inline  typename Tally_Array<T>::Rep_&  Tally_Array<T>::GetRep_ ()
                {
                    return reinterpret_cast<Tally_Array<T>::Rep_&> (this->_GetRep ());
                }
                template    <typename T>
                size_t  Tally_Array<T>::GetCapacity () const
                {
                    return (this->GetRep ().fData_.GetCapacity ());
                }
                template    <typename T>
                void    Tally_Array<T>::SetCapacity (size_t slotsAlloced)
                {
                    this->GetRep ().fData_.SetCapacity (slotsAlloced);
                }

            }
        }
    }
}

#endif  /* _Stroika_Foundation_Containers_Tally_Array_inl_ */

<|endoftext|>


<commit_before>// Copyright Microsoft Corporation
// Copyright Oberon microsystems, Inc
// Copyright GHI Electronics, LLC
//
// 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.

#include "STM32F4.h"
#include <stdio.h>

#define TOTAL_DEPLOYMENT_CONTROLLERS 1

#ifndef STM32F4_FLASH
#define STM32F4_FLASH               ((FLASH_TypeDef *) FLASH_R_BASE)
#endif

struct DeploymentSector {
    uint32_t id;
    uint32_t address;
    uint32_t size;
};

#if STM32F4_SUPPLY_VOLTAGE_MV < 2100
#error 16 bit Flash programming not allowed for voltages below 2.1V
#endif
#if STM32F4_AHB_CLOCK_HZ < 1000000
#error Flash programming not allowed for HCLK below 1MHz
#endif

TinyCLR_Result STM32F4_Flash_GetSectorSizeForAddress(const TinyCLR_Storage_Controller* self, uint32_t address, int32_t& size);

static const DeploymentSector deploymentSectors[] = DEPLOYMENT_SECTORS;
static uint64_t deploymentSectorAddress[SIZEOF_ARRAY(deploymentSectors)];
static size_t deploymentSectorSize[SIZEOF_ARRAY(deploymentSectors)];

static const uint32_t STM32F4_FLASH_KEY1 = 0x45670123;
static const uint32_t STM32F4_FLASH_KEY2 = 0xcdef89ab;

static TinyCLR_Storage_Controller deploymentControllers[TOTAL_DEPLOYMENT_CONTROLLERS];
static TinyCLR_Api_Info deploymentApi[TOTAL_DEPLOYMENT_CONTROLLERS];
static TinyCLR_Storage_Descriptor deploymentDescriptor;
TinyCLR_Startup_DeploymentConfiguration deploymentConfiguration;

const TinyCLR_Api_Info* STM32F4_Deployment_GetApi() {
    for (int32_t i = 0; i < TOTAL_DEPLOYMENT_CONTROLLERS; i++) {
        deploymentControllers[i].ApiInfo = &deploymentApi[i];
        deploymentControllers[i].Acquire = &STM32F4_Flash_Acquire;
        deploymentControllers[i].Release = &STM32F4_Flash_Release;
        deploymentControllers[i].Open = &STM32F4_Flash_Open;
        deploymentControllers[i].Close = &STM32F4_Flash_Close;
        deploymentControllers[i].Read = &STM32F4_Flash_Read;
        deploymentControllers[i].Write = &STM32F4_Flash_Write;
        deploymentControllers[i].Erase = &STM32F4_Flash_Erase;
        deploymentControllers[i].IsErased = &STM32F4_Flash_IsErased;
        deploymentControllers[i].GetDescriptor = &STM32F4_Flash_GetDescriptor;
        deploymentControllers[i].IsPresent = &STM32F4_Flash_IsPresent;
        deploymentControllers[i].SetPresenceChangedHandler = &STM32F4_Flash_SetPresenceChangedHandler;

        deploymentApi[i].Author = "GHI Electronics, LLC";
        deploymentApi[i].Name = "GHIElectronics.TinyCLR.NativeApis.STM32F4.StorageController";
        deploymentApi[i].Type = TinyCLR_Api_Type::StorageController;
        deploymentApi[i].Version = 0;
        deploymentApi[i].Implementation = &deploymentControllers[i];
        deploymentApi[i].State = nullptr;
    }

    STM32F4_Deplpoyment_Reset();

    return (const TinyCLR_Api_Info*)&deploymentApi;
}

TinyCLR_Result __section("SectionForFlashOperations") STM32F4_Flash_Read(const TinyCLR_Storage_Controller* self, uint64_t address, size_t& count, uint8_t* data, uint64_t timeout) {
    int32_t bytePerSector = 0;

    if (data == nullptr) return TinyCLR_Result::ArgumentNull;
    if (STM32F4_Flash_GetSectorSizeForAddress(self, address, bytePerSector) != TinyCLR_Result::Success)
        return TinyCLR_Result::IndexOutOfRange;

    uint32_t* addressStart = reinterpret_cast<uint32_t*>(address);
    uint32_t* addressEnd = reinterpret_cast<uint32_t*>(address + count);
    uint32_t* pBuf = (uint32_t*)data;

    while (addressStart < addressEnd) {
        *pBuf++ = *addressStart++;
    }

    return TinyCLR_Result::Success;
}

TinyCLR_Result __section("SectionForFlashOperations") STM32F4_Flash_Write(const TinyCLR_Storage_Controller* self, uint64_t address, size_t& count, const uint8_t* data, uint64_t timeout) {
    int32_t bytePerSector = 0;

    if (data == nullptr) return TinyCLR_Result::ArgumentNull;
    if (STM32F4_Flash_GetSectorSizeForAddress(self, address, bytePerSector) != TinyCLR_Result::Success)
        return TinyCLR_Result::IndexOutOfRange;

    if (STM32F4_FLASH->CR & FLASH_CR_LOCK) { // unlock
        STM32F4_FLASH->KEYR = STM32F4_FLASH_KEY1;
        STM32F4_FLASH->KEYR = STM32F4_FLASH_KEY2;
    }

    uint32_t* addressStart = reinterpret_cast<uint32_t*>(address);
    uint32_t* addressEnd = reinterpret_cast<uint32_t*>(address + count);
    uint32_t* pBuf = (uint32_t*)data;

    // enable programming
    STM32F4_FLASH->CR = FLASH_CR_PG | FLASH_CR_PSIZE_1;

    while (addressStart < addressEnd) {
        if (*addressStart != *pBuf) {
            // write data
            *addressStart = *pBuf;
            // wait for completion
            while (STM32F4_FLASH->SR & FLASH_SR_BSY);
            // check
            if (*addressStart != *pBuf) {
                return TinyCLR_Result::InvalidOperation;
            }
        }
        addressStart++;
        pBuf++;
    }

    // reset & lock the controller
    STM32F4_FLASH->CR = FLASH_CR_LOCK;

    return TinyCLR_Result::Success;
}

TinyCLR_Result __section("SectionForFlashOperations") STM32F4_Flash_IsErased(const TinyCLR_Storage_Controller* self, uint64_t address, size_t& count, bool& erased) {
    auto sector = address; //address is sector. Use sector for clear

    if (sector >= SIZEOF_ARRAY(deploymentSectors)) return TinyCLR_Result::IndexOutOfRange;

    uint32_t* addressStart = reinterpret_cast<uint32_t*>(deploymentSectors[sector].address);
    uint32_t* addressEnd = reinterpret_cast<uint32_t*>(deploymentSectors[sector].address + deploymentSectors[sector].size);

    erased = true;

    while (addressStart < addressEnd) {
        if (*addressStart != 0xFFFFFFFF) {
            erased = false;

            break;
        }

        addressStart++;
    }

    return TinyCLR_Result::Success;
}

TinyCLR_Result __section("SectionForFlashOperations") STM32F4_Flash_Erase(const TinyCLR_Storage_Controller* self, uint64_t address, size_t& count, uint64_t timeout) {
    auto sector = address; //address is sector. Use sector for clear

    if (sector >= SIZEOF_ARRAY(deploymentSectors)) return TinyCLR_Result::IndexOutOfRange;

    uint32_t num = deploymentSectors[sector].id;

    if (num > 11) num += 4;

    if (STM32F4_FLASH->CR & FLASH_CR_LOCK) { // unlock
        STM32F4_FLASH->KEYR = STM32F4_FLASH_KEY1;
        STM32F4_FLASH->KEYR = STM32F4_FLASH_KEY2;
    }

    // enable erasing
    uint32_t cr = num * FLASH_CR_SNB_0 | FLASH_CR_SER;
    STM32F4_FLASH->CR = cr;
    // start erase
    cr |= FLASH_CR_STRT;
    STM32F4_FLASH->CR = cr;
    // assure busy flag is set up (see STM32F4 errata)
    STM32F4_FLASH->CR = cr;
    // wait for completion
    while (STM32F4_FLASH->SR & FLASH_SR_BSY);

    // reset & lock the controller
    STM32F4_FLASH->CR = FLASH_CR_LOCK;

    TinyCLR_Result::Success;
}

TinyCLR_Result STM32F4_Flash_Acquire(const TinyCLR_Storage_Controller* self) {
    deploymentDescriptor.CanReadDirect = true;
    deploymentDescriptor.CanWriteDirect = true;
    deploymentDescriptor.CanExecuteDirect = true;
    deploymentDescriptor.EraseBeforeWrite = true;
    deploymentDescriptor.Removable = false;
    deploymentDescriptor.RegionsRepeat = false;
    deploymentDescriptor.RegionCount = SIZEOF_ARRAY(deploymentSectors);
    deploymentDescriptor.RegionAddresses = reinterpret_cast<const uint64_t*>(deploymentSectorAddress);
    deploymentDescriptor.RegionSizes = reinterpret_cast<const size_t*>(deploymentSectorSize);

    deploymentConfiguration.RegionCount = SIZEOF_ARRAY(deploymentSectors);
    deploymentConfiguration.RegionAddresses = reinterpret_cast<const uint64_t*>(deploymentSectorAddress);
    deploymentConfiguration.RegionSizes = reinterpret_cast<const size_t*>(deploymentSectorSize);

    return TinyCLR_Result::Success;
}

TinyCLR_Result STM32F4_Flash_Release(const TinyCLR_Storage_Controller* self) {
    return TinyCLR_Result::Success;
}

TinyCLR_Result STM32F4_Flash_Open(const TinyCLR_Storage_Controller* self) {
    return TinyCLR_Result::Success;
}

TinyCLR_Result STM32F4_Flash_Close(const TinyCLR_Storage_Controller* self) {
    return TinyCLR_Result::Success;
}

TinyCLR_Result STM32F4_Flash_GetSectorSizeForAddress(const TinyCLR_Storage_Controller* self, uint32_t address, int32_t& size) {
    int32_t sectors = SIZEOF_ARRAY(deploymentSectors);

    size = 0;

    for (int32_t i = 0; i < sectors; i++) {
        if (address >= deploymentSectors[i].address && address < deploymentSectors[i].address + deploymentSectors[i].size) {
            size = deploymentSectors[i].size;

            break;
        }
    }

    return size > 0 ? TinyCLR_Result::Success : TinyCLR_Result::ArgumentInvalid;
}

TinyCLR_Result STM32F4_Flash_SetPresenceChangedHandler(const TinyCLR_Storage_Controller* self, TinyCLR_Storage_PresenceChangedHandler handler) {
    return TinyCLR_Result::NotImplemented;
}

TinyCLR_Result STM32F4_Flash_IsPresent(const TinyCLR_Storage_Controller* self, bool& present) {
    return TinyCLR_Result::NotImplemented;
}

TinyCLR_Result STM32F4_Flash_GetDescriptor(const TinyCLR_Storage_Controller* self, const TinyCLR_Storage_Descriptor*& descriptor) {
    descriptor = &deploymentDescriptor;

    return descriptor->RegionCount > 0 ? TinyCLR_Result::Success : TinyCLR_Result::NotImplemented;
}

void STM32F4_Deplpoyment_Reset() {
    for (int32_t i = 0; i < SIZEOF_ARRAY(deploymentSectors); i++) {
        deploymentSectorAddress[i] = deploymentSectors[i].address;
        deploymentSectorSize[i] = deploymentSectors[i].size;
    }

}<commit_msg>Tweak<commit_after>// Copyright Microsoft Corporation
// Copyright Oberon microsystems, Inc
// Copyright GHI Electronics, LLC
//
// 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.

#include "STM32F4.h"
#include <stdio.h>

#define TOTAL_DEPLOYMENT_CONTROLLERS 1

#ifndef STM32F4_FLASH
#define STM32F4_FLASH               ((FLASH_TypeDef *) FLASH_R_BASE)
#endif

struct DeploymentSector {
    uint32_t id;
    uint32_t address;
    uint32_t size;
};

#if STM32F4_SUPPLY_VOLTAGE_MV < 2100
#error 16 bit Flash programming not allowed for voltages below 2.1V
#endif
#if STM32F4_AHB_CLOCK_HZ < 1000000
#error Flash programming not allowed for HCLK below 1MHz
#endif

TinyCLR_Result STM32F4_Flash_GetSectorSizeForAddress(const TinyCLR_Storage_Controller* self, uint32_t address, int32_t& size);

static const DeploymentSector deploymentSectors[] = DEPLOYMENT_SECTORS;
static uint64_t deploymentSectorAddress[SIZEOF_ARRAY(deploymentSectors)];
static size_t deploymentSectorSize[SIZEOF_ARRAY(deploymentSectors)];

static const uint32_t STM32F4_FLASH_KEY1 = 0x45670123;
static const uint32_t STM32F4_FLASH_KEY2 = 0xcdef89ab;

static TinyCLR_Storage_Controller deploymentControllers[TOTAL_DEPLOYMENT_CONTROLLERS];
static TinyCLR_Api_Info deploymentApi[TOTAL_DEPLOYMENT_CONTROLLERS];
static TinyCLR_Storage_Descriptor deploymentDescriptor;
TinyCLR_Startup_DeploymentConfiguration deploymentConfiguration;

const TinyCLR_Api_Info* STM32F4_Deployment_GetApi() {
    for (int32_t i = 0; i < TOTAL_DEPLOYMENT_CONTROLLERS; i++) {
        deploymentControllers[i].ApiInfo = &deploymentApi[i];
        deploymentControllers[i].Acquire = &STM32F4_Flash_Acquire;
        deploymentControllers[i].Release = &STM32F4_Flash_Release;
        deploymentControllers[i].Open = &STM32F4_Flash_Open;
        deploymentControllers[i].Close = &STM32F4_Flash_Close;
        deploymentControllers[i].Read = &STM32F4_Flash_Read;
        deploymentControllers[i].Write = &STM32F4_Flash_Write;
        deploymentControllers[i].Erase = &STM32F4_Flash_Erase;
        deploymentControllers[i].IsErased = &STM32F4_Flash_IsErased;
        deploymentControllers[i].GetDescriptor = &STM32F4_Flash_GetDescriptor;
        deploymentControllers[i].IsPresent = &STM32F4_Flash_IsPresent;
        deploymentControllers[i].SetPresenceChangedHandler = &STM32F4_Flash_SetPresenceChangedHandler;

        deploymentApi[i].Author = "GHI Electronics, LLC";
        deploymentApi[i].Name = "GHIElectronics.TinyCLR.NativeApis.STM32F4.StorageController";
        deploymentApi[i].Type = TinyCLR_Api_Type::StorageController;
        deploymentApi[i].Version = 0;
        deploymentApi[i].Implementation = &deploymentControllers[i];
        deploymentApi[i].State = nullptr;
    }

    STM32F4_Deplpoyment_Reset();

    return (const TinyCLR_Api_Info*)&deploymentApi;
}

TinyCLR_Result __section("SectionForFlashOperations") STM32F4_Flash_Read(const TinyCLR_Storage_Controller* self, uint64_t address, size_t& count, uint8_t* data, uint64_t timeout) {
    int32_t bytePerSector = 0;

    if (data == nullptr) return TinyCLR_Result::ArgumentNull;
    if (STM32F4_Flash_GetSectorSizeForAddress(self, address, bytePerSector) != TinyCLR_Result::Success)
        return TinyCLR_Result::IndexOutOfRange;

    uint32_t* addressStart = reinterpret_cast<uint32_t*>(address);
    uint32_t* addressEnd = reinterpret_cast<uint32_t*>(address + count);
    uint32_t* pBuf = (uint32_t*)data;

    while (addressStart < addressEnd) {
        *pBuf++ = *addressStart++;
    }

    return TinyCLR_Result::Success;
}

TinyCLR_Result __section("SectionForFlashOperations") STM32F4_Flash_Write(const TinyCLR_Storage_Controller* self, uint64_t address, size_t& count, const uint8_t* data, uint64_t timeout) {
    int32_t bytePerSector = 0;

    if (data == nullptr) return TinyCLR_Result::ArgumentNull;
    if (STM32F4_Flash_GetSectorSizeForAddress(self, address, bytePerSector) != TinyCLR_Result::Success)
        return TinyCLR_Result::IndexOutOfRange;

    if (STM32F4_FLASH->CR & FLASH_CR_LOCK) { // unlock
        STM32F4_FLASH->KEYR = STM32F4_FLASH_KEY1;
        STM32F4_FLASH->KEYR = STM32F4_FLASH_KEY2;
    }

    uint32_t* addressStart = reinterpret_cast<uint32_t*>(address);
    uint32_t* addressEnd = reinterpret_cast<uint32_t*>(address + count);
    uint32_t* pBuf = (uint32_t*)data;

    // enable programming
    STM32F4_FLASH->CR = FLASH_CR_PG | FLASH_CR_PSIZE_1;

    while (addressStart < addressEnd) {
        if (*addressStart != *pBuf) {
            // write data
            *addressStart = *pBuf;
            // wait for completion
            while (STM32F4_FLASH->SR & FLASH_SR_BSY);
            // check
            if (*addressStart != *pBuf) {
                return TinyCLR_Result::InvalidOperation;
            }
        }
        addressStart++;
        pBuf++;
    }

    // reset & lock the controller
    STM32F4_FLASH->CR = FLASH_CR_LOCK;

    return TinyCLR_Result::Success;
}

TinyCLR_Result __section("SectionForFlashOperations") STM32F4_Flash_IsErased(const TinyCLR_Storage_Controller* self, uint64_t address, size_t& count, bool& erased) {
    auto sector = address; //address is sector. Use sector for clear

    if (sector >= SIZEOF_ARRAY(deploymentSectors)) return TinyCLR_Result::IndexOutOfRange;

    uint32_t* addressStart = reinterpret_cast<uint32_t*>(deploymentSectors[sector].address);
    uint32_t* addressEnd = reinterpret_cast<uint32_t*>(deploymentSectors[sector].address + deploymentSectors[sector].size);

    erased = true;

    while (addressStart < addressEnd) {
        if (*addressStart != 0xFFFFFFFF) {
            erased = false;

            break;
        }

        addressStart++;
    }

    return TinyCLR_Result::Success;
}

TinyCLR_Result __section("SectionForFlashOperations") STM32F4_Flash_Erase(const TinyCLR_Storage_Controller* self, uint64_t address, size_t& count, uint64_t timeout) {
    auto sector = address; //address is sector. Use sector for clear

    if (sector >= SIZEOF_ARRAY(deploymentSectors)) return TinyCLR_Result::IndexOutOfRange;

    uint32_t num = deploymentSectors[sector].id;

    if (num > 11) num += 4;

    if (STM32F4_FLASH->CR & FLASH_CR_LOCK) { // unlock
        STM32F4_FLASH->KEYR = STM32F4_FLASH_KEY1;
        STM32F4_FLASH->KEYR = STM32F4_FLASH_KEY2;
    }

    // enable erasing
    uint32_t cr = num * FLASH_CR_SNB_0 | FLASH_CR_SER;
    STM32F4_FLASH->CR = cr;
    // start erase
    cr |= FLASH_CR_STRT;
    STM32F4_FLASH->CR = cr;
    // assure busy flag is set up (see STM32F4 errata)
    STM32F4_FLASH->CR = cr;
    // wait for completion
    while (STM32F4_FLASH->SR & FLASH_SR_BSY);

    // reset & lock the controller
    STM32F4_FLASH->CR = FLASH_CR_LOCK;

    TinyCLR_Result::Success;
}

TinyCLR_Result STM32F4_Flash_Acquire(const TinyCLR_Storage_Controller* self) {
    deploymentDescriptor.CanReadDirect = true;
    deploymentDescriptor.CanWriteDirect = true;
    deploymentDescriptor.CanExecuteDirect = true;
    deploymentDescriptor.EraseBeforeWrite = true;
    deploymentDescriptor.Removable = false;
    deploymentDescriptor.RegionsRepeat = false;

    deploymentDescriptor.RegionCount = SIZEOF_ARRAY(deploymentSectors);
    deploymentDescriptor.RegionAddresses = reinterpret_cast<const uint64_t*>(deploymentSectorAddress);
    deploymentDescriptor.RegionSizes = reinterpret_cast<const size_t*>(deploymentSectorSize);

    deploymentConfiguration.RegionCount = deploymentDescriptor.RegionCount;
    deploymentConfiguration.RegionAddresses = deploymentDescriptor.RegionAddresses;
    deploymentConfiguration.RegionSizes = deploymentDescriptor.RegionSizes;

    return TinyCLR_Result::Success;
}

TinyCLR_Result STM32F4_Flash_Release(const TinyCLR_Storage_Controller* self) {
    return TinyCLR_Result::Success;
}

TinyCLR_Result STM32F4_Flash_Open(const TinyCLR_Storage_Controller* self) {
    return TinyCLR_Result::Success;
}

TinyCLR_Result STM32F4_Flash_Close(const TinyCLR_Storage_Controller* self) {
    return TinyCLR_Result::Success;
}

TinyCLR_Result STM32F4_Flash_GetSectorSizeForAddress(const TinyCLR_Storage_Controller* self, uint32_t address, int32_t& size) {
    int32_t sectors = SIZEOF_ARRAY(deploymentSectors);

    size = 0;

    for (int32_t i = 0; i < sectors; i++) {
        if (address >= deploymentSectors[i].address && address < deploymentSectors[i].address + deploymentSectors[i].size) {
            size = deploymentSectors[i].size;

            break;
        }
    }

    return size > 0 ? TinyCLR_Result::Success : TinyCLR_Result::ArgumentInvalid;
}

TinyCLR_Result STM32F4_Flash_SetPresenceChangedHandler(const TinyCLR_Storage_Controller* self, TinyCLR_Storage_PresenceChangedHandler handler) {
    return TinyCLR_Result::NotImplemented;
}

TinyCLR_Result STM32F4_Flash_IsPresent(const TinyCLR_Storage_Controller* self, bool& present) {
    return TinyCLR_Result::NotImplemented;
}

TinyCLR_Result STM32F4_Flash_GetDescriptor(const TinyCLR_Storage_Controller* self, const TinyCLR_Storage_Descriptor*& descriptor) {
    descriptor = &deploymentDescriptor;

    return descriptor->RegionCount > 0 ? TinyCLR_Result::Success : TinyCLR_Result::NotImplemented;
}

void STM32F4_Deplpoyment_Reset() {
    for (int32_t i = 0; i < SIZEOF_ARRAY(deploymentSectors); i++) {
        deploymentSectorAddress[i] = deploymentSectors[i].address;
        deploymentSectorSize[i] = deploymentSectors[i].size;
    }

}<|endoftext|>


<commit_before>/*
    Copyright (C) 2009-2011 qiuu
    Copyright (C) 2016 Clownacy

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
    USA
*/

#include <cstdio>
#include <cstdint>
#include <cstring>
#include <SDL2/SDL.h>

#include "Screen.h"
#ifdef _WIN32
#include "WinAPI.h"
#include <windows.h>
#endif

#ifdef _WIN32
#define ADJUSTED_SCREEN_HEIGHT (SCREEN_HEIGHT + GetSystemMetrics(SM_CYMENU))
#else
#define ADJUSTED_SCREEN_HEIGHT SCREEN_HEIGHT
#endif

Screen::Screen(void)
{
	if (SDL_Init(SDL_INIT_VIDEO)<0)
		this->ShowInternalError("Unable to init SDL video\n\n", SDL_GetError());

	atexit(SDL_Quit);

	this->window = SDL_CreateWindow("Captain PlaneEd v1.0.1+", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, ADJUSTED_SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
	if (this->window == NULL)
		this->ShowInternalError("Unable to init SDL Window\n\n", SDL_GetError());

	this->renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_ACCELERATED);
	if (this->renderer == NULL)
		this->ShowInternalError("Unable to init SDL Renderer\n\n", SDL_GetError());

	SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT);

	SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
	this->texture = SDL_CreateTexture(this->renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH, SCREEN_HEIGHT);
	if (this->texture==NULL)
		this->ShowInternalError("Unable to init screen SDL Texture\n\n", SDL_GetError());

	this->background_colour = {.r = 0, .g = 0, .b = 0, .a = 0};

#ifdef _WIN32
	// Windows-only crap to generate a menu bar
	WinAPI::SaveHWND(this->window);
	WinAPI::CreateMenuBar();
#endif
}

void Screen::ProcessDisplay(void)
{
	SDL_SetRenderTarget(this->renderer, NULL);
	SDL_SetRenderDrawColor(this->renderer, 0, 0, 0, 0xFF);
	SDL_RenderClear(this->renderer);
	SDL_RenderCopy(this->renderer, this->texture, NULL, NULL);

	SDL_RenderPresent(this->renderer);
}

void Screen::Clear(void)
{
	SDL_SetRenderDrawColor(this->renderer, this->background_colour.r, this->background_colour.g, this->background_colour.b, 0xFF);
	SDL_RenderFillRect(this->renderer, NULL);
}

void Screen::ShowInformation(const char* const message)
{
	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Information", message, this->window);
}

void Screen::ShowInformation(const char* const message_part1, const char* const message_part2)
{
	char* const whole_message = new char[strlen(message_part1)+strlen(message_part2)+1];
	sprintf(whole_message, "%s%s", message_part1, message_part2);
	this->ShowInformation(whole_message);
	delete[] whole_message;
}

void Screen::ShowWarning(const char* const message)
{
	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Warning", message, this->window);
}

void Screen::ShowError(const char* const message)
{
	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", message, this->window);
	exit(1);
}

void Screen::ShowInternalError(const char* const message)
{
	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Internal Error", message, this->window);
	exit(1);
}

void Screen::ShowInternalError(const char* const message_part1, const char* const message_part2)
{
	char* const whole_message = new char[strlen(message_part1)+strlen(message_part2)+1];
	sprintf(whole_message, "%s%s", message_part1, message_part2);
	this->ShowInternalError(whole_message);
	delete[] whole_message;
}
<commit_msg>Bump the version number<commit_after>/*
    Copyright (C) 2009-2011 qiuu
    Copyright (C) 2016 Clownacy

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
    USA
*/

#include <cstdio>
#include <cstdint>
#include <cstring>
#include <SDL2/SDL.h>

#include "Screen.h"
#ifdef _WIN32
#include "WinAPI.h"
#include <windows.h>
#endif

#ifdef _WIN32
#define ADJUSTED_SCREEN_HEIGHT (SCREEN_HEIGHT + GetSystemMetrics(SM_CYMENU))
#else
#define ADJUSTED_SCREEN_HEIGHT SCREEN_HEIGHT
#endif

Screen::Screen(void)
{
	if (SDL_Init(SDL_INIT_VIDEO)<0)
		this->ShowInternalError("Unable to init SDL video\n\n", SDL_GetError());

	atexit(SDL_Quit);

	this->window = SDL_CreateWindow("Captain PlaneEd v1.1", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, ADJUSTED_SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
	if (this->window == NULL)
		this->ShowInternalError("Unable to init SDL Window\n\n", SDL_GetError());

	this->renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_ACCELERATED);
	if (this->renderer == NULL)
		this->ShowInternalError("Unable to init SDL Renderer\n\n", SDL_GetError());

	SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT);

	SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
	this->texture = SDL_CreateTexture(this->renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH, SCREEN_HEIGHT);
	if (this->texture==NULL)
		this->ShowInternalError("Unable to init screen SDL Texture\n\n", SDL_GetError());

	this->background_colour = {.r = 0, .g = 0, .b = 0, .a = 0};

#ifdef _WIN32
	// Windows-only crap to generate a menu bar
	WinAPI::SaveHWND(this->window);
	WinAPI::CreateMenuBar();
#endif
}

void Screen::ProcessDisplay(void)
{
	SDL_SetRenderTarget(this->renderer, NULL);
	SDL_SetRenderDrawColor(this->renderer, 0, 0, 0, 0xFF);
	SDL_RenderClear(this->renderer);
	SDL_RenderCopy(this->renderer, this->texture, NULL, NULL);

	SDL_RenderPresent(this->renderer);
}

void Screen::Clear(void)
{
	SDL_SetRenderDrawColor(this->renderer, this->background_colour.r, this->background_colour.g, this->background_colour.b, 0xFF);
	SDL_RenderFillRect(this->renderer, NULL);
}

void Screen::ShowInformation(const char* const message)
{
	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Information", message, this->window);
}

void Screen::ShowInformation(const char* const message_part1, const char* const message_part2)
{
	char* const whole_message = new char[strlen(message_part1)+strlen(message_part2)+1];
	sprintf(whole_message, "%s%s", message_part1, message_part2);
	this->ShowInformation(whole_message);
	delete[] whole_message;
}

void Screen::ShowWarning(const char* const message)
{
	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Warning", message, this->window);
}

void Screen::ShowError(const char* const message)
{
	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", message, this->window);
	exit(1);
}

void Screen::ShowInternalError(const char* const message)
{
	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Internal Error", message, this->window);
	exit(1);
}

void Screen::ShowInternalError(const char* const message_part1, const char* const message_part2)
{
	char* const whole_message = new char[strlen(message_part1)+strlen(message_part2)+1];
	sprintf(whole_message, "%s%s", message_part1, message_part2);
	this->ShowInternalError(whole_message);
	delete[] whole_message;
}
<|endoftext|>