<commit_before>//
// This file is part of Easylogging++ samples
//
// Demonstration of multithreaded application using pthread
//
// Compile this program using (if using gcc-c++ or intel or clang++):
//     [icpc | g++ | clang++] ./pthread.cpp -o bin/./pthread.cpp.bin -D_ELPP_THREAD_SAFE -std=c++0x -pthread -Wall -Wextra
//
// Revision: 1.1
// @author mkhan3189
//

#include <pthread.h>
#include "easylogging++.h"

_INITIALIZE_EASYLOGGINGPP

struct Args {
  const char* thrId;
  el::Logger* logger;
}args;

void* write2(void* args){
  struct Args* a = (struct Args*)args;

  char* threadId = (char*)a->thrId;
  el::Logger* logger = (el::Logger*)a->logger;

  LOG(INFO) << "Writing from different function using macro [Thread #" << threadId << "]";

  logger->info("Info log from [Thread #%v]", threadId);
  logger->info("Info log");
  logger->verbose(2, "Verbose test [Thread #%v]", threadId);
  logger->verbose(2, "Verbose test");
  return NULL;
}

void *write(void* thrId){
  char* threadId = (char*)thrId;
  // Following line will be logged with every thread
  LOG(INFO) << "This standard log is written by [Thread #" << threadId << "]";

  // Following line will be logged with every thread only when --v=2 argument
  // is provided, i.e, ./bin/multithread_test.cpp.bin --v=2
  VLOG(2) << "This is verbose level 2 logging from [Thread #" << threadId << "]";

  // Following line will be logged only once from second running thread (which every runs second into
  // this line because of interval 2)
  LOG_EVERY_N(2, WARNING) << "This will be logged only once from thread who every reaches this line first. Currently running from [Thread #" << threadId << "]";

  for (int i = 1; i <= 10; ++i) {
     VLOG_IF(true, 2) << "Verbose condition [Thread #" << threadId << "]";
     VLOG_EVERY_N(2, 3) << "Verbose level 3 log every 4th time. This is at " << i << " from [Thread #" << threadId << "]";
  }

  // Following line will be logged once with every thread because of interval 1
  LOG_EVERY_N(1, INFO) << "This interval log will be logged with every thread, this one is from [Thread #" << threadId << "]";

  LOG_IF(strcmp(threadId, "2") == 0, INFO) << "This log is only for thread 2 and is ran by [Thread #" << threadId << "]";

  // Register 5 vague loggers
  for (int i = 1; i <= 5; ++i) {
     std::stringstream ss;
     ss << "logger" << i;
     el::Logger* logger = easyloggingpp::Loggers::getLogger(ss.str());
     LOG(INFO) << "Registered logger [" << *logger << "] [Thread #" << threadId << "]";
  }
  CLOG(INFO, "logger1") << "Logging using new logger [Thread #" << threadId << "]";
  CLOG(INFO, "no-logger") << "THIS SHOULD SAY LOGGER NOT REGISTERED YET [Thread #" << threadId << "]"; // << -- NOTE THIS!

  el::Logger* logger = el::Loggers::getLogger("default");
  logger->info("Info log from [Thread #%v]", threadId);

  // Check for log counters positions
  for (int i = 1; i <= 50; ++i) {
     LOG_EVERY_N(2, INFO) << "Counter pos: " << ELPP_COUNTER_POS << " [Thread #" << threadId << "]";
  }
  LOG_EVERY_N(2, INFO) << "Counter pos: " << ELPP_COUNTER_POS << " [Thread #" << threadId << "]";
  return NULL;
}

// If you wish you can define your own way to get thread ID
const char* getThreadId_CustomVersion(void) {
    return "MyThreadId";
}

int main(int argc, char** argv)
{
     _START_EASYLOGGINGPP(argc, argv);

     // Your thread ID specification
     el::CustomFormatSpecifier myThreadIdSpecifier("%mythreadId", getThreadId_CustomVersion);
     el::Helpers::installCustomFormatSpecifier(myThreadIdSpecifier);

     // Note your %mythreadId or built-in, both are logged
     el::Loggers::reconfigureAllLoggers(el::ConfigurationType::Format, "%datetime %level (%thread | %mythreadId) [%logger] [%func] [%loc] %msg");
     el::Loggers::reconfigureAllLoggers(el::Level::Verbose, el::ConfigurationType::Format, "%datetime %level-%vlevel (%thread | %mythreadId) [%logger] [%func] [%loc] %msg");

     pthread_t thread1, thread2, thread3, thread4;

    /* Create independent threads each of which will execute function */
     pthread_create( &thread1, NULL, write, (void*)"1");
     pthread_create( &thread2, NULL, write, (void*)"2");
     pthread_create( &thread3, NULL, write, (void*)"3");

     el::Logger* logger = el::Loggers::getLogger("default");
     args.thrId = "4";
     args.logger = logger;
     pthread_create( &thread4, NULL, write2, (void*)&args);

     pthread_join(thread1, NULL);
     pthread_join(thread2, NULL);
     pthread_join(thread3, NULL);
     pthread_join(thread4, NULL);

    exit(0);
}
<commit_msg>updated version<commit_after>//
// This file is part of Easylogging++ samples
//
// Demonstration of multithreaded application using pthread
//
// Compile this program using (if using gcc-c++ or intel or clang++):
//     [icpc | g++ | clang++] ./pthread.cpp -o bin/./pthread.cpp.bin -D_ELPP_THREAD_SAFE -std=c++0x -pthread -Wall -Wextra
//
// Revision: 1.1
// @author mkhan3189
//

#include <pthread.h>
#include "easylogging++.h"

_INITIALIZE_EASYLOGGINGPP

struct Args {
  const char* thrId;
  el::Logger* logger;
}args;

void* write2(void* args){
  struct Args* a = (struct Args*)args;

  char* threadId = (char*)a->thrId;
  el::Logger* logger = (el::Logger*)a->logger;

  LOG(INFO) << "Writing from different function using macro [Thread #" << threadId << "]";

  logger->info("Info log from [Thread #%v]", threadId);
  logger->info("Info log");
  logger->verbose(2, "Verbose test [Thread #%v]", threadId);
  logger->verbose(2, "Verbose test");
  return NULL;
}

void *write(void* thrId){
  char* threadId = (char*)thrId;
  // Following line will be logged with every thread
  LOG(INFO) << "This standard log is written by [Thread #" << threadId << "]";

  // Following line will be logged with every thread only when --v=2 argument
  // is provided, i.e, ./bin/multithread_test.cpp.bin --v=2
  VLOG(2) << "This is verbose level 2 logging from [Thread #" << threadId << "]";

  // Following line will be logged only once from second running thread (which every runs second into
  // this line because of interval 2)
  LOG_EVERY_N(2, WARNING) << "This will be logged only once from thread who every reaches this line first. Currently running from [Thread #" << threadId << "]";

  for (int i = 1; i <= 10; ++i) {
     VLOG_IF(true, 2) << "Verbose condition [Thread #" << threadId << "]";
     VLOG_EVERY_N(2, 3) << "Verbose level 3 log every 4th time. This is at " << i << " from [Thread #" << threadId << "]";
  }

  // Following line will be logged once with every thread because of interval 1
  LOG_EVERY_N(1, INFO) << "This interval log will be logged with every thread, this one is from [Thread #" << threadId << "]";

  LOG_IF(strcmp(threadId, "2") == 0, INFO) << "This log is only for thread 2 and is ran by [Thread #" << threadId << "]";

  // Register 5 vague loggers
  for (int i = 1; i <= 5; ++i) {
     std::stringstream ss;
     ss << "logger" << i;
     el::Logger* logger = easyloggingpp::Loggers::getLogger(ss.str());
     LOG(INFO) << "Registered logger [" << *logger << "] [Thread #" << threadId << "]";
  }
  CLOG(INFO, "logger1") << "Logging using new logger [Thread #" << threadId << "]";
  CLOG(INFO, "no-logger") << "THIS SHOULD SAY LOGGER NOT REGISTERED YET [Thread #" << threadId << "]"; // << -- NOTE THIS!

  el::Logger* logger = el::Loggers::getLogger("default");
  logger->info("Info log from [Thread #%v]", threadId);

  // Check for log counters positions
  for (int i = 1; i <= 50; ++i) {
     LOG_EVERY_N(2, INFO) << "Counter pos: " << ELPP_COUNTER_POS << " [Thread #" << threadId << "]";
  }
  LOG_EVERY_N(2, INFO) << "Counter pos: " << ELPP_COUNTER_POS << " [Thread #" << threadId << "]";
  return NULL;
}

// If you wish you can define your own way to get thread ID
const char* getThreadId_CustomVersion(void) {
    return std::to_string(static_cast<long long>(pthread_self())).c_str();
}

int main(int argc, char** argv)
{
     _START_EASYLOGGINGPP(argc, argv);

     // Your thread ID specification
     el::CustomFormatSpecifier myThreadIdSpecifier("%mythreadId", getThreadId_CustomVersion);
     el::Helpers::installCustomFormatSpecifier(myThreadIdSpecifier);

     // Note your %mythreadId or built-in, both are logged
     el::Loggers::reconfigureAllLoggers(el::ConfigurationType::Format, "%datetime %level (%thread | %mythreadId) [%logger] [%func] [%loc] %msg");
     el::Loggers::reconfigureAllLoggers(el::Level::Verbose, el::ConfigurationType::Format, "%datetime %level-%vlevel (%thread | %mythreadId) [%logger] [%func] [%loc] %msg");

     pthread_t thread1, thread2, thread3, thread4;

    /* Create independent threads each of which will execute function */
     pthread_create( &thread1, NULL, write, (void*)"1");
     pthread_create( &thread2, NULL, write, (void*)"2");
     pthread_create( &thread3, NULL, write, (void*)"3");

     el::Logger* logger = el::Loggers::getLogger("default");
     args.thrId = "4";
     args.logger = logger;
     pthread_create( &thread4, NULL, write2, (void*)&args);

     pthread_join(thread1, NULL);
     pthread_join(thread2, NULL);
     pthread_join(thread3, NULL);
     pthread_join(thread4, NULL);

    exit(0);
}
<|endoftext|>


<commit_before>// Copyright 2011 Google Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * 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.
//     * Neither the name of Google Inc. 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.

#include <string.h>

#include "snappy-sinksource.h"

namespace snappy {

Source::~Source() { }

Sink::~Sink() { }

char* Sink::GetAppendBuffer(size_t length, char* scratch) {
  return scratch;
}

ByteArraySource::~ByteArraySource() { }

size_t ByteArraySource::Available() const { return left_; }

const char* ByteArraySource::Peek(size_t* len) {
  *len = left_;
  return ptr_;
}

void ByteArraySource::Skip(size_t n) {
  left_ -= n;
  ptr_ += n;
}

UncheckedByteArraySink::~UncheckedByteArraySink() { }

void UncheckedByteArraySink::Append(const char* data, size_t n) {
  // Do no copying if the caller filled in the result of GetAppendBuffer()
  if (data != dest_) {
    memcpy(dest_, data, n);
  }
  dest_ += n;
}

char* UncheckedByteArraySink::GetAppendBuffer(size_t len, char* scratch) {
  return dest_;
}

}
<commit_msg>Fix more snappy compiler warnings.<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * 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.
//     * Neither the name of Google Inc. 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.

#include <string.h>

#include "snappy-sinksource.h"

namespace snappy {

Source::~Source() { }

Sink::~Sink() { }

char* Sink::GetAppendBuffer(size_t /* length */, char* scratch) {
  return scratch;
}

ByteArraySource::~ByteArraySource() { }

size_t ByteArraySource::Available() const { return left_; }

const char* ByteArraySource::Peek(size_t* len) {
  *len = left_;
  return ptr_;
}

void ByteArraySource::Skip(size_t n) {
  left_ -= n;
  ptr_ += n;
}

UncheckedByteArraySink::~UncheckedByteArraySink() { }

void UncheckedByteArraySink::Append(const char* data, size_t n) {
  // Do no copying if the caller filled in the result of GetAppendBuffer()
  if (data != dest_) {
    memcpy(dest_, data, n);
  }
  dest_ += n;
}

char* UncheckedByteArraySink::GetAppendBuffer(size_t /* len */, char* /* scratch */) {
  return dest_;
}

}
<|endoftext|>


<commit_before>#include <reflection/reflection.h>

// TODO:
// - REFLECTABLE
// - REFLECTABLE_MEMBER_TYPE
// - REFLECTABLE_MEMBER_FUNCTION
// - REFLECTABLE_OPERATOR
// - REFLECTABLE_OPERATOR_UNARY
// - REFLECTABLE_OPERATOR_ASSIGNMENT
// TODO:
// - free function operators (see cppreference.com)

// TODO: Re-enable tests
REFLECTABLE(auto, operator!=,   member_function);
REFLECTABLE(auto, operator%,    member_function);
REFLECTABLE(auto, operator%=,   member_function);
REFLECTABLE(auto, operator&&,   member_function);
REFLECTABLE(auto, operator&,    member_function);
REFLECTABLE(auto, operator&=,   member_function);
REFLECTABLE(auto, operator(),   member_function);
REFLECTABLE(auto, operator*,    member_function);
REFLECTABLE(auto, operator*=,   member_function);
REFLECTABLE(auto, operator++,   member_function);
REFLECTABLE(auto, operator+,    member_function);
REFLECTABLE(auto, operator+=,   member_function);
REFLECTABLE(auto, operator-,    member_function);
REFLECTABLE(auto, operator--,   member_function);
REFLECTABLE(auto, operator-=,   member_function);
REFLECTABLE(auto, operator->*,  member_function);
REFLECTABLE(auto, operator/,    member_function);
REFLECTABLE(auto, operator/=,   member_function);
REFLECTABLE(auto, operator<,    member_function);
REFLECTABLE(auto, operator<<,   member_function);
REFLECTABLE(auto, operator<<=,  member_function);
REFLECTABLE(auto, operator<=,   member_function);
REFLECTABLE(auto, operator==,   member_function);
REFLECTABLE(auto, operator>,    member_function);
REFLECTABLE(auto, operator>=,   member_function);
REFLECTABLE(auto, operator>>,   member_function);
REFLECTABLE(auto, operator>>=,  member_function);
REFLECTABLE(auto, operator[],   member_function);
REFLECTABLE(auto, operator^,    member_function);
REFLECTABLE(auto, operator^=,   member_function);
REFLECTABLE(auto, operator|,    member_function);
REFLECTABLE(auto, operator|=,   member_function);
REFLECTABLE(auto, operator||,   member_function);

REFLECTION_REFLECTABLE_NONINTRUSIVE_UNARY_OPERATOR(auto, operator!,   member_function);
REFLECTION_REFLECTABLE_NONINTRUSIVE_UNARY_OPERATOR(auto, operator->,  member_function);
REFLECTION_REFLECTABLE_NONINTRUSIVE_UNARY_OPERATOR(auto, operator~,   member_function);

REFLECTION_REFLECTABLE_NONINTRUSIVE_ASSIGNMENT_OPERATOR(auto, operator=, member_function);

// TODO: operator,
// #define REFLECTION_OPERATOR_COMMA operator,
// REFLECTABLE(auto, REFLECTION_OPERATOR_COMMA,  member_function);
<commit_msg>Removed a TODO<commit_after>#include <reflection/reflection.h>

// TODO:
// - REFLECTABLE
// - REFLECTABLE_MEMBER_TYPE
// - REFLECTABLE_MEMBER_FUNCTION
// - REFLECTABLE_OPERATOR
// - REFLECTABLE_OPERATOR_UNARY
// - REFLECTABLE_OPERATOR_ASSIGNMENT
// TODO:
// - free function operators (see cppreference.com)

REFLECTABLE(auto, operator!=,   member_function);
REFLECTABLE(auto, operator%,    member_function);
REFLECTABLE(auto, operator%=,   member_function);
REFLECTABLE(auto, operator&&,   member_function);
REFLECTABLE(auto, operator&,    member_function);
REFLECTABLE(auto, operator&=,   member_function);
REFLECTABLE(auto, operator(),   member_function);
REFLECTABLE(auto, operator*,    member_function);
REFLECTABLE(auto, operator*=,   member_function);
REFLECTABLE(auto, operator++,   member_function);
REFLECTABLE(auto, operator+,    member_function);
REFLECTABLE(auto, operator+=,   member_function);
REFLECTABLE(auto, operator-,    member_function);
REFLECTABLE(auto, operator--,   member_function);
REFLECTABLE(auto, operator-=,   member_function);
REFLECTABLE(auto, operator->*,  member_function);
REFLECTABLE(auto, operator/,    member_function);
REFLECTABLE(auto, operator/=,   member_function);
REFLECTABLE(auto, operator<,    member_function);
REFLECTABLE(auto, operator<<,   member_function);
REFLECTABLE(auto, operator<<=,  member_function);
REFLECTABLE(auto, operator<=,   member_function);
REFLECTABLE(auto, operator==,   member_function);
REFLECTABLE(auto, operator>,    member_function);
REFLECTABLE(auto, operator>=,   member_function);
REFLECTABLE(auto, operator>>,   member_function);
REFLECTABLE(auto, operator>>=,  member_function);
REFLECTABLE(auto, operator[],   member_function);
REFLECTABLE(auto, operator^,    member_function);
REFLECTABLE(auto, operator^=,   member_function);
REFLECTABLE(auto, operator|,    member_function);
REFLECTABLE(auto, operator|=,   member_function);
REFLECTABLE(auto, operator||,   member_function);

REFLECTION_REFLECTABLE_NONINTRUSIVE_UNARY_OPERATOR(auto, operator!,   member_function);
REFLECTION_REFLECTABLE_NONINTRUSIVE_UNARY_OPERATOR(auto, operator->,  member_function);
REFLECTION_REFLECTABLE_NONINTRUSIVE_UNARY_OPERATOR(auto, operator~,   member_function);

REFLECTION_REFLECTABLE_NONINTRUSIVE_ASSIGNMENT_OPERATOR(auto, operator=, member_function);

// TODO: operator,
// #define REFLECTION_OPERATOR_COMMA operator,
// REFLECTABLE(auto, REFLECTION_OPERATOR_COMMA,  member_function);
<|endoftext|>


<commit_before>#include "libcanister.h"
#include "fileinterpretation.h"
#include "bzipWrapper.h"
using namespace std;

libcanister::canister::canister (char* fspath)
{
    info.path = *(new canmem(fspath));
    cachemax = 25;
    cachecnt = 0;
    readonly = false;
}

libcanister::canister::canister (canmem fspath)
{
    info.path = fspath;
    cachemax = 25;
    cachecnt = 0;
    readonly = false;
}

libcanister::canfile libcanister::canister::getTOC()
{
    return TOC;
}

int libcanister::canister::delFile(canmem path)
{
    int i = 0;
    //search for the file
    while (i < info.numfiles)
    {
        //if we found it
        if(!strcmp(files[i].path.data, path.data))
        {
            files[i].data.fragmem();
            files[i].cachestate = 2;
            files[i].isfrag = 1;
            files[i].cfid &= 0x80000000;
            files[i].path.data = (char*)"FRAGMENT";
            files[i].path.countlen();
            return 0;
        }
        i++;
    }
    return -1;
}

libcanister::canfile libcanister::canister::getFile(canmem path)
{
    int i = 0;
    //search for the file
    while (i < info.numfiles)
    {
        //if we found it
        if(!strcmp(files[i].path.data, path.data))
        {
            //pull it into memory
            files[i].cache();
            //and return it
            return files[i];
        }
        i++;
    }
    //otherwise generate an error file to report it
    canfile tmp;
    tmp.data = *(new canmem((char*)"Error: file not found."));
    tmp.cachestate = -1;
    return tmp;
}

bool libcanister::canister::writeFile(canmem path, canmem data)
{
    //here we simply wrap the information we're given and call
    //the 'real' writeFile function
    canfile wrapper;
    wrapper.path = path;
    wrapper.data = data;
    wrapper.cfid = -1;
    wrapper.dsize = -1;
    wrapper.isfrag = 0;
    wrapper.cachestate = 2;
    wrapper.parent = this;
    writeFile(wrapper);
    return true;
}

bool libcanister::canister::writeFile(canfile file)
{
    //if we're in readonly mode, we're definitely not going to be
    //writing this file under any circumstance.
    if (readonly)
    {
        cout << "Error: canister is read only, file could not be written." << endl;
        return false;
    }
    //we want to first figure out how much disk space it needs
    canmem tmpdata = bzipWrapper::compress(file.data);
    int i = 0;
    //search for the file
    while (i < info.numfiles)
    {
        //if it already exists
        if (!strcmp(files[i].path.data, file.path.data))
        {
            //then we check to make sure the new version would fit within the old
            if (tmpdata.size == files[i].dsize || tmpdata.size < files[i].dsize - 6)
            {
                //whereupon we make the changeover
                files[i].dsize = tmpdata.size;
                files[i].data = file.data;
                files[i].cachestate = 2; //needs flush
                //and handle the fragmented leftovers
                if (tmpdata.size < files[i].dsize - 6)
                {
                    #warning "Need to handle fragment."
                }
                return true;
            }
            else
            {
                //otherwise, we're just going to have to make the original
                //file into one big fragment and let the rest of the
                //function take care of the bigger version of the file
                files[i].cfid &= 0x80000000;
                files[i].isfrag = 1;
                files[i].path = *(new canmem((char*)"FRAGMENT"));
                //++info.numfiles; not sure if this was needed
                break;
            }
        }
        i++;
    }
    //search for a fragment large enough to hold this
    while (i < info.numfiles)
    {
        //is this a fragment?
        if (files[i].cfid & 0x80000000)
        {
            //can we fit it inside the fragment?
            if (files[i].dsize >= tmpdata.size + 6)
            {
                files[i] = file;
                files[i].data = tmpdata;
                files[i].dsize = tmpdata.size;
                files[i].cachestate = 2;
            }
        }
    }
    //here we generate a new CFID for the file
    file.cfid = ++info.numfiles;
    //mark it to be in need of flushing
    file.cachestate = 2;
    //it isn't a fragment
    file.isfrag = 0;
    //then we rebuild the array to be one larger
    canfile* newSet = new canfile[info.numfiles];
    //copy the old into the new
    memcpy(newSet, files, (info.numfiles - 1) * sizeof(canfile));
    //put this file into the array
    newSet[info.numfiles-1] = file;
    //and move the old pointer to look at this new array
    files = newSet;
    //and here we add the new file onto the autogenerated TOC
    int tLen = TOC.data.size;
    TOC.data.size += file.path.size;
    char* tmp = TOC.data.data;
    TOC.data.data = new char[TOC.data.size];
    memcpy(TOC.data.data, tmp, tLen);
    memcpy(TOC.data.data + tLen, file.path.data, file.path.size);
    TOC.data.data[TOC.data.size-1] = '\n';
    //success!
    return true;
}

//dumps files from memory until cachecnt <= cachemax
//first dumps unmodified files from memory until the condition is met
//however, it will do a full cache flush if needed
void libcanister::canister::cacheclean (int sCFID, bool dFlush)
{
    int i = 0;
    //loop through and uncache files until we're within cachemax
    while (i < info.numfiles && cachecnt > cachemax)
    {
        //preferably uncache only files which haven't been modified
        if (files[i].cfid != sCFID && (dFlush || files[i].cachestate == 1))
        {
            if (files[i].cachestate == 2)
                files[i].cachedump();
            else
            {
                files[i].data = canmem::null();
                files[i].cachestate = 0;
            }
        }
        i++;
    }

    //if we still haven't done enough cleaning, flush the modified files too!
    if (!dFlush && cachecnt > cachemax && !readonly)
        cacheclean(sCFID, true);
}

//actuates the close() item when naturally destroyed
libcanister::canister::~canister()
{
    close();
}

//flushes all caches and prepares for object deletion
int libcanister::canister::close ()
{
    //don't do anything if readonly
    if (readonly)
        return 0;

    canmem fspath = info.path;
    fstream infile;
    infile.open(fspath.data, ios::in | ios::out | ios::binary);
    if (!infile.is_open())
        cout << "Whoa there.." << endl;
    infile.seekg(0, ios::beg);
    //write the header verification (c00)
    unsigned char temp1, temp2, temp3, temp4, temp5;

    infile << 0x01;
    infile << 'c';
    infile << 'a';
    infile << 'n';
    infile << 0x01;

    //write the new file count (filect) (c01)
    unsigned char* filect = (unsigned char*)(void*)&info.numfiles;
    infile << filect[3];
    infile << filect[2];
    infile << filect[1];
    infile << filect[0];

    //make sure there is a footerloc (c11) in some form.
    infile << (unsigned char)0xFF;
    infile << (unsigned char)0xFF;
    infile << (unsigned char)0xFF;
    infile << (unsigned char)0xFF;
    infile.seekg(14, ios::beg); //seek to file section
    int i = 0;
    //otherwise, loop through the files
    while (i < info.numfiles)
    {
        //dout << files[i].cachestate << endl;
        files[i].cachedumpfinal(infile);
        files[i].data = canmem::null();
        files[i].cachestate = 0;
        i++;
    }
    //here we rewrite the footer to represent the latest changes to the canister
    int footerloc = infile.tellg();
    // infile.seekg(footerloc, ios::beg); //reset back to footer

    //write footer verification (c00)
    infile << temp1;
    infile << temp2;
    infile << temp3;
    infile << temp4;
    infile << temp5;

    //c02
    info.internalname.trim();
    infile.write(info.internalname.data, info.internalname.size);
    infile << (unsigned char)0x02;

    i = 0;
    while (i < info.numfiles)
    {
        //c03
        infile << (unsigned char)0x01;

        //c04
        unsigned char* sizeout = (unsigned char*)(void*)&files[i].dsize;
        infile << sizeout[7];
        infile << sizeout[6];
        infile << sizeout[5];
        infile << sizeout[4];
        infile << sizeout[3];
        infile << sizeout[2];
        infile << sizeout[1];
        infile << sizeout[0];

        //c05
        unsigned char* id = (unsigned char*)(void*)&files[i].cfid;
        infile << id[3];
        infile << id[2];
        infile << id[1];
        infile << id[0];

        //c06
        files[i].path.trim();
        infile.write(files[i].path.data, files[i].path.size);
        infile << (unsigned char)0x02;

        i++;
    }

    infile << (unsigned char)0x03; //c07

    infile.seekg(9, ios::beg); //go back to header

    //write the new footerloc into place (c11)
    unsigned char* ftloc = (unsigned char*)(void*)&footerloc;
    infile << ftloc[3];
    infile << ftloc[2];
    infile << ftloc[1];
    infile << ftloc[0];
    infile << (unsigned char)0x03; //c07

    //no other modifications to the canister should happen after this point
    //also prevents double closure from a manual close() call and the automated one
    //coming from ~canister()
    readonly = true;
    return 0;
}

int libcanister::canister::open()
{
    //here we open the file associated with this canister
    canmem fspath = info.path;
    ifstream infile;
    infile.open(fspath.data);
    //now we begin creating the table of contents
    TOC.parent = this;
    TOC.path = canmem::null();
    TOC.cachestate = 1;
    TOC.cfid = -1;
    TOC.dsize = 0;
    //if the file didn't open, we need to do a
    //skeletal initialization of the canister
    if (!infile.is_open())
    {
        info.internalname = *(new canmem((char*)"generic canister"));
        info.numfiles = 0;
        canmem tocData;
        tocData.data = (char*)"";
        tocData.size = 0;
        TOC.data = tocData;
        return 0;
    }
    //otherwise, we're going to work on reading the file's
    //header and footer into memory
    else
    {
        //begin interpreting the file
        //lets make some temporary variables to store the header
        unsigned char temp1, temp2, temp3, temp4, temp5;
        readonly = false;
        infile >> temp1;
        infile >> temp2;
        infile >> temp3;
        infile >> temp4;
        infile >> temp5;
        //does the header match? (c00)
        if ((temp1 == 0x01) && (temp2 == 'c') && (temp3 == 'a') && (temp4 == 'n') && (temp5 == 0x01))
        {   //yes, valid header
            dout << "valid header" << endl;
            //read in the number of files
            info.numfiles = readint32(infile);
            dout << "numfiles: " << info.numfiles << endl;
            #warning "technically this should be a readint64, but seekg won't accept the 64-bit int. Solution needed."
            int footerloc = readint32(infile);
            infile.seekg(footerloc, ios::beg);
            //does the footer match?
            infile >> temp1;
            infile >> temp2;
            infile >> temp3;
            infile >> temp4;
            infile >> temp5;
            if ((temp1 == 0x01) && (temp2 == 'c') && (temp3 == 'a') && (temp4 == 'n') && (temp5 == 0x01))
            {   //yes, valid footer (c00)
                //create a file array to hold the files
                files = new canfile[info.numfiles];
                //set the internal name of the canister
                info.internalname = readstr(infile);
                dout << "internalname: " << info.internalname.data << endl;
                int i = 0;
                char* tocRaw;
                int tocLen = 0;
                infile >> temp1;
                //loop through the file headers for each file
                while (temp1 == 0x01)
                {
                    //if we've exceeded the number of files and have found another
                    //then something fishy is happening somewhere... let's just
                    //use the info we have and ignore the other stuff in here
                    //Entering read only mode to prevent further damage to the canister
                    if (i >= info.numfiles)
                    {
                        cerr << "Corrupted Canister! Error message: File table length exceeds the number of files!" << endl;
                        cerr << "Best recovery option: read-only" << endl;
                        cerr << "Opening as read-only to prevent further damage to the canister." << endl;
                        readonly = true;
                        //loop to the end of the file header
                        while (temp1 != 0x03)
                            infile >> temp1;
                        break;
                    }

                    //read the file header
                    files[i].parent = this;
                    files[i].dsize = readint64(infile);
                    dout << "dsize: " << files[i].dsize << endl;
                    files[i].cfid = readint32(infile);
                    dout << "cfid: " << files[i].cfid << endl;
                    files[i].path = readstr(infile);
                    files[i].cachestate = 0;
                    files[i].data = canmem::null();
                    if (files[i].cfid & 0x80000000 || !strcmp(files[i].path.data, (char*)"FRAGMENT"))
                        files[i].isfrag = 1;
                    else
                    {
                        files[i].isfrag = 0;
                        //deal with the table of contents
                        int tLen = tocLen;
                        tocLen += files[i].path.size;
                        char* tmp = tocRaw;
                        tocRaw = new char[tocLen];
                        memcpy(tocRaw, tmp, tLen);
                        memcpy(tocRaw + tLen, files[i].path.data, files[i].path.size);
                        tocRaw[tocLen-1] = '\n';
                    }

                    //read the next file
                    i++;
                    infile >> temp1;
                }
                if (temp1 != 0x03)
                {
                    cerr << "Corrupted Canister! Error message: Incomplete file table! Data: " << (unsigned int)temp1 << " " << infile.tellg() << endl;
                    return -1;
                }
                if (tocLen > 0)
                    tocRaw[tocLen] = 0x00;
                else
                {
                    tocRaw = new char[1];
                    tocRaw[0] = 0x00;
                }
                canmem tocDat = *(new canmem(tocLen));
                tocDat.data = tocRaw;
                TOC.data = tocDat;

                infile.close();

                return 1;
            }
            else
            {
                cout << "Error: canister is corrupt." << endl;
                return -1;
            }
        }
        else
        {
            cout << "Error: canister is corrupt." << endl;
            return -1;
        }
    }
    return -1;
}

<commit_msg>minor fixes.<commit_after>#include "libcanister.h"
#include "fileinterpretation.h"
#include "bzipWrapper.h"
using namespace std;

libcanister::canister::canister (char* fspath)
{
    info.path = *(new canmem(fspath));
    cachemax = 25;
    cachecnt = 0;
    readonly = false;
}

libcanister::canister::canister (canmem fspath)
{
    info.path = fspath;
    cachemax = 25;
    cachecnt = 0;
    readonly = false;
}

libcanister::canfile libcanister::canister::getTOC()
{
    return TOC;
}

int libcanister::canister::delFile(canmem path)
{
    int i = 0;
    //search for the file
    while (i < info.numfiles)
    {
        //if we found it
        if(!strcmp(files[i].path.data, path.data))
        {
            files[i].data.fragmem();
            files[i].cachestate = 2;
            files[i].isfrag = 1;
            files[i].cfid &= 0x80000000;
            files[i].path.data = (char*)"FRAGMENT";
            files[i].path.countlen();
            return 0;
        }
        i++;
    }
    return -1;
}

libcanister::canfile libcanister::canister::getFile(canmem path)
{
    int i = 0;
    //search for the file
    while (i < info.numfiles)
    {
        //if we found it
        if(!strcmp(files[i].path.data, path.data))
        {
            //pull it into memory
            files[i].cache();
            //and return it
            return files[i];
        }
        i++;
    }
    //otherwise generate an error file to report it
    canfile tmp;
    tmp.data = *(new canmem((char*)"Error: file not found."));
    tmp.cachestate = -1;
    return tmp;
}

bool libcanister::canister::writeFile(canmem path, canmem data)
{
    //here we simply wrap the information we're given and call
    //the 'real' writeFile function
    canfile wrapper;
    wrapper.path = path;
    wrapper.data = data;
    wrapper.cfid = -1;
    wrapper.dsize = -1;
    wrapper.isfrag = 0;
    wrapper.cachestate = 2;
    wrapper.parent = this;
    writeFile(wrapper);
    return true;
}

bool libcanister::canister::writeFile(canfile file)
{
    //if we're in readonly mode, we're definitely not going to be
    //writing this file under any circumstance.
    if (readonly)
    {
        cout << "Error: canister is read only, file could not be written." << endl;
        return false;
    }
    //we want to first figure out how much disk space it needs
    canmem tmpdata = bzipWrapper::compress(file.data);
    int i = 0;
    //search for the file
    while (i < info.numfiles)
    {
        //if it already exists
        if (!strcmp(files[i].path.data, file.path.data))
        {
            //then we check to make sure the new version would fit within the old
            if (tmpdata.size == files[i].dsize || tmpdata.size < files[i].dsize - 6)
            {
                //whereupon we make the changeover
                files[i].dsize = tmpdata.size;
                files[i].data = file.data;
                files[i].cachestate = 2; //needs flush
                //and handle the fragmented leftovers
                if (tmpdata.size < files[i].dsize - 6)
                {
                    #warning "Need to handle fragment."
                }
                return true;
            }
            else
            {
                //otherwise, we're just going to have to make the original
                //file into one big fragment and let the rest of the
                //function take care of the bigger version of the file
                files[i].cfid &= 0x80000000;
                files[i].isfrag = 1;
                files[i].path = *(new canmem((char*)"FRAGMENT"));
                //++info.numfiles; not sure if this was needed
                break;
            }
        }
        i++;
    }
    //search for a fragment large enough to hold this
    while (i < info.numfiles)
    {
        //is this a fragment?
        if (files[i].cfid & 0x80000000)
        {
            //can we fit it inside the fragment?
            if (files[i].dsize >= tmpdata.size + 6)
            {
                files[i] = file;
                files[i].data = tmpdata;
                files[i].dsize = tmpdata.size;
                files[i].cachestate = 2;
            }
        }
    }
    //here we generate a new CFID for the file
    file.cfid = ++info.numfiles;
    //mark it to be in need of flushing
    file.cachestate = 2;
    //it isn't a fragment
    file.isfrag = 0;
    //then we rebuild the array to be one larger
    canfile* newSet = new canfile[info.numfiles];
    //copy the old into the new
    memcpy(newSet, files, (info.numfiles - 1) * sizeof(canfile));
    //put this file into the array
    newSet[info.numfiles-1] = file;
    //and move the old pointer to look at this new array
    files = newSet;
    //and here we add the new file onto the autogenerated TOC
    int tLen = TOC.data.size;
    TOC.data.size += file.path.size;
    char* tmp = TOC.data.data;
    TOC.data.data = new char[TOC.data.size];
    memcpy(TOC.data.data, tmp, tLen);
    memcpy(TOC.data.data + tLen, file.path.data, file.path.size);
    TOC.data.data[TOC.data.size-1] = '\n';
    //success!
    return true;
}

//dumps files from memory until cachecnt <= cachemax
//first dumps unmodified files from memory until the condition is met
//however, it will do a full cache flush if needed
void libcanister::canister::cacheclean (int sCFID, bool dFlush)
{
    int i = 0;
    //loop through and uncache files until we're within cachemax
    while (i < info.numfiles && cachecnt > cachemax)
    {
        //preferably uncache only files which haven't been modified
        if (files[i].cfid != sCFID && (dFlush || files[i].cachestate == 1))
        {
            if (files[i].cachestate == 2)
                files[i].cachedump();
            else
            {
                files[i].data = canmem::null();
                files[i].cachestate = 0;
            }
        }
        i++;
    }

    //if we still haven't done enough cleaning, flush the modified files too!
    if (!dFlush && cachecnt > cachemax && !readonly)
        cacheclean(sCFID, true);
}

//actuates the close() item when naturally destroyed
libcanister::canister::~canister()
{
    close();
}

//flushes all caches and prepares for object deletion
int libcanister::canister::close ()
{
    //don't do anything if readonly
    if (readonly)
        return 0;

    canmem fspath = info.path;
    fstream infile;
    infile.open(fspath.data, ios::in | ios::out | ios::binary);
    if (!infile.is_open())
        cout << "Whoa there.." << endl;
    infile.seekg(0, ios::beg);
    //write the header verification (c00)

    infile << 0x01;
    infile << 'c';
    infile << 'a';
    infile << 'n';
    infile << 0x01;

    //write the new file count (filect) (c01)
    unsigned char* filect = (unsigned char*)(void*)&info.numfiles;
    infile << filect[3];
    infile << filect[2];
    infile << filect[1];
    infile << filect[0];

    //make sure there is a footerloc (c11) in some form.
    infile << (unsigned char)0xFF;
    infile << (unsigned char)0xFF;
    infile << (unsigned char)0xFF;
    infile << (unsigned char)0xFF;
    infile.seekg(14, ios::beg); //seek to file section
    int i = 0;
    //otherwise, loop through the files
    while (i < info.numfiles)
    {
        //dout << files[i].cachestate << endl;
        files[i].cachedumpfinal(infile);
        files[i].data = canmem::null();
        files[i].cachestate = 0;
        i++;
    }
    //here we rewrite the footer to represent the latest changes to the canister
    int footerloc = infile.tellg();
    // infile.seekg(footerloc, ios::beg); //reset back to footer

    //write footer verification (c00)
    infile << 0x01;
    infile << 'c';
    infile << 'a';
    infile << 'n';
    infile << 0x01;

    //c02
    info.internalname.trim();
    infile.write(info.internalname.data, info.internalname.size);
    infile << (unsigned char)0x02;

    i = 0;
    while (i < info.numfiles)
    {
        //c03
        infile << (unsigned char)0x01;

        //c04
        unsigned char* sizeout = (unsigned char*)(void*)&files[i].dsize;
        infile << sizeout[7];
        infile << sizeout[6];
        infile << sizeout[5];
        infile << sizeout[4];
        infile << sizeout[3];
        infile << sizeout[2];
        infile << sizeout[1];
        infile << sizeout[0];

        //c05
        unsigned char* id = (unsigned char*)(void*)&files[i].cfid;
        infile << id[3];
        infile << id[2];
        infile << id[1];
        infile << id[0];

        //c06
        files[i].path.trim();
        infile.write(files[i].path.data, files[i].path.size);
        infile << (unsigned char)0x02;

        i++;
    }

    infile << (unsigned char)0x03; //c07

    infile.seekg(9, ios::beg); //go back to header

    //write the new footerloc into place (c11)
    unsigned char* ftloc = (unsigned char*)(void*)&footerloc;
    infile << ftloc[3];
    infile << ftloc[2];
    infile << ftloc[1];
    infile << ftloc[0];
    infile << (unsigned char)0x03; //c07

    //no other modifications to the canister should happen after this point
    //also prevents double closure from a manual close() call and the automated one
    //coming from ~canister()
    readonly = true;
    return 0;
}

int libcanister::canister::open()
{
    //here we open the file associated with this canister
    canmem fspath = info.path;
    ifstream infile;
    infile.open(fspath.data);
    //now we begin creating the table of contents
    TOC.parent = this;
    TOC.path = canmem::null();
    TOC.cachestate = 1;
    TOC.cfid = -1;
    TOC.dsize = 0;
    //if the file didn't open, we need to do a
    //skeletal initialization of the canister
    if (!infile.is_open())
    {
        info.internalname = *(new canmem((char*)"generic canister"));
        info.numfiles = 0;
        canmem tocData;
        tocData.data = (char*)"";
        tocData.size = 0;
        TOC.data = tocData;
        return 0;
    }
    //otherwise, we're going to work on reading the file's
    //header and footer into memory
    else
    {
        //begin interpreting the file
        //lets make some temporary variables to store the header
        unsigned char temp1, temp2, temp3, temp4, temp5;
        readonly = false;
        infile >> temp1;
        infile >> temp2;
        infile >> temp3;
        infile >> temp4;
        infile >> temp5;
        //does the header match? (c00)
        if ((temp1 == 0x01) && (temp2 == 'c') && (temp3 == 'a') && (temp4 == 'n') && (temp5 == 0x01))
        {   //yes, valid header
            dout << "valid header" << endl;
            //read in the number of files
            info.numfiles = readint32(infile);
            dout << "numfiles: " << info.numfiles << endl;
            #warning "technically this should be a readint64, but seekg won't accept the 64-bit int. Solution needed."
            int footerloc = readint32(infile);
            infile.seekg(footerloc, ios::beg);
            //does the footer match?
            infile >> temp1;
            infile >> temp2;
            infile >> temp3;
            infile >> temp4;
            infile >> temp5;
            if ((temp1 == 0x01) && (temp2 == 'c') && (temp3 == 'a') && (temp4 == 'n') && (temp5 == 0x01))
            {   //yes, valid footer (c00)
                //create a file array to hold the files
                files = new canfile[info.numfiles];
                //set the internal name of the canister
                info.internalname = readstr(infile);
                dout << "internalname: " << info.internalname.data << endl;
                int i = 0;
                char* tocRaw = 0x0;
                int tocLen = 0;
                infile >> temp1;
                //loop through the file headers for each file
                while (temp1 == 0x01)
                {
                    //if we've exceeded the number of files and have found another
                    //then something fishy is happening somewhere... let's just
                    //use the info we have and ignore the other stuff in here
                    //Entering read only mode to prevent further damage to the canister
                    if (i >= info.numfiles)
                    {
                        cerr << "Corrupted Canister! Error message: File table length exceeds the number of files!" << endl;
                        cerr << "Best recovery option: read-only" << endl;
                        cerr << "Opening as read-only to prevent further damage to the canister." << endl;
                        readonly = true;
                        //loop to the end of the file header
                        while (temp1 != 0x03)
                            infile >> temp1;
                        break;
                    }

                    //read the file header
                    files[i].parent = this;
                    files[i].dsize = readint64(infile);
                    dout << "dsize: " << files[i].dsize << endl;
                    files[i].cfid = readint32(infile);
                    dout << "cfid: " << files[i].cfid << endl;
                    files[i].path = readstr(infile);
                    files[i].cachestate = 0;
                    files[i].data = canmem::null();
                    if (files[i].cfid & 0x80000000 || !strcmp(files[i].path.data, (char*)"FRAGMENT"))
                        files[i].isfrag = 1;
                    else
                    {
                        files[i].isfrag = 0;
                        //deal with the table of contents
                        int tLen = tocLen;
                        tocLen += files[i].path.size;
                        char* tmp = tocRaw;
                        tocRaw = new char[tocLen];
                        if (tLen > 0)
                            memcpy(tocRaw, tmp, tLen);
                        memcpy(tocRaw + tLen, files[i].path.data, files[i].path.size);
                        tocRaw[tocLen-1] = '\n';
                    }

                    //read the next file
                    i++;
                    infile >> temp1;
                }
                if (temp1 != 0x03)
                {
                    cerr << "Corrupted Canister! Error message: Incomplete file table! Data: " << (unsigned int)temp1 << " " << infile.tellg() << endl;
                    return -1;
                }
                if (tocLen > 0)
                    tocRaw[tocLen] = 0x00;
                else
                {
                    tocRaw = new char[1];
                    tocRaw[0] = 0x00;
                }
                canmem tocDat = *(new canmem(tocLen));
                tocDat.data = tocRaw;
                TOC.data = tocDat;

                infile.close();

                return 1;
            }
            else
            {
                cout << "Error: canister is corrupt." << endl;
                return -1;
            }
        }
        else
        {
            cout << "Error: canister is corrupt." << endl;
            return -1;
        }
    }
    return -1;
}

<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include "server/TSimpleServer.h"
#include "transport/TTransportException.h"
#include <string>
#include <iostream>

namespace apache { namespace thrift { namespace server {

using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using boost::shared_ptr;

/**
 * A simple single-threaded application server. Perfect for unit tests!
 *
 */
void TSimpleServer::serve() {

  shared_ptr<TTransport> client;
  shared_ptr<TTransport> inputTransport;
  shared_ptr<TTransport> outputTransport;
  shared_ptr<TProtocol> inputProtocol;
  shared_ptr<TProtocol> outputProtocol;

  try {
    // Start the server listening
    serverTransport_->listen();
  } catch (TTransportException& ttx) {
    string errStr = string("TSimpleServer::run() listen(): ") + ttx.what();
    GlobalOutput(errStr.c_str());
    return;
  }

  // Run the preServe event
  if (eventHandler_ != NULL) {
    eventHandler_->preServe();
  }

  // Fetch client from server
  while (!stop_) {
    try {
      client = serverTransport_->accept();
      inputTransport = inputTransportFactory_->getTransport(client);
      outputTransport = outputTransportFactory_->getTransport(client);
      inputProtocol = inputProtocolFactory_->getProtocol(inputTransport);
      outputProtocol = outputProtocolFactory_->getProtocol(outputTransport);
    } catch (TTransportException& ttx) {
      if (inputTransport != NULL) { inputTransport->close(); }
      if (outputTransport != NULL) { outputTransport->close(); }
      if (client != NULL) { client->close(); }
      string errStr = string("TServerTransport died on accept: ") + ttx.what();
      GlobalOutput(errStr.c_str());
      continue;
    } catch (TException& tx) {
      if (inputTransport != NULL) { inputTransport->close(); }
      if (outputTransport != NULL) { outputTransport->close(); }
      if (client != NULL) { client->close(); }
      string errStr = string("Some kind of accept exception: ") + tx.what();
      GlobalOutput(errStr.c_str());
      continue;
    } catch (string s) {
      if (inputTransport != NULL) { inputTransport->close(); }
      if (outputTransport != NULL) { outputTransport->close(); }
      if (client != NULL) { client->close(); }
      string errStr = string("Some kind of accept exception: ") + s;
      GlobalOutput(errStr.c_str());
      break;
    }

    // Get the processor
    shared_ptr<TProcessor> processor = getProcessor(inputProtocol,
                                                    outputProtocol, client);

    void* connectionContext = NULL;
    if (eventHandler_ != NULL) {
      connectionContext = eventHandler_->createContext(inputProtocol, outputProtocol);
    }
    try {
      for (;;) {
        if (eventHandler_ != NULL) {
          eventHandler_->processContext(connectionContext, client);
        }
        if (!processor->process(inputProtocol, outputProtocol,
                                connectionContext) ||
          // Peek ahead, is the remote side closed?
            !inputProtocol->getTransport()->peek()) {
          break;
        }
      }
    } catch (const TTransportException& ttx) {
      string errStr = string("TSimpleServer client died: ") + ttx.what();
      GlobalOutput(errStr.c_str());
    } catch (const std::exception& x) {
      GlobalOutput.printf("TSimpleServer exception: %s: %s",
                          typeid(x).name(), x.what());
    } catch (...) {
      GlobalOutput("TSimpleServer uncaught exception.");
    }
    if (eventHandler_ != NULL) {
      eventHandler_->deleteContext(connectionContext, inputProtocol, outputProtocol);
    }

    try {
      inputTransport->close();
    } catch (const TTransportException& ttx) {
      string errStr = string("TSimpleServer input close failed: ")
        + ttx.what();
      GlobalOutput(errStr.c_str());
    }
    try {
      outputTransport->close();
    } catch (const TTransportException& ttx) {
      string errStr = string("TSimpleServer output close failed: ")
        + ttx.what();
      GlobalOutput(errStr.c_str());
    }
    try {
      client->close();
    } catch (const TTransportException& ttx) {
      string errStr = string("TSimpleServer client close failed: ")
        + ttx.what();
      GlobalOutput(errStr.c_str());
    }
  }

  if (stop_) {
    try {
      serverTransport_->close();
    } catch (TTransportException &ttx) {
      string errStr = string("TServerTransport failed on close: ") + ttx.what();
      GlobalOutput(errStr.c_str());
    }
    stop_ = false;
  }
}

}}} // apache::thrift::server
<commit_msg>Thrift-1502:TSimpleServer::serve(): Do not print out error message if server was stopped. Client: cpp Patch: Vibhav Sreekanti<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include "server/TSimpleServer.h"
#include "transport/TTransportException.h"
#include <string>
#include <iostream>

namespace apache { namespace thrift { namespace server {

using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using boost::shared_ptr;

/**
 * A simple single-threaded application server. Perfect for unit tests!
 *
 */
void TSimpleServer::serve() {

  shared_ptr<TTransport> client;
  shared_ptr<TTransport> inputTransport;
  shared_ptr<TTransport> outputTransport;
  shared_ptr<TProtocol> inputProtocol;
  shared_ptr<TProtocol> outputProtocol;

  try {
    // Start the server listening
    serverTransport_->listen();
  } catch (TTransportException& ttx) {
    string errStr = string("TSimpleServer::run() listen(): ") + ttx.what();
    GlobalOutput(errStr.c_str());
    return;
  }

  // Run the preServe event
  if (eventHandler_ != NULL) {
    eventHandler_->preServe();
  }

  // Fetch client from server
  while (!stop_) {
    try {
      client = serverTransport_->accept();
      inputTransport = inputTransportFactory_->getTransport(client);
      outputTransport = outputTransportFactory_->getTransport(client);
      inputProtocol = inputProtocolFactory_->getProtocol(inputTransport);
      outputProtocol = outputProtocolFactory_->getProtocol(outputTransport);
    } catch (TTransportException& ttx) {
      if (inputTransport != NULL) { inputTransport->close(); }
      if (outputTransport != NULL) { outputTransport->close(); }
      if (client != NULL) { client->close(); }
      if (!stop_ || ttx.getType() != TTransportException::INTERRUPTED) {
          string errStr = string("TServerTransport died on accept: ") + ttx.what();
          GlobalOutput(errStr.c_str());
      }
      continue;
    } catch (TException& tx) {
      if (inputTransport != NULL) { inputTransport->close(); }
      if (outputTransport != NULL) { outputTransport->close(); }
      if (client != NULL) { client->close(); }
      string errStr = string("Some kind of accept exception: ") + tx.what();
      GlobalOutput(errStr.c_str());
      continue;
    } catch (string s) {
      if (inputTransport != NULL) { inputTransport->close(); }
      if (outputTransport != NULL) { outputTransport->close(); }
      if (client != NULL) { client->close(); }
      string errStr = string("Some kind of accept exception: ") + s;
      GlobalOutput(errStr.c_str());
      break;
    }

    // Get the processor
    shared_ptr<TProcessor> processor = getProcessor(inputProtocol,
                                                    outputProtocol, client);

    void* connectionContext = NULL;
    if (eventHandler_ != NULL) {
      connectionContext = eventHandler_->createContext(inputProtocol, outputProtocol);
    }
    try {
      for (;;) {
        if (eventHandler_ != NULL) {
          eventHandler_->processContext(connectionContext, client);
        }
        if (!processor->process(inputProtocol, outputProtocol,
                                connectionContext) ||
          // Peek ahead, is the remote side closed?
            !inputProtocol->getTransport()->peek()) {
          break;
        }
      }
    } catch (const TTransportException& ttx) {
      string errStr = string("TSimpleServer client died: ") + ttx.what();
      GlobalOutput(errStr.c_str());
    } catch (const std::exception& x) {
      GlobalOutput.printf("TSimpleServer exception: %s: %s",
                          typeid(x).name(), x.what());
    } catch (...) {
      GlobalOutput("TSimpleServer uncaught exception.");
    }
    if (eventHandler_ != NULL) {
      eventHandler_->deleteContext(connectionContext, inputProtocol, outputProtocol);
    }

    try {
      inputTransport->close();
    } catch (const TTransportException& ttx) {
      string errStr = string("TSimpleServer input close failed: ")
        + ttx.what();
      GlobalOutput(errStr.c_str());
    }
    try {
      outputTransport->close();
    } catch (const TTransportException& ttx) {
      string errStr = string("TSimpleServer output close failed: ")
        + ttx.what();
      GlobalOutput(errStr.c_str());
    }
    try {
      client->close();
    } catch (const TTransportException& ttx) {
      string errStr = string("TSimpleServer client close failed: ")
        + ttx.what();
      GlobalOutput(errStr.c_str());
    }
  }

  if (stop_) {
    try {
      serverTransport_->close();
    } catch (TTransportException &ttx) {
      string errStr = string("TServerTransport failed on close: ") + ttx.what();
      GlobalOutput(errStr.c_str());
    }
    stop_ = false;
  }
}

}}} // apache::thrift::server
<|endoftext|>


<commit_before>// runV0ChCorrelations.C
//
// AddTask for AliAnalysisTaskV0ChCorrelations task
//
AliAnalysisTaskV0ChCorrelations *AddTaskV0ChCorrelations(const Bool_t bMCtruth=kFALSE,
														 Float_t DcaDToPV = 0.1,
														 Float_t DcaV0D = 1.0
														)
{
  // Creates a V0Ch correlations analysis task and adds it to the analysis manager.

  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================

    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
    if (!mgr) {
      ::Error("AddTaskV0ChCorrelations", "No analysis manager to connect to.");
      return NULL;
    }

    // mc event handlerrunEx01.C
    if(bMCtruth) {
        AliMCEventHandler* mchandler = new AliMCEventHandler();
        // Not reading track references
        mchandler->SetReadTR(kFALSE);
        mgr->SetMCtruthEventHandler(mchandler);
    }

	// create task
    AliAnalysisTaskV0ChCorrelations* task = new AliAnalysisTaskV0ChCorrelations("V0ChCorrelations_task");
	task->SetDcaDToPV(DcaDToPV);
	task->SetDcaV0D(DcaV0D);
    mgr->AddTask(task);

    // Create ONLY the output containers for the data produced by the task.
    // Get and connect other common input/output containers via the manager as below
    //==============================================================================
    TString outputFileName = AliAnalysisManager::GetCommonFileName();
   // outputFileName = "list.grid.v0ch.root";

    // create containers for input/output
    AliAnalysisDataContainer *cinput = mgr->GetCommonInputContainer();
    AliAnalysisDataContainer *coutput1 = mgr->CreateContainer("coutput1", TList::Class(), AliAnalysisManager::kOutputContainer, outputFileName);

    // connect input/output
    mgr->ConnectInput(task, 0, cinput);
    mgr->ConnectOutput(task, 1, coutput1);

    // Return task pointer at the end
    return task;
}

<commit_msg><commit_after>// runV0ChCorrelations.C
//
// AddTask for AliAnalysisTaskV0ChCorrelations task
//
AliAnalysisTaskV0ChCorrelations *AddTaskV0ChCorrelations(const char * outfilename,
													     const Bool_t bMCtruth=kTRUE,
														 Float_t DcaDToPV = 0.05,
														 Float_t DcaV0D = 3.0,
														 const Bool_t bChCh=kTRUE,
														 Int_t OStatus
														)
{
  // Creates a V0Ch correlations analysis task and adds it to the analysis manager.

  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================

    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
    if (!mgr) {
      ::Error("AddTaskV0ChCorrelations", "No analysis manager to connect to.");
      return NULL;
    }

    // mc event handlerrunEx01.C
    /*
	if(bMCtruth) {
		cout << "I am here too! " << endl;
        AliAODMCEventHandler* mchandler = new AliAODMCEventHandler();
        // Not reading track references
        mchandler->SetReadTR(kFALSE);
        mgr->SetMCtruthEventHandler(mchandler);
    }
*/
	// create task
    AliAnalysisTaskV0ChCorrelations* task = new AliAnalysisTaskV0ChCorrelations("V0ChCorrelations_task");
    task->SetAnalysisMC(bMCtruth);
	task->SetDcaDToPV(DcaDToPV);
	task->SetDcaV0D(DcaV0D);
	task->SetWithChCh(bChCh);
	task->SetOStatus(OStatus);
    mgr->AddTask(task);

    // Create ONLY the output containers for the data produced by the task.
    // Get and connect other common input/output containers via the manager as below
    //==============================================================================
    TString outputFileName = AliAnalysisManager::GetCommonFileName();
    //outputFileName = "list.grid.v0ch.root";

    // create containers for input/output
    AliAnalysisDataContainer *cinput = mgr->GetCommonInputContainer();
    AliAnalysisDataContainer *coutput1 = mgr->CreateContainer(outfilename, TList::Class(), AliAnalysisManager::kOutputContainer, outputFileName);

    // connect input/output
    mgr->ConnectInput(task, 0, cinput);
    mgr->ConnectOutput(task, 1, coutput1);

    // Return task pointer at the end
    return task;
}

<|endoftext|>


<commit_before>/******************************************************************************
** Copyright (c) 2013-2015, Intel Corporation                                **
** 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 of the copyright holder 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      **
** HOLDER 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.              **
******************************************************************************/
/* Hans Pabst (Intel Corp.)
******************************************************************************/
#include <libxsmm.h>
#include <libxsmm_timer.h>

#if defined(LIBXSMM_OFFLOAD_BUILD)
# pragma offload_attribute(push,target(LIBXSMM_OFFLOAD_TARGET))
#endif

#include <algorithm>
#include <stdexcept>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <cmath>

#if defined(USE_MKL) || defined(MKL_DIRECT_CALL_SEQ) || defined(MKL_DIRECT_CALL)
# include <mkl_service.h>
#endif

#if defined(_OPENMP)
# include <omp.h>
#endif

#if defined(LIBXSMM_OFFLOAD_BUILD)
# pragma offload_attribute(pop)
#endif

#define MAX_SIZE (80 * 80)

template<int Seed>
struct LIBXSMM_RETARGETABLE init {
  template<typename T> init(T *LIBXSMM_RESTRICT dst, int nrows, int ncols, int n = 0, int ld = 0) {
    const int ldx = 0 == ld ? ncols : ld;
    const int minval = n + Seed, addval = (nrows - 1) * ldx + (ncols - 1);
    const int maxval = std::max(std::abs(minval), addval);
    const double norm = 0 != maxval ? (1.0 / maxval) : 1.0;
    for (int i = 0; i < nrows; ++i) {
      for (int j = 0; j < ncols; ++j) {
        const double value = static_cast<double>(i * ldx + j + minval);
        dst[i*ldx+j] = static_cast<T>(norm * (value - 0.5 * addval));
      }
    }
  }
};

int main(int argc, char* argv[])
{
  try {
    typedef double T;
    const int m = 1 < argc ? std::atoi(argv[1]) : 23;
    const int n = 2 < argc ? std::atoi(argv[2]) : m;
    const int k = 3 < argc ? std::atoi(argv[3]) : m;

    const int csize = m * n;
    if ((MAX_SIZE) < csize) {
      throw std::runtime_error("The size M x N is exceeding MAX_SIZE!");
    }

    const int asize = m * k, bsize = k * n, aspace = (LIBXSMM_ALIGNED_MAX) / sizeof(T);
    const int ldc = LIBXSMM_ALIGN_STORES(LIBXSMM_LD(m, n), sizeof(T));
    const int csize_act = ldc*n;
    const int s = (2ULL << 30) / ((asize + bsize + csize_act) * sizeof(T)); // 2 GByte
    const size_t bwsize_batched = (asize/*load*/ + bsize/*load*/ + 2*csize_act /*RFO*/) * sizeof(T); // batched
    const size_t bwsize = (asize/*load*/ + bsize/*load*/) * sizeof(T); // streamed, we skip C as this just in cache
    const double gflops = 2.0 * s * m * n * k * 1E-9;

    struct raii { // avoid std::vector (first-touch init. causes NUMA issue)
      T *a, *b, *c;
      raii(int asize, int bsize, int csize_act): a(new T[asize]), b(new T[bsize]), c(new T[csize_act]) {}
      ~raii() { delete[] a; delete[] b; delete[] c; }
    } buffer(s * asize + aspace - 1, s * bsize + aspace - 1, s * csize_act + aspace - 1);
    T *const a = LIBXSMM_ALIGN(buffer.a, LIBXSMM_ALIGNED_MAX);
    T *const b = LIBXSMM_ALIGN(buffer.b, LIBXSMM_ALIGNED_MAX);
    T *c = LIBXSMM_ALIGN(buffer.c, LIBXSMM_ALIGNED_MAX);

#if defined(_OPENMP)
#   pragma omp parallel for
#endif
    for (int i = 0; i < s; ++i) {
      init<42>(a + i * asize, m, k, i);
      init<24>(b + i * bsize, k, n, i);
      init<22>(c + i * csize_act, ldc, n, i);
    }

#if defined(LIBXSMM_OFFLOAD_BUILD)
#   pragma offload target(LIBXSMM_OFFLOAD_TARGET) in(a: length(s * asize)) in(b: length(s * bsize)) inout(c: length(s * csize_act))
#endif
    {
#if defined(MKL_ENABLE_AVX512_MIC)
      mkl_enable_instructions(MKL_ENABLE_AVX512_MIC);
#endif
      // initialize LIBXSMM
      libxsmm_init();

      fprintf(stdout, "m=%i n=%i k=%i ldc=%i (%s) size=%i memory=%.f MB\n\n",
        m, n, k, ldc, 0 != (LIBXSMM_ROW_MAJOR) ? "row-major" : "column-major",
        s, 1.0 * s * (asize + bsize + csize_act) * sizeof(T) / (1 << 20));

      { // batched
        fprintf(stdout, "Batched (A,B,C)...\n");
        const unsigned long long start = libxsmm_timer_tick();
#if defined(_OPENMP)
#       pragma omp parallel for
#endif
        for (int i = 0; i < s; ++i) {
          const T *const pa = a + i * asize, *const pb = b + i * bsize;
          T* pc = c + i * csize_act;
          libxsmm_imm(m, n, k, pa, pb, pc);
        }
        const double duration = libxsmm_timer_duration(start, libxsmm_timer_tick());
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
          fprintf(stdout, "\tbandwidth: %.1f GB/s\n", s * bwsize_batched / (duration * (1 << 30)));
        }
        fprintf(stdout, "\tduration: %.0f ms\n", 1000.0 * duration);
      }

      { // streaming
        fprintf(stdout, "Streamed (A,B)...\n");
        const unsigned long long start = libxsmm_timer_tick();
#if defined(_OPENMP)
#       pragma omp parallel for
#endif
        for (int i = 0; i < s; ++i) {
          // make sure that stacksize is covering the problem size; tmp is zero-initialized by lang. rules
          LIBXSMM_ALIGNED(T tmp[MAX_SIZE], LIBXSMM_ALIGNED_MAX);
          const T *const pa = a + i * asize, *const pb = b + i * bsize;
          libxsmm_imm(m, n, k, pa, pb, tmp);
        }
        const double duration = libxsmm_timer_duration(start, libxsmm_timer_tick());
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
          fprintf(stdout, "\tbandwidth: %.1f GB/s\n", s * bwsize / (duration * (1 << 30)));
        }
        fprintf(stdout, "\tduration: %.0f ms\n", 1000.0 * duration);
      }

      { // cached
        fprintf(stdout, "Cached...\n");
        const unsigned long long start = libxsmm_timer_tick();
#if defined(_OPENMP)
#       pragma omp parallel for
#endif
        for (int i = 0; i < s; ++i) {
          // make sure that stacksize is covering the problem size; tmp is zero-initialized by lang. rules
          LIBXSMM_ALIGNED(T tmp[MAX_SIZE], LIBXSMM_ALIGNED_MAX);
          // do nothing else with tmp; just a benchmark
          libxsmm_imm(m, n, k, a, b, tmp);
        }
        const double duration = libxsmm_timer_duration(start, libxsmm_timer_tick());
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
        }
        fprintf(stdout, "\tduration: %.0f ms\n", 1000.0 * duration);
      }

      fprintf(stdout, "Finished\n");
    }
  }
  catch(const std::exception& e) {
    fprintf(stderr, "Error: %s\n", e.what());
    return EXIT_FAILURE;
  }
  catch(...) {
    fprintf(stderr, "Error: unknown exception caught!\n");
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
<commit_msg>Call LIBXSMM_XIMM rather than libxsmm_imm since the latter was removed as part of resolving issue #35.<commit_after>/******************************************************************************
** Copyright (c) 2013-2015, Intel Corporation                                **
** 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 of the copyright holder 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      **
** HOLDER 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.              **
******************************************************************************/
/* Hans Pabst (Intel Corp.)
******************************************************************************/
#include <libxsmm.h>
#include <libxsmm_timer.h>

#if defined(LIBXSMM_OFFLOAD_BUILD)
# pragma offload_attribute(push,target(LIBXSMM_OFFLOAD_TARGET))
#endif

#include <algorithm>
#include <stdexcept>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <cmath>

#if defined(USE_MKL) || defined(MKL_DIRECT_CALL_SEQ) || defined(MKL_DIRECT_CALL)
# include <mkl_service.h>
#endif

#if defined(_OPENMP)
# include <omp.h>
#endif

#if defined(LIBXSMM_OFFLOAD_BUILD)
# pragma offload_attribute(pop)
#endif

#define MAX_SIZE (80 * 80)

template<int Seed>
struct LIBXSMM_RETARGETABLE init {
  template<typename T> init(T *LIBXSMM_RESTRICT dst, int nrows, int ncols, int n = 0, int ld = 0) {
    const int ldx = 0 == ld ? ncols : ld;
    const int minval = n + Seed, addval = (nrows - 1) * ldx + (ncols - 1);
    const int maxval = std::max(std::abs(minval), addval);
    const double norm = 0 != maxval ? (1.0 / maxval) : 1.0;
    for (int i = 0; i < nrows; ++i) {
      for (int j = 0; j < ncols; ++j) {
        const double value = static_cast<double>(i * ldx + j + minval);
        dst[i*ldx+j] = static_cast<T>(norm * (value - 0.5 * addval));
      }
    }
  }
};

int main(int argc, char* argv[])
{
  try {
    typedef double T;
    const int m = 1 < argc ? std::atoi(argv[1]) : 23;
    const int n = 2 < argc ? std::atoi(argv[2]) : m;
    const int k = 3 < argc ? std::atoi(argv[3]) : m;

    const int csize = m * n;
    if ((MAX_SIZE) < csize) {
      throw std::runtime_error("The size M x N is exceeding MAX_SIZE!");
    }

    const int asize = m * k, bsize = k * n, aspace = (LIBXSMM_ALIGNED_MAX) / sizeof(T);
    const int ldc = LIBXSMM_ALIGN_STORES(LIBXSMM_LD(m, n), sizeof(T));
    const int csize_act = ldc*n;
    const int s = (2ULL << 30) / ((asize + bsize + csize_act) * sizeof(T)); // 2 GByte
    const size_t bwsize_batched = (asize/*load*/ + bsize/*load*/ + 2*csize_act /*RFO*/) * sizeof(T); // batched
    const size_t bwsize = (asize/*load*/ + bsize/*load*/) * sizeof(T); // streamed, we skip C as this just in cache
    const double gflops = 2.0 * s * m * n * k * 1E-9;

    struct raii { // avoid std::vector (first-touch init. causes NUMA issue)
      T *a, *b, *c;
      raii(int asize, int bsize, int csize_act): a(new T[asize]), b(new T[bsize]), c(new T[csize_act]) {}
      ~raii() { delete[] a; delete[] b; delete[] c; }
    } buffer(s * asize + aspace - 1, s * bsize + aspace - 1, s * csize_act + aspace - 1);
    T *const a = LIBXSMM_ALIGN(buffer.a, LIBXSMM_ALIGNED_MAX);
    T *const b = LIBXSMM_ALIGN(buffer.b, LIBXSMM_ALIGNED_MAX);
    T *c = LIBXSMM_ALIGN(buffer.c, LIBXSMM_ALIGNED_MAX);

#if defined(_OPENMP)
#   pragma omp parallel for
#endif
    for (int i = 0; i < s; ++i) {
      init<42>(a + i * asize, m, k, i);
      init<24>(b + i * bsize, k, n, i);
      init<22>(c + i * csize_act, ldc, n, i);
    }

#if defined(LIBXSMM_OFFLOAD_BUILD)
#   pragma offload target(LIBXSMM_OFFLOAD_TARGET) in(a: length(s * asize)) in(b: length(s * bsize)) inout(c: length(s * csize_act))
#endif
    {
#if defined(MKL_ENABLE_AVX512_MIC)
      mkl_enable_instructions(MKL_ENABLE_AVX512_MIC);
#endif
      // initialize LIBXSMM
      libxsmm_init();

      fprintf(stdout, "m=%i n=%i k=%i ldc=%i (%s) size=%i memory=%.f MB\n\n",
        m, n, k, ldc, 0 != (LIBXSMM_ROW_MAJOR) ? "row-major" : "column-major",
        s, 1.0 * s * (asize + bsize + csize_act) * sizeof(T) / (1 << 20));

      { // batched
        fprintf(stdout, "Batched (A,B,C)...\n");
        const unsigned long long start = libxsmm_timer_tick();
#if defined(_OPENMP)
#       pragma omp parallel for
#endif
        for (int i = 0; i < s; ++i) {
          const T *const pa = a + i * asize, *const pb = b + i * bsize;
          T* pc = c + i * csize_act;
          LIBXSMM_XIMM(m, n, k, pa, pb, pc, 0);
        }
        const double duration = libxsmm_timer_duration(start, libxsmm_timer_tick());
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
          fprintf(stdout, "\tbandwidth: %.1f GB/s\n", s * bwsize_batched / (duration * (1 << 30)));
        }
        fprintf(stdout, "\tduration: %.0f ms\n", 1000.0 * duration);
      }

      { // streaming
        fprintf(stdout, "Streamed (A,B)...\n");
        const unsigned long long start = libxsmm_timer_tick();
#if defined(_OPENMP)
#       pragma omp parallel for
#endif
        for (int i = 0; i < s; ++i) {
          // make sure that stacksize is covering the problem size; tmp is zero-initialized by lang. rules
          LIBXSMM_ALIGNED(T tmp[MAX_SIZE], LIBXSMM_ALIGNED_MAX);
          const T *const pa = a + i * asize, *const pb = b + i * bsize;
          LIBXSMM_XIMM(m, n, k, pa, pb, tmp, 0);
        }
        const double duration = libxsmm_timer_duration(start, libxsmm_timer_tick());
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
          fprintf(stdout, "\tbandwidth: %.1f GB/s\n", s * bwsize / (duration * (1 << 30)));
        }
        fprintf(stdout, "\tduration: %.0f ms\n", 1000.0 * duration);
      }

      { // cached
        fprintf(stdout, "Cached...\n");
        const unsigned long long start = libxsmm_timer_tick();
#if defined(_OPENMP)
#       pragma omp parallel for
#endif
        for (int i = 0; i < s; ++i) {
          // make sure that stacksize is covering the problem size; tmp is zero-initialized by lang. rules
          LIBXSMM_ALIGNED(T tmp[MAX_SIZE], LIBXSMM_ALIGNED_MAX);
          // do nothing else with tmp; just a benchmark
          LIBXSMM_XIMM(m, n, k, a, b, tmp, 0);
        }
        const double duration = libxsmm_timer_duration(start, libxsmm_timer_tick());
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
        }
        fprintf(stdout, "\tduration: %.0f ms\n", 1000.0 * duration);
      }

      fprintf(stdout, "Finished\n");
    }
  }
  catch(const std::exception& e) {
    fprintf(stderr, "Error: %s\n", e.what());
    return EXIT_FAILURE;
  }
  catch(...) {
    fprintf(stderr, "Error: unknown exception caught!\n");
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
    This file is part of Kontact.
    Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>

    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 2 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, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/
#include <qimage.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qtooltip.h>

#include <dcopclient.h>
#include <dcopref.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kglobal.h>
#include <kglobalsettings.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kurllabel.h>

#include "summarywidget.h"

SummaryWidget::SummaryWidget( QWidget *parent, const char *name )
  : Kontact::Summary( parent, name ),
    DCOPObject( "WeatherSummaryWidget" ), mProc( 0 )
{
  mLayout = new QVBoxLayout( this, 3, 3 );
  mLayout->setAlignment( Qt::AlignTop );

  QPixmap icon = KGlobal::iconLoader()->loadIcon( "kweather", KIcon::Desktop, KIcon::SizeMedium );
  QWidget *header = createHeader( this, icon, i18n( "Weather Information" ) );
  mLayout->addWidget( header );

  QString error;
  QCString appID;
  bool serviceAvailable = true;
  if ( !kapp->dcopClient()->isApplicationRegistered( "KWeatherService" ) ) {
    if ( KApplication::startServiceByDesktopName( "kweatherservice", QStringList(), &error, &appID ) ) {
      QLabel *label = new QLabel( i18n( "No weather dcop service available;\nyou need KWeather to use this plugin." ), this );
      mLayout->addWidget( label, Qt::AlignHCenter );
      serviceAvailable = false;
    }
  }

  if ( serviceAvailable ) {
    connectDCOPSignal( 0, 0, "fileUpdate(QString)", "refresh(QString)", false );
    connectDCOPSignal( 0, 0, "stationRemoved(QString)", "stationRemoved(QString)", false );

    DCOPRef dcopCall( "KWeatherService", "WeatherService" );
    DCOPReply reply = dcopCall.call( "listStations()", true );
    if ( reply.isValid() ) {
      mStations = reply;

      connect( &mTimer, SIGNAL( timeout() ), this, SLOT( timeout() ) );
      mTimer.start( 0 );
    } else {
      kdDebug(5602) << "ERROR: dcop reply not valid..." << endl;
    }
  }
}

void SummaryWidget::updateView()
{
  mLayouts.setAutoDelete( true );
  mLayouts.clear();
  mLayouts.setAutoDelete( false );

  mLabels.setAutoDelete( true );
  mLabels.clear();
  mLabels.setAutoDelete( false );

  if ( mStations.count() == 0 ) {
    kdDebug(5602) << "No weather stations defined..." << endl;
    return;
  }

  QValueList<WeatherData> dataList = mWeatherMap.values();
  qHeapSort( dataList );

  QValueList<WeatherData>::Iterator it;
  for ( it = dataList.begin(); it != dataList.end(); ++it ) {
    QString cover;
    for ( uint i = 0; i < (*it).cover().count(); ++i )
      cover += QString( "- %1\n" ).arg( (*it).cover()[ i ] );

    QImage img;
    img = (*it).icon();

    QGridLayout *layout = new QGridLayout( mLayout, 3, 3, 3 );
    mLayouts.append( layout );

    KURLLabel* urlLabel = new KURLLabel(this);
    urlLabel->installEventFilter(this);
    urlLabel->setURL((*it).stationID());
    urlLabel->setPixmap( img.smoothScale( 32, 32 ) );
    urlLabel->setMaximumSize(urlLabel->sizeHint());
    urlLabel->setAlignment(/* AlignRight |*/ AlignTop );
    layout->addMultiCellWidget( urlLabel, 0, 1, 0, 0 );
    mLabels.append( urlLabel );
    connect (urlLabel, SIGNAL(leftClickedURL( const QString&) ),
    	this, SLOT(slotShowReport(const QString& )));

    QLabel* label = new QLabel( this );
    label->setText( QString( "%1 (%2)" ).arg( (*it).name() ).arg( (*it).temperature() ) );
    QFont font = label->font();
    font.setBold( true );
    label->setFont( font );
    label->setAlignment( AlignLeft );
    layout->addMultiCellWidget( label, 0, 0, 1, 2 );
    mLabels.append( label );

    QString labelText;
    labelText = QString( "%1: %2
"
                         "%3: %4" )
                         .arg( i18n( "Wind Speed" ) )
                         .arg( (*it).windSpeed() )
                         .arg( i18n( "Rel. Humidity" ) )
                         .arg( (*it).relativeHumidity() );

    QToolTip::add( label, labelText.replace( " ", " " ) );

    label = new QLabel( cover, this );
    label->setAlignment( AlignLeft );
    layout->addMultiCellWidget( label, 1, 1, 1, 2 );
    mLabels.append( label );
  }

  for ( QLabel *label = mLabels.first(); label; label = mLabels.next() )
    label->show();

  mLayout->addStretch( 1 );
}

void SummaryWidget::timeout()
{
  mTimer.stop();

  DCOPRef dcopCall( "KWeatherService", "WeatherService" );
  dcopCall.send( "updateAll()" );

  mTimer.start( 15 * 60000 );
}

void SummaryWidget::refresh( QString station )
{
  DCOPRef dcopCall( "KWeatherService", "WeatherService" );

  mWeatherMap[ station ].setIcon( dcopCall.call( "currentIcon(QString)", station, true ) );
  mWeatherMap[ station ].setName( dcopCall.call( "stationName(QString)", station, true ) );
  mWeatherMap[ station ].setCover( dcopCall.call( "cover(QString)", station, true ) );
  mWeatherMap[ station ].setTemperature( dcopCall.call( "temperature(QString)", station, true ) );
  mWeatherMap[ station ].setWindSpeed( dcopCall.call( "wind(QString)", station, true ) );
  mWeatherMap[ station ].setRelativeHumidity( dcopCall.call( "relativeHumidity(QString)", station, true ) );
  mWeatherMap[ station ].setStationID(station);

  updateView();
}

void SummaryWidget::stationRemoved( QString station )
{
  mWeatherMap.remove( station );
  updateView();
}

QStringList SummaryWidget::configModules() const
{
  return QStringList( "kcmweatherservice.desktop" );
}

void SummaryWidget::slotShowReport(const QString &stationID)
{
  mProc = new KProcess;
  QApplication::connect(mProc, SIGNAL(processExited(KProcess *)),
	this, SLOT(slotReportFinished(KProcess* )));
  *mProc << "kweatherreport";
  *mProc << stationID;
  if ( !mProc->start() )
  {
    delete mProc;
    mProc=0;
  }
}

void SummaryWidget::slotReportFinished(KProcess* /*proc*/){
  delete mProc;
 mProc = 0;
}

#include "summarywidget.moc"
<commit_msg>Remove spacer to avoid empty space between the plugin header and the KURL's approved by: Reinhold<commit_after>/*
    This file is part of Kontact.
    Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>

    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 2 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, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/
#include <qimage.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qtooltip.h>

#include <dcopclient.h>
#include <dcopref.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kglobal.h>
#include <kglobalsettings.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kurllabel.h>

#include "summarywidget.h"

SummaryWidget::SummaryWidget( QWidget *parent, const char *name )
  : Kontact::Summary( parent, name ),
    DCOPObject( "WeatherSummaryWidget" ), mProc( 0 )
{
  mLayout = new QVBoxLayout( this, 3, 3 );
  mLayout->setAlignment( Qt::AlignTop );

  QPixmap icon = KGlobal::iconLoader()->loadIcon( "kweather", KIcon::Desktop, KIcon::SizeMedium );
  QWidget *header = createHeader( this, icon, i18n( "Weather Information" ) );
  mLayout->addWidget( header );

  QString error;
  QCString appID;
  bool serviceAvailable = true;
  if ( !kapp->dcopClient()->isApplicationRegistered( "KWeatherService" ) ) {
    if ( KApplication::startServiceByDesktopName( "kweatherservice", QStringList(), &error, &appID ) ) {
      QLabel *label = new QLabel( i18n( "No weather dcop service available;\nyou need KWeather to use this plugin." ), this );
      mLayout->addWidget( label, Qt::AlignHCenter );
      serviceAvailable = false;
    }
  }

  if ( serviceAvailable ) {
    connectDCOPSignal( 0, 0, "fileUpdate(QString)", "refresh(QString)", false );
    connectDCOPSignal( 0, 0, "stationRemoved(QString)", "stationRemoved(QString)", false );

    DCOPRef dcopCall( "KWeatherService", "WeatherService" );
    DCOPReply reply = dcopCall.call( "listStations()", true );
    if ( reply.isValid() ) {
      mStations = reply;

      connect( &mTimer, SIGNAL( timeout() ), this, SLOT( timeout() ) );
      mTimer.start( 0 );
    } else {
      kdDebug(5602) << "ERROR: dcop reply not valid..." << endl;
    }
  }
}

void SummaryWidget::updateView()
{
  mLayouts.setAutoDelete( true );
  mLayouts.clear();
  mLayouts.setAutoDelete( false );

  mLabels.setAutoDelete( true );
  mLabels.clear();
  mLabels.setAutoDelete( false );

  if ( mStations.count() == 0 ) {
    kdDebug(5602) << "No weather stations defined..." << endl;
    return;
  }

  QValueList<WeatherData> dataList = mWeatherMap.values();
  qHeapSort( dataList );

  QValueList<WeatherData>::Iterator it;
  for ( it = dataList.begin(); it != dataList.end(); ++it ) {
    QString cover;
    for ( uint i = 0; i < (*it).cover().count(); ++i )
      cover += QString( "- %1\n" ).arg( (*it).cover()[ i ] );

    QImage img;
    img = (*it).icon();

    QGridLayout *layout = new QGridLayout( mLayout, 3, 3, 3 );
    mLayouts.append( layout );

    KURLLabel* urlLabel = new KURLLabel(this);
    urlLabel->installEventFilter(this);
    urlLabel->setURL((*it).stationID());
    urlLabel->setPixmap( img.smoothScale( 32, 32 ) );
    urlLabel->setMaximumSize(urlLabel->sizeHint());
    urlLabel->setAlignment(/* AlignRight |*/ AlignTop );
    layout->addMultiCellWidget( urlLabel, 0, 1, 0, 0 );
    mLabels.append( urlLabel );
    connect (urlLabel, SIGNAL(leftClickedURL( const QString&) ),
    	this, SLOT(slotShowReport(const QString& )));

    QLabel* label = new QLabel( this );
    label->setText( QString( "%1 (%2)" ).arg( (*it).name() ).arg( (*it).temperature() ) );
    QFont font = label->font();
    font.setBold( true );
    label->setFont( font );
    label->setAlignment( AlignLeft );
    layout->addMultiCellWidget( label, 0, 0, 1, 2 );
    mLabels.append( label );

    QString labelText;
    labelText = QString( "%1: %2
"
                         "%3: %4" )
                         .arg( i18n( "Wind Speed" ) )
                         .arg( (*it).windSpeed() )
                         .arg( i18n( "Rel. Humidity" ) )
                         .arg( (*it).relativeHumidity() );

    QToolTip::add( label, labelText.replace( " ", " " ) );

    label = new QLabel( cover, this );
    label->setAlignment( AlignLeft );
    layout->addMultiCellWidget( label, 1, 1, 1, 2 );
    mLabels.append( label );
  }

  for ( QLabel *label = mLabels.first(); label; label = mLabels.next() )
    label->show();
}

void SummaryWidget::timeout()
{
  mTimer.stop();

  DCOPRef dcopCall( "KWeatherService", "WeatherService" );
  dcopCall.send( "updateAll()" );

  mTimer.start( 15 * 60000 );
}

void SummaryWidget::refresh( QString station )
{
  DCOPRef dcopCall( "KWeatherService", "WeatherService" );

  mWeatherMap[ station ].setIcon( dcopCall.call( "currentIcon(QString)", station, true ) );
  mWeatherMap[ station ].setName( dcopCall.call( "stationName(QString)", station, true ) );
  mWeatherMap[ station ].setCover( dcopCall.call( "cover(QString)", station, true ) );
  mWeatherMap[ station ].setTemperature( dcopCall.call( "temperature(QString)", station, true ) );
  mWeatherMap[ station ].setWindSpeed( dcopCall.call( "wind(QString)", station, true ) );
  mWeatherMap[ station ].setRelativeHumidity( dcopCall.call( "relativeHumidity(QString)", station, true ) );
  mWeatherMap[ station ].setStationID(station);

  updateView();
}

void SummaryWidget::stationRemoved( QString station )
{
  mWeatherMap.remove( station );
  updateView();
}

QStringList SummaryWidget::configModules() const
{
  return QStringList( "kcmweatherservice.desktop" );
}

void SummaryWidget::slotShowReport(const QString &stationID)
{
  mProc = new KProcess;
  QApplication::connect(mProc, SIGNAL(processExited(KProcess *)),
	this, SLOT(slotReportFinished(KProcess* )));
  *mProc << "kweatherreport";
  *mProc << stationID;
  if ( !mProc->start() )
  {
    delete mProc;
    mProc=0;
  }
}

void SummaryWidget::slotReportFinished(KProcess* /*proc*/){
  delete mProc;
 mProc = 0;
}

#include "summarywidget.moc"
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "..\task1\VectorProcessor.h"

using namespace std;

bool VectorsAreEqual(vector<double> const& x, vector<double> const& y)
{
	return x == y;
}

// Функция ProcessVector
BOOST_AUTO_TEST_SUITE(ProcessVector_function)

	// Создает пустой вектор из пустого вектора
	BOOST_AUTO_TEST_CASE(makes_empty_vector_from_empty_vector)
	{
		vector<double> emptyVector;
		ProcessVector(emptyVector);
		BOOST_CHECK(emptyVector.empty());
	}

	// не изменяет содержимое вектора, который не содержит положительных чисел
	BOOST_AUTO_TEST_CASE(does_not_change_vector_containing_no_positive_numbers)
	{
		vector<double> numbers = { -4, 0, -3 };
		auto copy(numbers);
		ProcessVector(numbers);
		BOOST_CHECK(numbers == copy);
	}

	// при обработке вектора с одним положительным числом
	BOOST_AUTO_TEST_SUITE(when_processing_a_vector_with_one_positive_number)
		// должен добавить это число ко всем элементам вектора
		BOOST_AUTO_TEST_CASE(should_add_this_number_to_each_element)
		{
			vector<double> numbers = { -1, 3.5 };
			ProcessVector(numbers);

			BOOST_CHECK(VectorsAreEqual( numbers,
				{ (-1 + 3.5), (3.5 + 3.5) }
			));
		}
	BOOST_AUTO_TEST_SUITE_END()

	// при обработке вектора с несколькими положительными элементами
	BOOST_AUTO_TEST_SUITE(when_processing_a_vector_with_several_positive_elements)
		// должен добавить их среднее арифметическое к каждому элементу
		BOOST_AUTO_TEST_CASE(should_add_their_average_to_each_element)
		{
			vector<double> numbers = { -1, 1, 2, 3 };
			ProcessVector(numbers);

			const double average = (1.0 + 2.0 + 3.0) / 3;
			BOOST_CHECK(VectorsAreEqual(numbers,
			{ (-1 + average), (1 + average), (2 + average), (3 + average) }
			));
		}
	BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE_END()

<commit_msg>обновлены концы строк<commit_after>#include "stdafx.h"
#include "..\task1\VectorProcessor.h"

using namespace std;

bool VectorsAreEqual(vector<double> const& x, vector<double> const& y)
{
	return x == y;
}

// Функция ProcessVector
BOOST_AUTO_TEST_SUITE(ProcessVector_function)

	// Создает пустой вектор из пустого вектора
	BOOST_AUTO_TEST_CASE(makes_empty_vector_from_empty_vector)
	{
		vector<double> emptyVector;
		ProcessVector(emptyVector);
		BOOST_CHECK(emptyVector.empty());
	}

	// не изменяет содержимое вектора, который не содержит положительных чисел
	BOOST_AUTO_TEST_CASE(does_not_change_vector_containing_no_positive_numbers)
	{
		vector<double> numbers = { -4, 0, -3 };
		auto copy(numbers);
		ProcessVector(numbers);
		BOOST_CHECK(numbers == copy);
	}

	// при обработке вектора с одним положительным числом
	BOOST_AUTO_TEST_SUITE(when_processing_a_vector_with_one_positive_number)
		// должен добавить это число ко всем элементам вектора
		BOOST_AUTO_TEST_CASE(should_add_this_number_to_each_element)
		{
			vector<double> numbers = { -1, 3.5 };
			ProcessVector(numbers);

			BOOST_CHECK(VectorsAreEqual( numbers,
				{ (-1 + 3.5), (3.5 + 3.5) }
			));
		}
	BOOST_AUTO_TEST_SUITE_END()

	// при обработке вектора с несколькими положительными элементами
	BOOST_AUTO_TEST_SUITE(when_processing_a_vector_with_several_positive_elements)
		// должен добавить их среднее арифметическое к каждому элементу
		BOOST_AUTO_TEST_CASE(should_add_their_average_to_each_element)
		{
			vector<double> numbers = { -1, 1, 2, 3 };
			ProcessVector(numbers);

			const double average = (1.0 + 2.0 + 3.0) / 3;
			BOOST_CHECK(VectorsAreEqual(numbers,
			{ (-1 + average), (1 + average), (2 + average), (3 + average) }
			));
		}
	BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE_END()

<|endoftext|>