<commit_before>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/fastos/fastos.h>
#include <vespa/log/log.h>
LOG_SETUP(".proton.docsummary.summarymanager");
#include "documentstoreadapter.h"
#include "summarycompacttarget.h"
#include "summaryflushtarget.h"
#include "summarymanager.h"
#include <vespa/searchcore/proton/common/eventlogger.h>
#include <vespa/searchlib/docstore/logdocumentstore.h>
#include <vespa/searchsummary/docsummary/docsumconfig.h>
#include <vespa/config/print/ostreamconfigwriter.h>

using namespace config;
using namespace document;
using namespace search::docsummary;
using namespace vespa::config::search::core;
using namespace vespa::config::search::summary;
using namespace vespa::config::search;

using search::TuneFileSummary;
using search::common::FileHeaderContext;

namespace proton {

SummaryManager::SummarySetup::
SummarySetup(const vespalib::string & baseDir,
             const DocTypeName & docTypeName,
             const SummaryConfig & summaryCfg,
             const SummarymapConfig & summarymapCfg,
             const JuniperrcConfig & juniperCfg,
             const search::IAttributeManager::SP &attributeMgr,
             const search::IDocumentStore::SP & docStore,
             const DocumentTypeRepo::SP &repo)
    : _docsumWriter(),
      _wordFolder(),
      _juniperProps(juniperCfg),
      _juniperConfig(),
      _attributeMgr(attributeMgr),
      _docStore(docStore),
      _fieldCacheRepo(),
      _repo(repo),
      _markupFields()
{
    std::unique_ptr<ResultConfig> resultConfig(new ResultConfig());
    if (!resultConfig->ReadConfig(summaryCfg,
                                  vespalib::make_string("SummaryManager(%s)",
                                          baseDir.c_str()).c_str())) {
        std::ostringstream oss;
        config::OstreamConfigWriter writer(oss);
        writer.write(summaryCfg);
        throw vespalib::IllegalArgumentException
            (vespalib::make_string("Could not initialize "
                                   "summary result config for directory '%s' "
                                   "based on summary config '%s'",
                                   baseDir.c_str(), oss.str().c_str()));
    }

    _juniperConfig.reset(new juniper::Juniper(&_juniperProps, &_wordFolder));
    _docsumWriter.reset(new DynamicDocsumWriter(resultConfig.release(), NULL));
    DynamicDocsumConfig dynCfg(this, _docsumWriter.get());
    dynCfg.configure(summarymapCfg);
    for (size_t i = 0; i < summarymapCfg.override.size(); ++i) {
        const SummarymapConfig::Override & o = summarymapCfg.override[i];
        if (o.command == "dynamicteaser" ||
            o.command == "textextractor") {
            vespalib::string markupField = o.arguments;
            if (markupField.empty())
                continue;
            // Assume just one argument: source field that must contain markup
            _markupFields.insert(markupField);
        }
    }
    const DocumentType *docType = repo->getDocumentType(docTypeName.getName());
    if (docType != NULL) {
        _fieldCacheRepo.reset(new FieldCacheRepo(getResultConfig(), *docType));
    } else if (getResultConfig().GetNumResultClasses() == 0) {
        LOG(debug, "Create empty field cache repo for document type '%s'",
            docTypeName.toString().c_str());
        _fieldCacheRepo.reset(new FieldCacheRepo());
    } else {
        throw vespalib::IllegalArgumentException
            (vespalib::make_string("Did not find document type '%s' in current document type repo. "
                                   "Cannot setup field cache repo for the summary setup",
                                   docTypeName.toString().c_str()));
    }
}

IDocsumStore::UP SummaryManager::SummarySetup::createDocsumStore(
        const vespalib::string &resultClassName) {
    return search::docsummary::IDocsumStore::UP(
            new DocumentStoreAdapter(
                    *_docStore, *_repo, getResultConfig(), resultClassName,
                    _fieldCacheRepo->getFieldCache(resultClassName),
                    _markupFields));
}

ISummaryManager::ISummarySetup::SP
SummaryManager::createSummarySetup(const SummaryConfig & summaryCfg,
                                   const SummarymapConfig & summarymapCfg,
                                   const JuniperrcConfig & juniperCfg,
                                   const DocumentTypeRepo::SP &repo,
                                   const search::IAttributeManager::SP &attributeMgr)
{
    ISummarySetup::SP newSetup(new SummarySetup(_baseDir, _docTypeName, summaryCfg,
                                                summarymapCfg, juniperCfg,
                                                attributeMgr, _docStore, repo));
    return newSetup;
}

namespace {

search::DocumentStore::Config getStoreConfig(const ProtonConfig::Summary::Cache & cache)
{
    document::CompressionConfig compression;
    if (cache.compression.type == ProtonConfig::Summary::Cache::Compression::LZ4) {
        compression.type = document::CompressionConfig::LZ4;
    }
    compression.compressionLevel = cache.compression.level;
    return search::DocumentStore::Config(compression, cache.maxbytes, cache.initialentries).allowVisitCaching(cache.allowvisitcaching);
}

}

SummaryManager::SummaryManager(vespalib::ThreadStackExecutorBase & executor,
                               const ProtonConfig::Summary & summary,
                               const search::GrowStrategy & growStrategy,
                               const vespalib::string &baseDir,
                               const DocTypeName &docTypeName,
                               const TuneFileSummary &tuneFileSummary,
                               const FileHeaderContext &fileHeaderContext,
                               search::transactionlog::SyncProxy &tlSyncer,
                               const search::IBucketizer::SP & bucketizer)
    : _baseDir(baseDir),
      _docTypeName(docTypeName),
      _docStore(),
      _tuneFileSummary(tuneFileSummary),
      _currentSerial(0u)
{
    search::DocumentStore::Config config(getStoreConfig(summary.cache));
    const ProtonConfig::Summary::Log & log(summary.log);
    const ProtonConfig::Summary::Log::Chunk & chunk(log.chunk);
    document::CompressionConfig chunkCompression;
    if (chunk.compression.type == ProtonConfig::Summary::Log::Chunk::Compression::LZ4) {
        chunkCompression.type = document::CompressionConfig::LZ4;
    }
    chunkCompression.compressionLevel = chunk.compression.level;

    document::CompressionConfig compactCompression;
    if (chunk.compression.type == ProtonConfig::Summary::Log::Chunk::Compression::LZ4) {
        compactCompression.type = document::CompressionConfig::LZ4;
    }
    compactCompression.compressionLevel = chunk.compression.level;

    search::WriteableFileChunk::Config fileConfig(chunkCompression, chunk.maxbytes, chunk.maxentries);
    search::LogDataStore::Config logConfig(log.maxfilesize,
                                           log.maxdiskbloatfactor,
                                           log.maxbucketspread,
                                           log.minfilesizefactor,
                                           log.numthreads,
                                           log.compact2activefile,
                                           compactCompression,
                                           fileConfig);
    logConfig.disableCrcOnRead(chunk.skipcrconread);
    _docStore.reset(
            new search::LogDocumentStore(executor, baseDir,
                                         search::LogDocumentStore::
                                         Config(config, logConfig),
                                         growStrategy,
                                         tuneFileSummary,
                                         fileHeaderContext,
                                         tlSyncer,
                                         summary.compact2buckets ? bucketizer : search::IBucketizer::SP()));
}

void
SummaryManager::putDocument(uint64_t syncToken, const Document & doc, search::DocumentIdT lid)
{
    _docStore->write(syncToken, doc, lid);
    _currentSerial = syncToken;
}

void
SummaryManager::removeDocument(uint64_t syncToken, search::DocumentIdT lid)
{
    _docStore->remove(syncToken, lid);
    _currentSerial = syncToken;
}

IFlushTarget::List SummaryManager::getFlushTargets()
{
    IFlushTarget::List ret;
    ret.push_back(IFlushTarget::SP(new SummaryFlushTarget(getBackingStore())));
    if (dynamic_cast<search::LogDocumentStore *>(_docStore.get()) != NULL) {
        ret.push_back(IFlushTarget::SP(new SummaryCompactTarget(getBackingStore())));
    }
    return ret;
}

} // namespace proton
<commit_msg>Avoid copy paste errors by using a template for deriving compression config.<commit_after>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/fastos/fastos.h>
#include <vespa/log/log.h>
LOG_SETUP(".proton.docsummary.summarymanager");
#include "documentstoreadapter.h"
#include "summarycompacttarget.h"
#include "summaryflushtarget.h"
#include "summarymanager.h"
#include <vespa/searchcore/proton/common/eventlogger.h>
#include <vespa/searchlib/docstore/logdocumentstore.h>
#include <vespa/searchsummary/docsummary/docsumconfig.h>
#include <vespa/config/print/ostreamconfigwriter.h>

using namespace config;
using namespace document;
using namespace search::docsummary;
using namespace vespa::config::search::core;
using namespace vespa::config::search::summary;
using namespace vespa::config::search;

using search::TuneFileSummary;
using search::common::FileHeaderContext;

namespace proton {

SummaryManager::SummarySetup::
SummarySetup(const vespalib::string & baseDir,
             const DocTypeName & docTypeName,
             const SummaryConfig & summaryCfg,
             const SummarymapConfig & summarymapCfg,
             const JuniperrcConfig & juniperCfg,
             const search::IAttributeManager::SP &attributeMgr,
             const search::IDocumentStore::SP & docStore,
             const DocumentTypeRepo::SP &repo)
    : _docsumWriter(),
      _wordFolder(),
      _juniperProps(juniperCfg),
      _juniperConfig(),
      _attributeMgr(attributeMgr),
      _docStore(docStore),
      _fieldCacheRepo(),
      _repo(repo),
      _markupFields()
{
    std::unique_ptr<ResultConfig> resultConfig(new ResultConfig());
    if (!resultConfig->ReadConfig(summaryCfg,
                                  vespalib::make_string("SummaryManager(%s)",
                                          baseDir.c_str()).c_str())) {
        std::ostringstream oss;
        config::OstreamConfigWriter writer(oss);
        writer.write(summaryCfg);
        throw vespalib::IllegalArgumentException
            (vespalib::make_string("Could not initialize "
                                   "summary result config for directory '%s' "
                                   "based on summary config '%s'",
                                   baseDir.c_str(), oss.str().c_str()));
    }

    _juniperConfig.reset(new juniper::Juniper(&_juniperProps, &_wordFolder));
    _docsumWriter.reset(new DynamicDocsumWriter(resultConfig.release(), NULL));
    DynamicDocsumConfig dynCfg(this, _docsumWriter.get());
    dynCfg.configure(summarymapCfg);
    for (size_t i = 0; i < summarymapCfg.override.size(); ++i) {
        const SummarymapConfig::Override & o = summarymapCfg.override[i];
        if (o.command == "dynamicteaser" ||
            o.command == "textextractor") {
            vespalib::string markupField = o.arguments;
            if (markupField.empty())
                continue;
            // Assume just one argument: source field that must contain markup
            _markupFields.insert(markupField);
        }
    }
    const DocumentType *docType = repo->getDocumentType(docTypeName.getName());
    if (docType != NULL) {
        _fieldCacheRepo.reset(new FieldCacheRepo(getResultConfig(), *docType));
    } else if (getResultConfig().GetNumResultClasses() == 0) {
        LOG(debug, "Create empty field cache repo for document type '%s'",
            docTypeName.toString().c_str());
        _fieldCacheRepo.reset(new FieldCacheRepo());
    } else {
        throw vespalib::IllegalArgumentException
            (vespalib::make_string("Did not find document type '%s' in current document type repo. "
                                   "Cannot setup field cache repo for the summary setup",
                                   docTypeName.toString().c_str()));
    }
}

IDocsumStore::UP SummaryManager::SummarySetup::createDocsumStore(
        const vespalib::string &resultClassName) {
    return search::docsummary::IDocsumStore::UP(
            new DocumentStoreAdapter(
                    *_docStore, *_repo, getResultConfig(), resultClassName,
                    _fieldCacheRepo->getFieldCache(resultClassName),
                    _markupFields));
}

ISummaryManager::ISummarySetup::SP
SummaryManager::createSummarySetup(const SummaryConfig & summaryCfg,
                                   const SummarymapConfig & summarymapCfg,
                                   const JuniperrcConfig & juniperCfg,
                                   const DocumentTypeRepo::SP &repo,
                                   const search::IAttributeManager::SP &attributeMgr)
{
    ISummarySetup::SP newSetup(new SummarySetup(_baseDir, _docTypeName, summaryCfg,
                                                summarymapCfg, juniperCfg,
                                                attributeMgr, _docStore, repo));
    return newSetup;
}

namespace {

template<typename T>
document::CompressionConfig
deriveCompression(const T & config) {
    document::CompressionConfig compression;
    if (config.type == T::LZ4) {
        compression.type = document::CompressionConfig::LZ4;
    }
    compression.compressionLevel = config.level;
    return compression;
}

search::DocumentStore::Config getStoreConfig(const ProtonConfig::Summary::Cache & cache)
{
    return search::DocumentStore::Config(deriveCompression(cache.compression), cache.maxbytes, cache.initialentries).allowVisitCaching(cache.allowvisitcaching);
}

}

SummaryManager::SummaryManager(vespalib::ThreadStackExecutorBase & executor,
                               const ProtonConfig::Summary & summary,
                               const search::GrowStrategy & growStrategy,
                               const vespalib::string &baseDir,
                               const DocTypeName &docTypeName,
                               const TuneFileSummary &tuneFileSummary,
                               const FileHeaderContext &fileHeaderContext,
                               search::transactionlog::SyncProxy &tlSyncer,
                               const search::IBucketizer::SP & bucketizer)
    : _baseDir(baseDir),
      _docTypeName(docTypeName),
      _docStore(),
      _tuneFileSummary(tuneFileSummary),
      _currentSerial(0u)
{
    search::DocumentStore::Config config(getStoreConfig(summary.cache));
    const ProtonConfig::Summary::Log & log(summary.log);
    const ProtonConfig::Summary::Log::Chunk & chunk(log.chunk);

    search::WriteableFileChunk::Config fileConfig(deriveCompression(chunk.compression), chunk.maxbytes, chunk.maxentries);
    search::LogDataStore::Config logConfig(log.maxfilesize,
                                           log.maxdiskbloatfactor,
                                           log.maxbucketspread,
                                           log.minfilesizefactor,
                                           log.numthreads,
                                           log.compact2activefile,
                                           deriveCompression(log.compact.compression),
                                           fileConfig);
    logConfig.disableCrcOnRead(chunk.skipcrconread);
    _docStore.reset(
            new search::LogDocumentStore(executor, baseDir,
                                         search::LogDocumentStore::
                                         Config(config, logConfig),
                                         growStrategy,
                                         tuneFileSummary,
                                         fileHeaderContext,
                                         tlSyncer,
                                         summary.compact2buckets ? bucketizer : search::IBucketizer::SP()));
}

void
SummaryManager::putDocument(uint64_t syncToken, const Document & doc, search::DocumentIdT lid)
{
    _docStore->write(syncToken, doc, lid);
    _currentSerial = syncToken;
}

void
SummaryManager::removeDocument(uint64_t syncToken, search::DocumentIdT lid)
{
    _docStore->remove(syncToken, lid);
    _currentSerial = syncToken;
}

IFlushTarget::List SummaryManager::getFlushTargets()
{
    IFlushTarget::List ret;
    ret.push_back(IFlushTarget::SP(new SummaryFlushTarget(getBackingStore())));
    if (dynamic_cast<search::LogDocumentStore *>(_docStore.get()) != NULL) {
        ret.push_back(IFlushTarget::SP(new SummaryCompactTarget(getBackingStore())));
    }
    return ret;
}

} // namespace proton
<|endoftext|>


<commit_before>#ifndef INC_STATIC_POW_HPP_
#define INC_STATIC_POW_HPP_

#include <boost/integer.hpp>

namespace utils {
    template<size_t n, size_t p>
    struct static_pow
    {
        static boost::uintmax_t const value = n * static_pow<n, p-1>::value;
    };

    template<size_t n>
    struct static_pow<n, 1>
    {
        static boost::uintmax_t const value = n;
    };
}

#endif
<commit_msg>assertion if p < 0<commit_after>#ifndef INC_STATIC_POW_HPP_
#define INC_STATIC_POW_HPP_

#include <boost/integer.hpp>
#include <boost/static_assert.hpp>

namespace utils {
    template<size_t n, size_t p>
    struct static_pow
    {
        BOOST_STATIC_ASSERT((p >= 0));
        static boost::uintmax_t const value = n * static_pow<n, p-1>::value;
    };

    template<size_t n>
    struct static_pow<n, 0>
    {
        static boost::uintmax_t const value = 1;
    };
}

#endif
<|endoftext|>


<commit_before>#include "BootSplash.h"
#include "ui_BootSplash.h"

#include <LuminaXDG.h>

BootSplash::BootSplash() : QWidget(0, Qt::SplashScreen | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus), ui(new Ui::BootSplash){
  ui->setupUi(this);
  this->setObjectName("LuminaBootSplash"); //for theme styling
  //Center the window on the primary screen
  QPoint ctr = QApplication::desktop()->screenGeometry().center();
  this->move( ctr.x()-(this->width()/2), ctr.y()-(this->height()/2) );
}

void BootSplash::showScreen(QString loading){ //update icon, text, and progress
  QString txt, icon;
  int per = 0;
  if(loading=="init"){
    txt = tr("Initializing Session..."); per = 10;
    icon = "preferences-system-login";
  }else if(loading=="settings"){
    txt = tr("Loading Settings..."); per = 20;
    icon = "user-home";
  }else if(loading=="user"){
    txt = tr("Checking User Settings..."); per = 30;
    icon = "preferences-desktop-user";
  }else if(loading=="systray"){
    txt = tr("Registering System Tray..."); per = 40;
    icon = "preferences-plugin";
  }else if(loading=="wm"){
    txt = tr("Starting Window Manager..."); per = 50;
    icon = "preferences-system-windows-actions";
  }else if(loading=="apps"){
    txt = tr("Detecting System Applications..."); per = 60;
    icon = "preferences-desktop-icons";
  }else if(loading=="menus"){
    txt = tr("Initializing System Menu(s)..."); per = 70;
    icon = "preferences-system-windows";
  }else if(loading=="desktop"){
    txt = tr("Initializing Desktop(s)..."); per = 80;
    icon = "preferences-desktop-wallpaper";
  }else if(loading=="final"){
    txt = tr("Performing Final Checks..."); per = 90;
    icon = "pcbsd";
  }
  ui->progressBar->setValue(per);
  ui->label_text->setText(txt);
  ui->label_icon->setPixmap( LXDG::findIcon(icon, "Lumina-DE").pixmap(64,64) );
  this->show();
  this->update();
  QApplication::processEvents();
}

void BootSplash::showText(QString txt){ //will only update the text, not the icon/progress
  ui->label_text->setText(txt);
  this->show();
  this->update();
  QApplication::processEvents();
}<commit_msg>Tidier wording, and punctuation, in BootSplash.cpp<commit_after>#include "BootSplash.h"
#include "ui_BootSplash.h"

#include <LuminaXDG.h>

BootSplash::BootSplash() : QWidget(0, Qt::SplashScreen | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus), ui(new Ui::BootSplash){
  ui->setupUi(this);
  this->setObjectName("LuminaBootSplash"); //for theme styling
  //Center the window on the primary screen
  QPoint ctr = QApplication::desktop()->screenGeometry().center();
  this->move( ctr.x()-(this->width()/2), ctr.y()-(this->height()/2) );
}

void BootSplash::showScreen(QString loading){ //update icon, text, and progress
  QString txt, icon;
  int per = 0;
  if(loading=="init"){
    txt = tr("Initializing Session …"); per = 10;
    icon = "preferences-system-login";
  }else if(loading=="settings"){
    txt = tr("Loading System Settings …"); per = 20;
    icon = "user-home";
  }else if(loading=="user"){
    txt = tr("Loading User Preferences …"); per = 30;
    icon = "preferences-desktop-user";
  }else if(loading=="systray"){
    txt = tr("Preparing System Tray …"); per = 40;
    icon = "preferences-plugin";
  }else if(loading=="wm"){
    txt = tr("Starting Window Manager …"); per = 50;
    icon = "preferences-system-windows-actions";
  }else if(loading=="apps"){
    txt = tr("Detecting Applications …"); per = 60;
    icon = "preferences-desktop-icons";
  }else if(loading=="menus"){
    txt = tr("Preparing Menus …"); per = 70;
    icon = "preferences-system-windows";
  }else if(loading=="desktop"){
    txt = tr("Preparing Workspace …"); per = 80;
    icon = "preferences-desktop-wallpaper";
  }else if(loading=="final"){
    txt = tr("Finalizing …"); per = 90;
    icon = "pcbsd";
  }
  ui->progressBar->setValue(per);
  ui->label_text->setText(txt);
  ui->label_icon->setPixmap( LXDG::findIcon(icon, "Lumina-DE").pixmap(64,64) );
  this->show();
  this->update();
  QApplication::processEvents();
}

void BootSplash::showText(QString txt){ //will only update the text, not the icon/progress
  ui->label_text->setText(txt);
  this->show();
  this->update();
  QApplication::processEvents();
}
<|endoftext|>


<commit_before>
/*
 * Copyright (c) 2012-2021 Karl N. Redgate
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/** \file redx.cc
 * \brief A diagnostic shell
 *
 * \todo add process status/grep/lookup/etc
 * \todo add dbus
 * \todo add syslog
 */

#include <sys/stat.h>
#include <errno.h>

#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <dirent.h>
#include <pthread.h>
#include <string.h>
#include <syslog.h>

#include "platform.h"

#include "tcl_util.h"
#include "AppInit.h"

/**
 */
int RedX_Init( Tcl_Interp *interp ) {
    int interactive = 1;
    Tcl_Obj *interactive_obj;
    interactive_obj = Tcl_GetVar2Ex( interp, "tcl_interactive", NULL, TCL_GLOBAL_ONLY );
    if ( interactive_obj != NULL ) {
        Tcl_GetIntFromObj( interp, interactive_obj, &interactive );
    }

    Tcl_Command command;

    if ( interactive ) printf( " ** RedX debug tool v1.0\n" );
    Tcl_SetVar(interp, "tcl_rcFileName", "~/.redxrc", TCL_GLOBAL_ONLY);

    Tcl_EvalEx( interp, "proc clock {command} { namespace eval ::tcl::clock $command}", -1, TCL_EVAL_GLOBAL );
    Tcl_EvalEx( interp, "proc commands {} {namespace eval commands {info procs}}", -1, TCL_EVAL_GLOBAL );
    const char *help_script = "proc help {args} {\n"
        "  foreach name [namespace children] {\n"
        "    puts \"## $name commands\"\n"
        "    foreach command [info commands \"${name}::*\"] {\n"
        "      puts -nonewline \"[namespace tail $command] \"\n"
        "    }\n"
        "    puts {}\n"
        "  }\n"
        "}\n";
    int retcode = Tcl_EvalEx( interp, help_script, -1, TCL_EVAL_GLOBAL );
    if ( retcode != TCL_OK )  return false;

#if 0
    if ( getuid() != 0 ) {
        if ( interactive ) printf( "BIOS not initialized, no access to /dev/mem\n" );
    } else {
        if ( BIOS::Initialize(interp) == false ) {
            Tcl_StaticSetResult( interp, "BIOS::Initialize failed" );
            return TCL_ERROR;
        }
        if ( interactive ) printf( "BIOS initialized\n" );
    }

    if ( access("/proc/xen/privcmd", R_OK) != 0 ) {
        if ( interactive ) printf( "Xen not initialized, no hypervisor present\n" );
    } else {
        if ( Xen::Initialize(interp) == false ) {
            Tcl_StaticSetResult( interp, "Xen::Initialize failed" );
            return TCL_ERROR;
        }
        if ( interactive ) printf( "Xen initialized\n" );
    }

#endif

    if ( Tcl_CallAppInitChain(interp) == false ) {
        // this may want to be additive result
        Tcl_StaticSetResult( interp, "AppInit failed" );
        return TCL_ERROR;
    }

    return TCL_OK;
}

/**
 */
int main( int argc, char **argv ) {
    Tcl_Main( argc, argv, RedX_Init );
}

/* vim: set autoindent expandtab sw=4 : */
<commit_msg>initialize the logger<commit_after>
/*
 * Copyright (c) 2012-2021 Karl N. Redgate
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/** \file redx.cc
 * \brief A diagnostic shell
 *
 * \todo add process status/grep/lookup/etc
 * \todo add dbus
 * \todo add syslog
 */

#include <sys/stat.h>
#include <errno.h>

#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <dirent.h>
#include <pthread.h>
#include <string.h>
#include <syslog.h>

#include "platform.h"
#include "logger.h"

#include "tcl_util.h"
#include "AppInit.h"

/**
 */
int RedX_Init( Tcl_Interp *interp ) {
    int interactive = 1;
    Tcl_Obj *interactive_obj;
    interactive_obj = Tcl_GetVar2Ex( interp, "tcl_interactive", NULL, TCL_GLOBAL_ONLY );
    if ( interactive_obj != NULL ) {
        Tcl_GetIntFromObj( interp, interactive_obj, &interactive );
    }
    log_interactive( interactive );

    Tcl_Command command;

    if ( interactive ) printf( " ** RedX debug tool v1.0\n" );
    Tcl_SetVar(interp, "tcl_rcFileName", "~/.redxrc", TCL_GLOBAL_ONLY);

    Tcl_EvalEx( interp, "proc clock {command} { namespace eval ::tcl::clock $command}", -1, TCL_EVAL_GLOBAL );
    Tcl_EvalEx( interp, "proc commands {} {namespace eval commands {info procs}}", -1, TCL_EVAL_GLOBAL );
    const char *help_script = "proc help {args} {\n"
        "  foreach name [namespace children] {\n"
        "    puts \"## $name commands\"\n"
        "    foreach command [info commands \"${name}::*\"] {\n"
        "      puts -nonewline \"[namespace tail $command] \"\n"
        "    }\n"
        "    puts {}\n"
        "  }\n"
        "}\n";
    int retcode = Tcl_EvalEx( interp, help_script, -1, TCL_EVAL_GLOBAL );
    if ( retcode != TCL_OK )  return false;

#if 0
    if ( getuid() != 0 ) {
        if ( interactive ) printf( "BIOS not initialized, no access to /dev/mem\n" );
    } else {
        if ( BIOS::Initialize(interp) == false ) {
            Tcl_StaticSetResult( interp, "BIOS::Initialize failed" );
            return TCL_ERROR;
        }
        if ( interactive ) printf( "BIOS initialized\n" );
    }

    if ( access("/proc/xen/privcmd", R_OK) != 0 ) {
        if ( interactive ) printf( "Xen not initialized, no hypervisor present\n" );
    } else {
        if ( Xen::Initialize(interp) == false ) {
            Tcl_StaticSetResult( interp, "Xen::Initialize failed" );
            return TCL_ERROR;
        }
        if ( interactive ) printf( "Xen initialized\n" );
    }

#endif

    if ( Tcl_CallAppInitChain(interp) == false ) {
        // this may want to be additive result
        Tcl_StaticSetResult( interp, "AppInit failed" );
        return TCL_ERROR;
    }

    return TCL_OK;
}

/**
 */
int main( int argc, char **argv ) {
    Tcl_Main( argc, argv, RedX_Init );
}

/* vim: set autoindent expandtab sw=4 : */
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2019 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

#pragma once

#include <stdint.h>

namespace px4
{

class WorkQueue; // forward declaration

struct wq_config_t {
	const char *name;
	uint16_t stacksize;
	int8_t relative_priority; // relative to max
};

namespace wq_configurations
{
static constexpr wq_config_t rate_ctrl{"wq:rate_ctrl", 1664, 0}; // PX4 inner loop highest priority

static constexpr wq_config_t SPI0{"wq:SPI0", 2496, -1};
static constexpr wq_config_t SPI1{"wq:SPI1", 2496, -2};
static constexpr wq_config_t SPI2{"wq:SPI2", 2496, -3};
static constexpr wq_config_t SPI3{"wq:SPI3", 2496, -4};
static constexpr wq_config_t SPI4{"wq:SPI4", 2496, -5};
static constexpr wq_config_t SPI5{"wq:SPI5", 2496, -6};
static constexpr wq_config_t SPI6{"wq:SPI6", 2496, -7};

static constexpr wq_config_t I2C0{"wq:I2C0", 1472, -8};
static constexpr wq_config_t I2C1{"wq:I2C1", 1472, -9};
static constexpr wq_config_t I2C2{"wq:I2C2", 1472, -10};
static constexpr wq_config_t I2C3{"wq:I2C3", 1472, -11};
static constexpr wq_config_t I2C4{"wq:I2C4", 1472, -12};

// PX4 att/pos controllers, highest priority after sensors.
static constexpr wq_config_t attitude_ctrl{"wq:attitude_ctrl", 1600, -13};
static constexpr wq_config_t navigation_and_controllers{"wq:navigation_and_controllers", 7200, -14};

static constexpr wq_config_t hp_default{"wq:hp_default", 1900, -15};

static constexpr wq_config_t uavcan{"wq:uavcan", 3000, -16};

static constexpr wq_config_t UART0{"wq:UART0", 1400, -17};
static constexpr wq_config_t UART1{"wq:UART1", 1400, -18};
static constexpr wq_config_t UART2{"wq:UART2", 1400, -19};
static constexpr wq_config_t UART3{"wq:UART3", 1400, -20};
static constexpr wq_config_t UART4{"wq:UART4", 1400, -21};
static constexpr wq_config_t UART5{"wq:UART5", 1400, -22};
static constexpr wq_config_t UART6{"wq:UART6", 1400, -23};
static constexpr wq_config_t UART7{"wq:UART7", 1400, -24};
static constexpr wq_config_t UART8{"wq:UART8", 1400, -25};
static constexpr wq_config_t UART_UNKNOWN{"wq:UART_UNKNOWN", 1400, -26};

static constexpr wq_config_t lp_default{"wq:lp_default", 1700, -50};

static constexpr wq_config_t test1{"wq:test1", 2000, 0};
static constexpr wq_config_t test2{"wq:test2", 2000, 0};

} // namespace wq_configurations

/**
 * Start the work queue manager task.
 */
int WorkQueueManagerStart();

/**
 * Stop the work queue manager task.
 */
int WorkQueueManagerStop();

/**
 * Work queue manager status.
 */
int WorkQueueManagerStatus();

/**
 * Create (or find) a work queue with a particular configuration.
 *
 * @param new_wq		The work queue configuration (see WorkQueueManager.hpp).
 * @return		A pointer to the WorkQueue, or nullptr on failure.
 */
WorkQueue *WorkQueueFindOrCreate(const wq_config_t &new_wq);

/**
 * Map a PX4 driver device id to a work queue (by sensor bus).
 *
 * @param device_id		The PX4 driver's device id.
 * @return		A work queue configuration.
 */
const wq_config_t &device_bus_to_wq(uint32_t device_id);

/**
 * Map a serial device path (eg /dev/ttyS1) to a work queue.
 *
 * @param device_id		The device path.
 * @return		A work queue configuration.
 */
const wq_config_t &serial_port_to_wq(const char *serial);

} // namespace px4
<commit_msg>wq:attitude_ctrl small stack increase<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2019 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

#pragma once

#include <stdint.h>

namespace px4
{

class WorkQueue; // forward declaration

struct wq_config_t {
	const char *name;
	uint16_t stacksize;
	int8_t relative_priority; // relative to max
};

namespace wq_configurations
{
static constexpr wq_config_t rate_ctrl{"wq:rate_ctrl", 1664, 0}; // PX4 inner loop highest priority

static constexpr wq_config_t SPI0{"wq:SPI0", 2496, -1};
static constexpr wq_config_t SPI1{"wq:SPI1", 2496, -2};
static constexpr wq_config_t SPI2{"wq:SPI2", 2496, -3};
static constexpr wq_config_t SPI3{"wq:SPI3", 2496, -4};
static constexpr wq_config_t SPI4{"wq:SPI4", 2496, -5};
static constexpr wq_config_t SPI5{"wq:SPI5", 2496, -6};
static constexpr wq_config_t SPI6{"wq:SPI6", 2496, -7};

static constexpr wq_config_t I2C0{"wq:I2C0", 1472, -8};
static constexpr wq_config_t I2C1{"wq:I2C1", 1472, -9};
static constexpr wq_config_t I2C2{"wq:I2C2", 1472, -10};
static constexpr wq_config_t I2C3{"wq:I2C3", 1472, -11};
static constexpr wq_config_t I2C4{"wq:I2C4", 1472, -12};

// PX4 att/pos controllers, highest priority after sensors.
static constexpr wq_config_t attitude_ctrl{"wq:attitude_ctrl", 1632, -13};
static constexpr wq_config_t navigation_and_controllers{"wq:navigation_and_controllers", 7200, -14};

static constexpr wq_config_t hp_default{"wq:hp_default", 1900, -15};

static constexpr wq_config_t uavcan{"wq:uavcan", 3000, -16};

static constexpr wq_config_t UART0{"wq:UART0", 1400, -17};
static constexpr wq_config_t UART1{"wq:UART1", 1400, -18};
static constexpr wq_config_t UART2{"wq:UART2", 1400, -19};
static constexpr wq_config_t UART3{"wq:UART3", 1400, -20};
static constexpr wq_config_t UART4{"wq:UART4", 1400, -21};
static constexpr wq_config_t UART5{"wq:UART5", 1400, -22};
static constexpr wq_config_t UART6{"wq:UART6", 1400, -23};
static constexpr wq_config_t UART7{"wq:UART7", 1400, -24};
static constexpr wq_config_t UART8{"wq:UART8", 1400, -25};
static constexpr wq_config_t UART_UNKNOWN{"wq:UART_UNKNOWN", 1400, -26};

static constexpr wq_config_t lp_default{"wq:lp_default", 1700, -50};

static constexpr wq_config_t test1{"wq:test1", 2000, 0};
static constexpr wq_config_t test2{"wq:test2", 2000, 0};

} // namespace wq_configurations

/**
 * Start the work queue manager task.
 */
int WorkQueueManagerStart();

/**
 * Stop the work queue manager task.
 */
int WorkQueueManagerStop();

/**
 * Work queue manager status.
 */
int WorkQueueManagerStatus();

/**
 * Create (or find) a work queue with a particular configuration.
 *
 * @param new_wq		The work queue configuration (see WorkQueueManager.hpp).
 * @return		A pointer to the WorkQueue, or nullptr on failure.
 */
WorkQueue *WorkQueueFindOrCreate(const wq_config_t &new_wq);

/**
 * Map a PX4 driver device id to a work queue (by sensor bus).
 *
 * @param device_id		The PX4 driver's device id.
 * @return		A work queue configuration.
 */
const wq_config_t &device_bus_to_wq(uint32_t device_id);

/**
 * Map a serial device path (eg /dev/ttyS1) to a work queue.
 *
 * @param device_id		The device path.
 * @return		A work queue configuration.
 */
const wq_config_t &serial_port_to_wq(const char *serial);

} // namespace px4
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <cmath>
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::exception;
using std::ofstream;
using std::fixed;
using std::setprecision;
using std::numeric_limits;

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <CLData.hpp>
#include <utils.hpp>
#include <Folding.hpp>
#include <Timer.hpp>
using isa::utils::ArgumentList;
using isa::utils::toStringValue;
using isa::utils::Timer;
using AstroData::Observation;
using isa::OpenCL::initializeOpenCL;
using isa::OpenCL::CLData;
using PulsarSearch::Folding;

typedef float dataType;
const string typeName("float");
const unsigned int maxThreadsPerBlock = 1024;
const unsigned int maxThreadsMultiplier = 512;
const unsigned int maxItemsPerThread = 256;
const unsigned int maxItemsMultiplier = 256;
const unsigned int padding = 32;

// Common parameters
const unsigned int nrBeams = 1;
const unsigned int nrStations = 64;
// LOFAR
/*const float minFreq = 138.965f;
const float channelBandwidth = 0.195f;
const unsigned int nrSamplesPerSecond = 200000;
const unsigned int nrChannels = 32;*/
// Apertif
const float minFreq = 1425.0f;
const float channelBandwidth = 0.2929f;
const unsigned int nrSamplesPerSecond = 20000;
const unsigned int nrChannels = 1024;
// Periods
const unsigned int nrBins = 256;

int main(int argc, char * argv[]) {
	unsigned int lowerNrThreads = 0;
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	Observation< dataType > observation("FoldingTuning", typeName);
	CLData< dataType > * dedispersedData = new CLData< dataType >("DedispersedData", true);
	CLData< dataType > * foldedData = new CLData<dataType >("FoldedData", true);
	CLData< unsigned int > * counterData = new CLData< unsigned int >("CounterData", true);

	try {
		ArgumentList args(argc, argv);

		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		observation.setNrDMs(args.getSwitchArgument< unsigned int >("-dms"));
		lowerNrThreads = args.getSwitchArgument< unsigned int >("-lnt");
		observation.setNrPeriods(args.getSwitchArgument< unsigned int >("-periods"));
	} catch ( exception & err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Setup of the observation
	observation.setPadding(padding);
	observation.setNrSamplesPerSecond(nrSamplesPerSecond);
	observation.setNrBins(nrBins);

	cl::Context * clContext = new cl::Context();
	vector< cl::Platform > * clPlatforms = new vector< cl::Platform >();
	vector< cl::Device > * clDevices = new vector< cl::Device >();
	vector< vector< cl::CommandQueue > > * clQueues = new vector< vector < cl::CommandQueue > >();

	initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	cout << fixed << endl;
	cout << "# nrDMs nrPeriods nrDMsPerBlock nrPeriodsPerBlock nrBinsPerBlock nrDMsPerThread nrPeriodsPerThread nrBinsPerThread GFLOP/s err time err" << endl << endl;

	// Allocate memory
	dedispersedData->allocateHostData(observation.getNrSamplesPerSecond() * observation.getNrPaddedDMs());
	foldedData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
	foldedData->blankHostData();
	counterData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
	counterData->blankHostData();

	dedispersedData->setCLContext(clContext);
	dedispersedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	foldedData->setCLContext(clContext);
	foldedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	counterData->setCLContext(clContext);
	counterData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));

	try {
		dedispersedData->allocateDeviceData();
		foldedData->allocateDeviceData();
		foldedData->copyHostToDevice();
		counterData->allocateDeviceData();
		counterData->copyHostToDevice();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
	}

	// Find the parameters
	vector< vector< unsigned int > > configurations;
	for ( unsigned int DMsPerBlock = lowerNrThreads; DMsPerBlock <= maxThreadsPerBlock; DMsPerBlock++ ) {
		if ( observation.getNrDMs() % DMsPerBlock != 0 ) {
			continue;
		}

		for ( unsigned int periodsPerBlock = 1; periodsPerBlock <= maxThreadsMultiplier; periodsPerBlock++ ) {
			if ( observation.getNrPeriods() % periodsPerBlock != 0 ) {
				continue;
			} else if ( DMsPerBlock * periodsPerBlock > maxThreadsPerBlock ) {
				break;
			}

			for ( unsigned int binsPerBlock = 1; binsPerBlock <= maxThreadsMultiplier; binsPerBlock++ ) {
				if ( observation.getNrBins() % binsPerBlock != 0 ) {
					continue;
				} else if ( DMsPerBlock * periodsPerBlock * binsPerBlock > maxThreadsPerBlock ) {
					break;
				}

				for ( unsigned int DMsPerThread = 1; DMsPerThread <= maxItemsPerThread; DMsPerThread++ ) {
					if ( observation.getNrDMs() % (DMsPerBlock * DMsPerThread) != 0 ) {
						continue;
					}

					for ( unsigned int periodsPerThread = 1; periodsPerThread <= maxItemsMultiplier; periodsPerThread++ ) {
						if ( observation.getNrPeriods() % (periodsPerBlock * periodsPerThread) != 0 ) {
							continue;
						} else if ( DMsPerThread * periodsPerThread > maxItemsPerThread ) {
							break;
						}

						for ( unsigned int binsPerThread = 1; binsPerThread <= maxItemsMultiplier; binsPerThread++ ) {
							if ( observation.getNrBins() % (binsPerBlock * binsPerThread) != 0 ) {
								continue;
							} else if ( DMsPerThread * periodsPerThread * binsPerThread > maxItemsPerThread ) {
								break;
							}

							vector< unsigned int > parameters;

							parameters.push_back(DMsPerBlock);
							parameters.push_back(periodsPerBlock);
							parameters.push_back(binsPerBlock);
							parameters.push_back(DMsPerThread);
							parameters.push_back(periodsPerThread);
							parameters.push_back(binsPerThread);

							configurations.push_back(parameters);
						}
					}
				}
			}
		}
	}

	for ( vector< vector< unsigned int > >::const_iterator parameters = configurations.begin(); parameters != configurations.end(); parameters++ ) {
		double Acur = 0.0;
		double Aold = 0.0;
		double Vcur = 0.0;
		double Vold = 0.0;

		try {
			// Generate kernel
			Folding< dataType > clFold("clFold", typeName);
			clFold.bindOpenCL(clContext, &(clDevices->at(clDeviceID)), &((clQueues->at(clDeviceID)).at(0)));
			clFold.setObservation(&observation);
			clFold.setNrDMsPerBlock((*parameters)[0]);
			clFold.setNrPeriodsPerBlock((*parameters)[1]);
			clFold.setNrBinsPerBlock((*parameters)[2]);
			clFold.setNrDMsPerThread((*parameters)[3]);
			clFold.setNrPeriodsPerThread((*parameters)[4]);
			clFold.setNrBinsPerThread((*parameters)[5]);
			clFold.generateCode();

			clFold(dedispersedData, foldedData, counterData);
			(clFold.getTimer()).reset();
			for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
				clFold(dedispersedData, foldedData, counterData);

				if ( iteration == 0 ) {
					Acur = clFold.getGFLOP() / clFold.getTimer().getLastRunTime();
				} else {
					Aold = Acur;
					Vold = Vcur;

					Acur = Aold + (((clFold.getGFLOP() / clFold.getTimer().getLastRunTime()) - Aold) / (iteration + 1));
					Vcur = Vold + (((clFold.getGFLOP() / clFold.getTimer().getLastRunTime()) - Aold) * ((clFold.getGFLOP() / clFold.getTimer().getLastRunTime()) - Acur));
				}
			}
			Vcur = sqrt(Vcur / nrIterations);

			cout << observation.getNrDMs() << " " << observation.getNrPeriods() << " " << (*parameters)[0] << " " << (*parameters)[1] << " " << (*parameters)[2] << " " << (*parameters)[3] << " " << (*parameters)[4] << " " << (*parameters)[5] << " " << setprecision(3) << Acur << " " << Vcur << " " << setprecision(6) << clFold.getTimer().getAverageTime() << " " << clFold.getTimer().getStdDev() << endl;
		} catch ( OpenCLError err ) {
			cerr << err.what() << endl;
			continue;
		}
	}

	cout << endl;

	return 0;
}
<commit_msg>Fixed the formula to compute the number of registers necessary.<commit_after>/*
 * Copyright (C) 2013
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <cmath>
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::exception;
using std::ofstream;
using std::fixed;
using std::setprecision;
using std::numeric_limits;

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <CLData.hpp>
#include <utils.hpp>
#include <Folding.hpp>
#include <Timer.hpp>
using isa::utils::ArgumentList;
using isa::utils::toStringValue;
using isa::utils::Timer;
using AstroData::Observation;
using isa::OpenCL::initializeOpenCL;
using isa::OpenCL::CLData;
using PulsarSearch::Folding;

typedef float dataType;
const string typeName("float");
const unsigned int maxThreadsPerBlock = 1024;
const unsigned int maxThreadsMultiplier = 512;
const unsigned int maxItemsPerThread = 256;
const unsigned int maxItemsMultiplier = 256;
const unsigned int padding = 32;

// Common parameters
const unsigned int nrBeams = 1;
const unsigned int nrStations = 64;
// LOFAR
/*const float minFreq = 138.965f;
const float channelBandwidth = 0.195f;
const unsigned int nrSamplesPerSecond = 200000;
const unsigned int nrChannels = 32;*/
// Apertif
const float minFreq = 1425.0f;
const float channelBandwidth = 0.2929f;
const unsigned int nrSamplesPerSecond = 20000;
const unsigned int nrChannels = 1024;
// Periods
const unsigned int nrBins = 256;

int main(int argc, char * argv[]) {
	unsigned int lowerNrThreads = 0;
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	Observation< dataType > observation("FoldingTuning", typeName);
	CLData< dataType > * dedispersedData = new CLData< dataType >("DedispersedData", true);
	CLData< dataType > * foldedData = new CLData<dataType >("FoldedData", true);
	CLData< unsigned int > * counterData = new CLData< unsigned int >("CounterData", true);

	try {
		ArgumentList args(argc, argv);

		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		observation.setNrDMs(args.getSwitchArgument< unsigned int >("-dms"));
		lowerNrThreads = args.getSwitchArgument< unsigned int >("-lnt");
		observation.setNrPeriods(args.getSwitchArgument< unsigned int >("-periods"));
	} catch ( exception & err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Setup of the observation
	observation.setPadding(padding);
	observation.setNrSamplesPerSecond(nrSamplesPerSecond);
	observation.setNrBins(nrBins);

	cl::Context * clContext = new cl::Context();
	vector< cl::Platform > * clPlatforms = new vector< cl::Platform >();
	vector< cl::Device > * clDevices = new vector< cl::Device >();
	vector< vector< cl::CommandQueue > > * clQueues = new vector< vector < cl::CommandQueue > >();

	initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	cout << fixed << endl;
	cout << "# nrDMs nrPeriods nrDMsPerBlock nrPeriodsPerBlock nrBinsPerBlock nrDMsPerThread nrPeriodsPerThread nrBinsPerThread GFLOP/s err time err" << endl << endl;

	// Allocate memory
	dedispersedData->allocateHostData(observation.getNrSamplesPerSecond() * observation.getNrPaddedDMs());
	foldedData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
	foldedData->blankHostData();
	counterData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
	counterData->blankHostData();

	dedispersedData->setCLContext(clContext);
	dedispersedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	foldedData->setCLContext(clContext);
	foldedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	counterData->setCLContext(clContext);
	counterData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));

	try {
		dedispersedData->allocateDeviceData();
		foldedData->allocateDeviceData();
		foldedData->copyHostToDevice();
		counterData->allocateDeviceData();
		counterData->copyHostToDevice();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
	}

	// Find the parameters
	vector< vector< unsigned int > > configurations;
	for ( unsigned int DMsPerBlock = lowerNrThreads; DMsPerBlock <= maxThreadsPerBlock; DMsPerBlock++ ) {
		if ( observation.getNrDMs() % DMsPerBlock != 0 ) {
			continue;
		}

		for ( unsigned int periodsPerBlock = 1; periodsPerBlock <= maxThreadsMultiplier; periodsPerBlock++ ) {
			if ( observation.getNrPeriods() % periodsPerBlock != 0 ) {
				continue;
			} else if ( DMsPerBlock * periodsPerBlock > maxThreadsPerBlock ) {
				break;
			}

			for ( unsigned int binsPerBlock = 1; binsPerBlock <= maxThreadsMultiplier; binsPerBlock++ ) {
				if ( observation.getNrBins() % binsPerBlock != 0 ) {
					continue;
				} else if ( DMsPerBlock * periodsPerBlock * binsPerBlock > maxThreadsPerBlock ) {
					break;
				}

				for ( unsigned int DMsPerThread = 1; DMsPerThread <= maxItemsPerThread; DMsPerThread++ ) {
					if ( observation.getNrDMs() % (DMsPerBlock * DMsPerThread) != 0 ) {
						continue;
					}

					for ( unsigned int periodsPerThread = 1; periodsPerThread <= maxItemsMultiplier; periodsPerThread++ ) {
						if ( observation.getNrPeriods() % (periodsPerBlock * periodsPerThread) != 0 ) {
							continue;
						} else if ( (DMsPerThread + (2 * periodsPerThread)) + (2 * DMsPerThread * periodsPerThread) > maxItemsPerThread ) {
							break;
						}

						for ( unsigned int binsPerThread = 1; binsPerThread <= maxItemsMultiplier; binsPerThread++ ) {
							if ( observation.getNrBins() % (binsPerBlock * binsPerThread) != 0 ) {
								continue;
							} else if ( (DMsPerThread + (2 * periodsPerThread) + binsPerThread) + (2 * DMsPerThread * periodsPerThread * binsPerThread) > maxItemsPerThread ) {
								break;
							}

							vector< unsigned int > parameters;

							parameters.push_back(DMsPerBlock);
							parameters.push_back(periodsPerBlock);
							parameters.push_back(binsPerBlock);
							parameters.push_back(DMsPerThread);
							parameters.push_back(periodsPerThread);
							parameters.push_back(binsPerThread);

							configurations.push_back(parameters);
						}
					}
				}
			}
		}
	}

	for ( vector< vector< unsigned int > >::const_iterator parameters = configurations.begin(); parameters != configurations.end(); parameters++ ) {
		double Acur = 0.0;
		double Aold = 0.0;
		double Vcur = 0.0;
		double Vold = 0.0;

		try {
			// Generate kernel
			Folding< dataType > clFold("clFold", typeName);
			clFold.bindOpenCL(clContext, &(clDevices->at(clDeviceID)), &((clQueues->at(clDeviceID)).at(0)));
			clFold.setObservation(&observation);
			clFold.setNrDMsPerBlock((*parameters)[0]);
			clFold.setNrPeriodsPerBlock((*parameters)[1]);
			clFold.setNrBinsPerBlock((*parameters)[2]);
			clFold.setNrDMsPerThread((*parameters)[3]);
			clFold.setNrPeriodsPerThread((*parameters)[4]);
			clFold.setNrBinsPerThread((*parameters)[5]);
			clFold.generateCode();

			clFold(dedispersedData, foldedData, counterData);
			(clFold.getTimer()).reset();
			for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
				clFold(dedispersedData, foldedData, counterData);

				if ( iteration == 0 ) {
					Acur = clFold.getGFLOP() / clFold.getTimer().getLastRunTime();
				} else {
					Aold = Acur;
					Vold = Vcur;

					Acur = Aold + (((clFold.getGFLOP() / clFold.getTimer().getLastRunTime()) - Aold) / (iteration + 1));
					Vcur = Vold + (((clFold.getGFLOP() / clFold.getTimer().getLastRunTime()) - Aold) * ((clFold.getGFLOP() / clFold.getTimer().getLastRunTime()) - Acur));
				}
			}
			Vcur = sqrt(Vcur / nrIterations);

			cout << observation.getNrDMs() << " " << observation.getNrPeriods() << " " << (*parameters)[0] << " " << (*parameters)[1] << " " << (*parameters)[2] << " " << (*parameters)[3] << " " << (*parameters)[4] << " " << (*parameters)[5] << " " << setprecision(3) << Acur << " " << Vcur << " " << setprecision(6) << clFold.getTimer().getAverageTime() << " " << clFold.getTimer().getStdDev() << endl;
		} catch ( OpenCLError err ) {
			cerr << err.what() << endl;
			continue;
		}
	}

	cout << endl;

	return 0;
}
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file rlp.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * RLP test functions.
 */

#include <fstream>
#include <sstream>
#include <libdevcore/Log.h>
#include <libdevcore/RLP.h>
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
#include <boost/test/unit_test.hpp>
#include <algorithm>
#include "JsonSpiritHeaders.h"

using namespace std;
using namespace dev;
namespace js = json_spirit;

namespace dev
{
	namespace test
	{
		static void buildRLP(js::mValue& _v, RLPStream& _rlp)
		{
			if (_v.type() == js::array_type)
			{
				RLPStream s;
				for (auto& i: _v.get_array())
					buildRLP(i, s);
				_rlp.appendList(s.out());
			}
			else if (_v.type() == js::int_type)
				_rlp.append(_v.get_uint64());
			else if (_v.type() == js::str_type)
			{
				auto s = _v.get_str();
				if (s.size() && s[0] == '#')
					_rlp.append(bigint(s.substr(1)));
				else
					_rlp.append(s);
			}
		}

		static void getRLPTestCases(js::mValue& v)
		{
			string s = asString(contents("../../../tests/rlptest.json"));
			BOOST_REQUIRE_MESSAGE( s.length() > 0,
				"Contents of 'rlptest.json' is empty. Have you cloned the 'tests' repo branch develop?");
			js::read_string(s, v);
		}

		static void checkRLPTestCase(js::mObject& o)
		{
			BOOST_REQUIRE( o.count("in") > 0 );
			BOOST_REQUIRE( o.count("out") > 0 );
			BOOST_REQUIRE(!o["out"].is_null());
		}

		static void checkRLPAgainstJson(js::mValue& v, RLP& u)
		{
			if ( v.type() == js::str_type )
			{
				const std::string& expectedText = v.get_str();
				if ( expectedText.front() == '#' )
				{
					// Deal with bigint instead of a raw string
					std::string bigIntStr = expectedText.substr(1,expectedText.length()-1);
					std::stringstream bintStream(bigIntStr);
					bigint val;
					bintStream >> val;
					BOOST_CHECK( !u.isList() );
					BOOST_CHECK( !u.isNull() );
					BOOST_CHECK( u );             // operator bool()
					BOOST_CHECK(u == val);
				}
				else
				{
					BOOST_CHECK( !u.isList() );
					BOOST_CHECK( !u.isNull() );
					BOOST_CHECK( u.isData() );
					BOOST_CHECK( u );
					BOOST_CHECK( u.size() == expectedText.length() );
					BOOST_CHECK(u == expectedText);
				}
			}
			else if ( v.type() == js::int_type )
			{
				const int expectedValue = v.get_int();
				BOOST_CHECK( u.isInt() );
				BOOST_CHECK( !u.isList() );
				BOOST_CHECK( !u.isNull() );
				BOOST_CHECK( u );             // operator bool()
				BOOST_CHECK(u == expectedValue);
			}
			else if ( v.type() == js::array_type )
			{
				BOOST_CHECK( u.isList() );
				BOOST_CHECK( !u.isInt() );
				BOOST_CHECK( !u.isData() );
				js::mArray& arr = v.get_array();
				BOOST_CHECK( u.itemCount() == arr.size() );
				unsigned i;
				for( i = 0; i < arr.size(); i++ )
				{
					RLP item = u[i];
					checkRLPAgainstJson(arr[i], item);
				}
			}
			else
			{
				BOOST_ERROR("Invalid Javascript object!");
			}

		}
	}
}

BOOST_AUTO_TEST_CASE(rlp_encoding_test)
{
	cnote << "Testing RLP Encoding...";
	js::mValue v;
	dev::test::getRLPTestCases(v);

	for (auto& i: v.get_obj())
	{
		js::mObject& o = i.second.get_obj();
		cnote << i.first;
		dev::test::checkRLPTestCase(o);

		RLPStream s;
		dev::test::buildRLP(o["in"], s);

		std::string expectedText(o["out"].get_str());
		std::transform(expectedText.begin(), expectedText.end(), expectedText.begin(), ::tolower );

		const std::string& computedText = toHex(s.out());

		std::stringstream msg;
		msg << "Encoding Failed: expected: " << expectedText << std::endl;
		msg << " But Computed: " << computedText;

		BOOST_CHECK_MESSAGE(
			expectedText == computedText,
			msg.str()
			);
	}

}

BOOST_AUTO_TEST_CASE(rlp_decoding_test)
{
	cnote << "Testing RLP decoding...";
	// Uses the same test cases as encoding but in reverse.
	// We read into the string of hex values, convert to bytes,
	// and then compare the output structure to the json of the
	// input object.
	js::mValue v;
	dev::test::getRLPTestCases(v);
	for (auto& i: v.get_obj())
	{
		js::mObject& o = i.second.get_obj();
		cnote << i.first;
		dev::test::checkRLPTestCase(o);

		js::mValue& inputData = o["in"];
		bytes payloadToDecode = fromHex(o["out"].get_str());

		RLP payload(payloadToDecode);

		dev::test::checkRLPAgainstJson(inputData, payload);

	}
}

<commit_msg>test/rlp bugfix: expectedText can be empty<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file rlp.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * RLP test functions.
 */

#include <fstream>
#include <sstream>
#include <libdevcore/Log.h>
#include <libdevcore/RLP.h>
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
#include <boost/test/unit_test.hpp>
#include <algorithm>
#include "JsonSpiritHeaders.h"

using namespace std;
using namespace dev;
namespace js = json_spirit;

namespace dev
{
	namespace test
	{
		static void buildRLP(js::mValue& _v, RLPStream& _rlp)
		{
			if (_v.type() == js::array_type)
			{
				RLPStream s;
				for (auto& i: _v.get_array())
					buildRLP(i, s);
				_rlp.appendList(s.out());
			}
			else if (_v.type() == js::int_type)
				_rlp.append(_v.get_uint64());
			else if (_v.type() == js::str_type)
			{
				auto s = _v.get_str();
				if (s.size() && s[0] == '#')
					_rlp.append(bigint(s.substr(1)));
				else
					_rlp.append(s);
			}
		}

		static void getRLPTestCases(js::mValue& v)
		{
			string s = asString(contents("../../../tests/rlptest.json"));
			BOOST_REQUIRE_MESSAGE( s.length() > 0,
				"Contents of 'rlptest.json' is empty. Have you cloned the 'tests' repo branch develop?");
			js::read_string(s, v);
		}

		static void checkRLPTestCase(js::mObject& o)
		{
			BOOST_REQUIRE( o.count("in") > 0 );
			BOOST_REQUIRE( o.count("out") > 0 );
			BOOST_REQUIRE(!o["out"].is_null());
		}

		static void checkRLPAgainstJson(js::mValue& v, RLP& u)
		{
			if ( v.type() == js::str_type )
			{
				const std::string& expectedText = v.get_str();
				if ( !expectedText.empty() && expectedText.front() == '#' )
				{
					// Deal with bigint instead of a raw string
					std::string bigIntStr = expectedText.substr(1,expectedText.length()-1);
					std::stringstream bintStream(bigIntStr);
					bigint val;
					bintStream >> val;
					BOOST_CHECK( !u.isList() );
					BOOST_CHECK( !u.isNull() );
					BOOST_CHECK( u );             // operator bool()
					BOOST_CHECK(u == val);
				}
				else
				{
					BOOST_CHECK( !u.isList() );
					BOOST_CHECK( !u.isNull() );
					BOOST_CHECK( u.isData() );
					BOOST_CHECK( u );
					BOOST_CHECK( u.size() == expectedText.length() );
					BOOST_CHECK(u == expectedText);
				}
			}
			else if ( v.type() == js::int_type )
			{
				const int expectedValue = v.get_int();
				BOOST_CHECK( u.isInt() );
				BOOST_CHECK( !u.isList() );
				BOOST_CHECK( !u.isNull() );
				BOOST_CHECK( u );             // operator bool()
				BOOST_CHECK(u == expectedValue);
			}
			else if ( v.type() == js::array_type )
			{
				BOOST_CHECK( u.isList() );
				BOOST_CHECK( !u.isInt() );
				BOOST_CHECK( !u.isData() );
				js::mArray& arr = v.get_array();
				BOOST_CHECK( u.itemCount() == arr.size() );
				unsigned i;
				for( i = 0; i < arr.size(); i++ )
				{
					RLP item = u[i];
					checkRLPAgainstJson(arr[i], item);
				}
			}
			else
			{
				BOOST_ERROR("Invalid Javascript object!");
			}

		}
	}
}

BOOST_AUTO_TEST_CASE(rlp_encoding_test)
{
	cnote << "Testing RLP Encoding...";
	js::mValue v;
	dev::test::getRLPTestCases(v);

	for (auto& i: v.get_obj())
	{
		js::mObject& o = i.second.get_obj();
		cnote << i.first;
		dev::test::checkRLPTestCase(o);

		RLPStream s;
		dev::test::buildRLP(o["in"], s);

		std::string expectedText(o["out"].get_str());
		std::transform(expectedText.begin(), expectedText.end(), expectedText.begin(), ::tolower );

		const std::string& computedText = toHex(s.out());

		std::stringstream msg;
		msg << "Encoding Failed: expected: " << expectedText << std::endl;
		msg << " But Computed: " << computedText;

		BOOST_CHECK_MESSAGE(
			expectedText == computedText,
			msg.str()
			);
	}

}

BOOST_AUTO_TEST_CASE(rlp_decoding_test)
{
	cnote << "Testing RLP decoding...";
	// Uses the same test cases as encoding but in reverse.
	// We read into the string of hex values, convert to bytes,
	// and then compare the output structure to the json of the
	// input object.
	js::mValue v;
	dev::test::getRLPTestCases(v);
	for (auto& i: v.get_obj())
	{
		js::mObject& o = i.second.get_obj();
		cnote << i.first;
		dev::test::checkRLPTestCase(o);

		js::mValue& inputData = o["in"];
		bytes payloadToDecode = fromHex(o["out"].get_str());

		RLP payload(payloadToDecode);

		dev::test::checkRLPAgainstJson(inputData, payload);

	}
}

<|endoftext|>


<commit_before>/*
flink.cpp

 ࠧ 㭪権  ࠡ⪥ Link` - Hard&Sym

*/

/* Revision: 1.04 05.01.2001 $ */

/*
Modify:
  05.01.2001 SVS
    + 㭪 GetSubstName - ॥堫  mix.cpp
    + 㭪 DelSubstDrive - 㤠 Subst ࠩ
  05.01.2000 OT
    - ᬥ⨪, - ன    VC :)
  04.01.2001 SVS
    + 誨  CreateJunctionPoint, DeleteJunctionPoint
    + GetJunctionPointInfo -    Junc
  03.01.2001 SVS
    ! 뤥  ⢥ ᠬ⥫쭮
    + GetNumberOfLinks  MkLink ॥堫  mix.cpp
*/

#include "headers.hpp"
#pragma hdrstop

#include "internalheaders.hpp"

//#if defined(__BORLANDC__)
// current thread's ANSI code page
  #define CP_THREAD_ACP             3

  #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE      ( 16 * 1024 )
  // Predefined reparse tags.
  // These tags need to avoid conflicting with IO_REMOUNT defined in ntos\inc\io.h
  #define IO_REPARSE_TAG_RESERVED_ZERO             (0)
  #define IO_REPARSE_TAG_RESERVED_ONE              (1)

  // The value of the following constant needs to satisfy the following conditions:
  //  (1) Be at least as large as the largest of the reserved tags.
  //  (2) Be strictly smaller than all the tags in use.
  #define IO_REPARSE_TAG_RESERVED_RANGE            IO_REPARSE_TAG_RESERVED_ONE
  // The following constant represents the bits that are valid to use in
  // reparse tags.
  #define IO_REPARSE_TAG_VALID_VALUES     (0xE000FFFF)
  // Macro to determine whether a reparse tag is a valid tag.
  #define IsReparseTagValid(_tag) (                               \
                    !((_tag) & ~IO_REPARSE_TAG_VALID_VALUES) &&   \
                    ((_tag) > IO_REPARSE_TAG_RESERVED_RANGE)      \
                   )
  #define FILE_FLAG_OPEN_REPARSE_POINT    0x00200000
  #define FSCTL_GET_REPARSE_POINT         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
// REPARSE_DATA_BUFFER
//#endif
struct TMN_REPARSE_DATA_BUFFER
{
  DWORD  ReparseTag;
  WORD   ReparseDataLength;
  WORD   Reserved;

  // IO_REPARSE_TAG_MOUNT_POINT specifics follow
  WORD   SubstituteNameOffset;
  WORD   SubstituteNameLength;
  WORD   PrintNameOffset;
  WORD   PrintNameLength;
  WCHAR  PathBuffer[1];

  // Some helper functions
  //BOOL Init(LPCSTR szJunctionPoint);
  //BOOL Init(LPCWSTR wszJunctionPoint);
  //int BytesForIoControl() const;
};

BOOL WINAPI CreateJunctionPoint(LPCTSTR szMountDir, LPCTSTR szDestDirArg)
{
  return TRUE;
}

BOOL WINAPI DeleteJunctionPoint(LPCTSTR szDir)
{
  return TRUE;
}

DWORD WINAPI GetJunctionPointInfo(LPCTSTR szMountDir,
              LPTSTR  szDestBuff,
              DWORD   dwBuffSize)
{
  const DWORD FileAttr = GetFileAttributes(szMountDir);
  if (FileAttr == 0xffffffff || !(FileAttr & FILE_ATTRIBUTE_REPARSE_POINT))
  {
    SetLastError(ERROR_PATH_NOT_FOUND);
    return 0;
  }

  HANDLE hDir=CreateFile(szMountDir,GENERIC_READ|0,0,0,OPEN_EXISTING,
          FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,0);

  if (hDir == INVALID_HANDLE_VALUE)
  {
    SetLastError(ERROR_PATH_NOT_FOUND);
    return 0;
  }

  char szBuff[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
  TMN_REPARSE_DATA_BUFFER& rdb = *(TMN_REPARSE_DATA_BUFFER*)szBuff;

  DWORD dwBytesReturned;
  if (!DeviceIoControl(hDir,
            FSCTL_GET_REPARSE_POINT,
            NULL,
            0,
            (LPVOID)&rdb,
            MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
            &dwBytesReturned,
            0) ||
    !IsReparseTagValid(rdb.ReparseTag))
  {
    CloseHandle(hDir);
    return 0;
  }

  CloseHandle(hDir);

  if (dwBuffSize < rdb.SubstituteNameLength / sizeof(TCHAR) + sizeof(TCHAR))
  {
    return rdb.SubstituteNameLength / sizeof(TCHAR) + sizeof(TCHAR);
  }

#ifdef UNICODE
  lstrcpy(szDestBuff, rdb.PathBuffer);
#else
  if (!WideCharToMultiByte(CP_THREAD_ACP,
              0,
              rdb.PathBuffer,
              rdb.SubstituteNameLength / sizeof(WCHAR) + 1,
              szDestBuff,
              dwBuffSize,
              "",
              FALSE))
  {
    //printf("WideCharToMultiByte failed (%d)\n", GetLastError());
    return 0;
  }
#endif
  return rdb.SubstituteNameLength / sizeof(TCHAR);
}

/* $ 07.09.2000 SVS
   㭪 GetNumberOfLinks ⮦ 㯭  :-)
*/
int WINAPI GetNumberOfLinks(char *Name)
{
  HANDLE hFile=CreateFile(Name,0,FILE_SHARE_READ|FILE_SHARE_WRITE,
                          NULL,OPEN_EXISTING,0,NULL);
  if (hFile==INVALID_HANDLE_VALUE)
    return(1);
  BY_HANDLE_FILE_INFORMATION bhfi;
  int GetCode=GetFileInformationByHandle(hFile,&bhfi);
  CloseHandle(hFile);
  return(GetCode ? bhfi.nNumberOfLinks:0);
}
/* SVS $*/

#if defined(__BORLANDC__)
#pragma option -a4
#endif
int WINAPI MkLink(char *Src,char *Dest)
{
  struct CORRECTED_WIN32_STREAM_ID
  {
    DWORD          dwStreamId ;
    DWORD          dwStreamAttributes ;
    LARGE_INTEGER  Size ;
    DWORD          dwStreamNameSize ;
    WCHAR          cStreamName[ ANYSIZE_ARRAY ] ;
  } StreamId;

  char FileSource[NM],FileDest[NM];
  WCHAR FileLink[NM];

  HANDLE hFileSource;

  DWORD dwBytesWritten;
  LPVOID lpContext;
  DWORD cbPathLen;
  DWORD StreamSize;

  BOOL bSuccess;

//  ConvertNameToFull(Src,FileSource, sizeof(FileSource));
  if (ConvertNameToFull(Src,FileSource, sizeof(FileSource)) >= sizeof(FileSource)){
    return FALSE;
  }
//  ConvertNameToFull(Dest,FileDest, sizeof(FileDest));
  if (ConvertNameToFull(Dest,FileDest, sizeof(FileDest)) >= sizeof(FileDest)){
    return FALSE;
  }
  MultiByteToWideChar(CP_OEMCP,0,FileDest,-1,FileLink,sizeof(FileLink)/sizeof(FileLink[0]));

  hFileSource = CreateFile(FileSource,FILE_WRITE_ATTRIBUTES,
                FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);

  if(hFileSource == INVALID_HANDLE_VALUE)
    return(FALSE);

  lpContext = NULL;
  cbPathLen = (lstrlenW(FileLink) + 1) * sizeof(WCHAR);

  StreamId.dwStreamId = BACKUP_LINK;
  StreamId.dwStreamAttributes = 0;
  StreamId.dwStreamNameSize = 0;
  StreamId.Size.u.HighPart = 0;
  StreamId.Size.u.LowPart = cbPathLen;

  StreamSize=sizeof(StreamId)-sizeof(WCHAR **)+StreamId.dwStreamNameSize;

  bSuccess = BackupWrite(hFileSource,(LPBYTE)&StreamId,StreamSize,
             &dwBytesWritten,FALSE,FALSE,&lpContext);

  int LastError=0;

  if (bSuccess)
  {
    bSuccess = BackupWrite(hFileSource,(LPBYTE)FileLink,cbPathLen,
                &dwBytesWritten,FALSE,FALSE,&lpContext);
    if (!bSuccess)
      LastError=GetLastError();

    BackupWrite(hFileSource,NULL,0,&dwBytesWritten,TRUE,FALSE,&lpContext);
  }
  else
    LastError=GetLastError();

  CloseHandle(hFileSource);

  if (LastError)
    SetLastError(LastError);

  return(bSuccess);
}
#if defined(__BORLANDC__)
#pragma option -a.
#endif

/* $ 05.01.2001 SVS
   㭪 DelSubstDrive - 㤠 Subst ࠩ
   Return: -1 -    SUBST-ࠩ,  OS  .
            0 -  㤠
            1 - 訡  㤠.
*/
int DelSubstDrive(char *DosDeviceName)
{
  if (WinVer.dwPlatformId==VER_PLATFORM_WIN32_NT)
  {
    char NtDeviceName[512];
    if (QueryDosDevice(DosDeviceName,NtDeviceName,sizeof(NtDeviceName))==0)
      return(-1);
    if (strncmp(NtDeviceName,"\\??\\",4)!=0)
      return(-1);
    return !DefineDosDevice(DDD_RAW_TARGET_PATH|
                       DDD_REMOVE_DEFINITION|
                       DDD_EXACT_MATCH_ON_REMOVE,
                       DosDeviceName, NtDeviceName)?1:0;
  }
  return(-1);
}
/* SVS $ */

BOOL GetSubstName(char *LocalName,char *SubstName,int SubstSize)
{
  if (WinVer.dwPlatformId==VER_PLATFORM_WIN32_NT)
  {
    char Name[512]="";
    if (QueryDosDevice(LocalName,Name,sizeof(Name))==0)
      return(FALSE);
    if (strncmp(Name,"\\??\\",4)!=0)
      return(FALSE);
    strncpy(SubstName,Name+4,SubstSize);
    return(TRUE);
  }
  return(FALSE);
}

<commit_msg>FAR patch 00404.SUBST_98 Дата              : 25.01.2001 Сделал            : Valentin Skirdin Описание          : SUBST in Win98 Измененные файлы  : flink.cpp Состав            : 00404.SUBST_98.txt                     flink.cpp.404.diff Основан на патче  : 403 Дополнение        :<commit_after>/*
flink.cpp

 ࠧ 㭪権  ࠡ⪥ Link` - Hard&Sym

*/

/* Revision: 1.05 25.01.2001 $ */

/*
Modify:
  25.01.2001 SVS
    ! 㭪樨 GetSubstName  DelSubstDrive ⥯ ଠ쭮 ࠡ
      Windows98
  05.01.2001 SVS
    + 㭪 GetSubstName - ॥堫  mix.cpp
    + 㭪 DelSubstDrive - 㤠 Subst ࠩ
  05.01.2000 OT
    - ᬥ⨪, - ன    VC :)
  04.01.2001 SVS
    + 誨  CreateJunctionPoint, DeleteJunctionPoint
    + GetJunctionPointInfo -    Junc
  03.01.2001 SVS
    ! 뤥  ⢥ ᠬ⥫쭮
    + GetNumberOfLinks  MkLink ॥堫  mix.cpp
*/

#include "headers.hpp"
#pragma hdrstop

#include "internalheaders.hpp"

//#if defined(__BORLANDC__)
// current thread's ANSI code page
  #define CP_THREAD_ACP             3

  #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE      ( 16 * 1024 )
  // Predefined reparse tags.
  // These tags need to avoid conflicting with IO_REMOUNT defined in ntos\inc\io.h
  #define IO_REPARSE_TAG_RESERVED_ZERO             (0)
  #define IO_REPARSE_TAG_RESERVED_ONE              (1)

  // The value of the following constant needs to satisfy the following conditions:
  //  (1) Be at least as large as the largest of the reserved tags.
  //  (2) Be strictly smaller than all the tags in use.
  #define IO_REPARSE_TAG_RESERVED_RANGE            IO_REPARSE_TAG_RESERVED_ONE
  // The following constant represents the bits that are valid to use in
  // reparse tags.
  #define IO_REPARSE_TAG_VALID_VALUES     (0xE000FFFF)
  // Macro to determine whether a reparse tag is a valid tag.
  #define IsReparseTagValid(_tag) (                               \
                    !((_tag) & ~IO_REPARSE_TAG_VALID_VALUES) &&   \
                    ((_tag) > IO_REPARSE_TAG_RESERVED_RANGE)      \
                   )
  #define FILE_FLAG_OPEN_REPARSE_POINT    0x00200000
  #define FSCTL_GET_REPARSE_POINT         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
// REPARSE_DATA_BUFFER
//#endif
struct TMN_REPARSE_DATA_BUFFER
{
  DWORD  ReparseTag;
  WORD   ReparseDataLength;
  WORD   Reserved;

  // IO_REPARSE_TAG_MOUNT_POINT specifics follow
  WORD   SubstituteNameOffset;
  WORD   SubstituteNameLength;
  WORD   PrintNameOffset;
  WORD   PrintNameLength;
  WCHAR  PathBuffer[1];

  // Some helper functions
  //BOOL Init(LPCSTR szJunctionPoint);
  //BOOL Init(LPCWSTR wszJunctionPoint);
  //int BytesForIoControl() const;
};

BOOL WINAPI CreateJunctionPoint(LPCTSTR szMountDir, LPCTSTR szDestDirArg)
{
  return TRUE;
}

BOOL WINAPI DeleteJunctionPoint(LPCTSTR szDir)
{
  return TRUE;
}

DWORD WINAPI GetJunctionPointInfo(LPCTSTR szMountDir,
              LPTSTR  szDestBuff,
              DWORD   dwBuffSize)
{
  const DWORD FileAttr = GetFileAttributes(szMountDir);
  if (FileAttr == 0xffffffff || !(FileAttr & FILE_ATTRIBUTE_REPARSE_POINT))
  {
    SetLastError(ERROR_PATH_NOT_FOUND);
    return 0;
  }

  HANDLE hDir=CreateFile(szMountDir,GENERIC_READ|0,0,0,OPEN_EXISTING,
          FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,0);

  if (hDir == INVALID_HANDLE_VALUE)
  {
    SetLastError(ERROR_PATH_NOT_FOUND);
    return 0;
  }

  char szBuff[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
  TMN_REPARSE_DATA_BUFFER& rdb = *(TMN_REPARSE_DATA_BUFFER*)szBuff;

  DWORD dwBytesReturned;
  if (!DeviceIoControl(hDir,
            FSCTL_GET_REPARSE_POINT,
            NULL,
            0,
            (LPVOID)&rdb,
            MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
            &dwBytesReturned,
            0) ||
    !IsReparseTagValid(rdb.ReparseTag))
  {
    CloseHandle(hDir);
    return 0;
  }

  CloseHandle(hDir);

  if (dwBuffSize < rdb.SubstituteNameLength / sizeof(TCHAR) + sizeof(TCHAR))
  {
    return rdb.SubstituteNameLength / sizeof(TCHAR) + sizeof(TCHAR);
  }

#ifdef UNICODE
  lstrcpy(szDestBuff, rdb.PathBuffer);
#else
  if (!WideCharToMultiByte(CP_THREAD_ACP,
              0,
              rdb.PathBuffer,
              rdb.SubstituteNameLength / sizeof(WCHAR) + 1,
              szDestBuff,
              dwBuffSize,
              "",
              FALSE))
  {
    //printf("WideCharToMultiByte failed (%d)\n", GetLastError());
    return 0;
  }
#endif
  return rdb.SubstituteNameLength / sizeof(TCHAR);
}

/* $ 07.09.2000 SVS
   㭪 GetNumberOfLinks ⮦ 㯭  :-)
*/
int WINAPI GetNumberOfLinks(char *Name)
{
  HANDLE hFile=CreateFile(Name,0,FILE_SHARE_READ|FILE_SHARE_WRITE,
                          NULL,OPEN_EXISTING,0,NULL);
  if (hFile==INVALID_HANDLE_VALUE)
    return(1);
  BY_HANDLE_FILE_INFORMATION bhfi;
  int GetCode=GetFileInformationByHandle(hFile,&bhfi);
  CloseHandle(hFile);
  return(GetCode ? bhfi.nNumberOfLinks:0);
}
/* SVS $*/

#if defined(__BORLANDC__)
#pragma option -a4
#endif
int WINAPI MkLink(char *Src,char *Dest)
{
  struct CORRECTED_WIN32_STREAM_ID
  {
    DWORD          dwStreamId ;
    DWORD          dwStreamAttributes ;
    LARGE_INTEGER  Size ;
    DWORD          dwStreamNameSize ;
    WCHAR          cStreamName[ ANYSIZE_ARRAY ] ;
  } StreamId;

  char FileSource[NM],FileDest[NM];
  WCHAR FileLink[NM];

  HANDLE hFileSource;

  DWORD dwBytesWritten;
  LPVOID lpContext;
  DWORD cbPathLen;
  DWORD StreamSize;

  BOOL bSuccess;

//  ConvertNameToFull(Src,FileSource, sizeof(FileSource));
  if (ConvertNameToFull(Src,FileSource, sizeof(FileSource)) >= sizeof(FileSource)){
    return FALSE;
  }
//  ConvertNameToFull(Dest,FileDest, sizeof(FileDest));
  if (ConvertNameToFull(Dest,FileDest, sizeof(FileDest)) >= sizeof(FileDest)){
    return FALSE;
  }
  MultiByteToWideChar(CP_OEMCP,0,FileDest,-1,FileLink,sizeof(FileLink)/sizeof(FileLink[0]));

  hFileSource = CreateFile(FileSource,FILE_WRITE_ATTRIBUTES,
                FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);

  if(hFileSource == INVALID_HANDLE_VALUE)
    return(FALSE);

  lpContext = NULL;
  cbPathLen = (lstrlenW(FileLink) + 1) * sizeof(WCHAR);

  StreamId.dwStreamId = BACKUP_LINK;
  StreamId.dwStreamAttributes = 0;
  StreamId.dwStreamNameSize = 0;
  StreamId.Size.u.HighPart = 0;
  StreamId.Size.u.LowPart = cbPathLen;

  StreamSize=sizeof(StreamId)-sizeof(WCHAR **)+StreamId.dwStreamNameSize;

  bSuccess = BackupWrite(hFileSource,(LPBYTE)&StreamId,StreamSize,
             &dwBytesWritten,FALSE,FALSE,&lpContext);

  int LastError=0;

  if (bSuccess)
  {
    bSuccess = BackupWrite(hFileSource,(LPBYTE)FileLink,cbPathLen,
                &dwBytesWritten,FALSE,FALSE,&lpContext);
    if (!bSuccess)
      LastError=GetLastError();

    BackupWrite(hFileSource,NULL,0,&dwBytesWritten,TRUE,FALSE,&lpContext);
  }
  else
    LastError=GetLastError();

  CloseHandle(hFileSource);

  if (LastError)
    SetLastError(LastError);

  return(bSuccess);
}
#if defined(__BORLANDC__)
#pragma option -a.
#endif

/* $ 05.01.2001 SVS
   㭪 DelSubstDrive - 㤠 Subst ࠩ
   Return: -1 -    SUBST-ࠩ,  OS  .
            0 -  㤠
            1 - 訡  㤠.
*/
int DelSubstDrive(char *DosDeviceName)
{
  char NtDeviceName[512];
  if(GetSubstName(DosDeviceName,NtDeviceName,sizeof(NtDeviceName)))
  {
    return !DefineDosDevice(DDD_RAW_TARGET_PATH|
                       DDD_REMOVE_DEFINITION|
                       DDD_EXACT_MATCH_ON_REMOVE,
                       DosDeviceName, NtDeviceName)?1:0;
  }
  return(-1);
}
/* SVS $ */

BOOL GetSubstName(char *LocalName,char *SubstName,int SubstSize)
{
  char Name[NM*2]="";
  LocalName=CharUpper((LPTSTR)LocalName);
  if ((LocalName[0]>='A') && ((LocalName[0]<='Z')))
  {
    //  ,   WIN98   !!!!
    int SizeName=WinVer.dwPlatformId==VER_PLATFORM_WIN32_NT?sizeof(Name):MAXPATH;

    if (QueryDosDevice(LocalName,Name,SizeName) >= 3)
    {
      /* Subst drive format API differences:
       *   WinNT: \??\qualified_path (e.g. \??\C:\WinNT)
       *   Win98: qualified_path (e.g. C:\ or C:\Win98) */
      if (WinVer.dwPlatformId==VER_PLATFORM_WIN32_NT)
      {
        if (!strncmp(Name,"\\??\\",4))
        {
          strncpy(SubstName,Name+4,SubstSize);
          return TRUE;
        }
      }
      else
      {
        if(Name[1] == ':' && Name[2] == '\\')
        {
          strncpy(SubstName,Name,SubstSize);
          return TRUE;
        }
      }
    }
  }
  return FALSE;
}

<|endoftext|>