<commit_before>/*
* Copyright (c) 2003-2016 Rony Shapiro <ronys@pwsafe.org>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/
/// \file Item.cpp
//-----------------------------------------------------------------------------

#include "Item.h"
#include "BlowFish.h"
#include "TwoFish.h"
#include "PWSrand.h"
#include "UTF8Conv.h"
#include "Util.h"
#include "os/env.h"

#include <vector>

CItem::CItem()
{
  PWSrand::GetInstance()->GetRandomData( m_key, sizeof(m_key) );
}

CItem::CItem(const CItem &that) :
  m_fields(that.m_fields),
  m_URFL(that.m_URFL),
  m_display_info(that.m_display_info == NULL ?
                 NULL : that.m_display_info->clone())
{
  memcpy(m_key, that.m_key, sizeof(m_key));
}

CItem::~CItem()
{
  delete m_display_info;
  delete m_blowfish;
  // Following protects against possible use-after-delete
  // bug, since new BF will be created, rather than
  // using one with trashed values
#ifndef _DEBUG
  m_blowfish = nullptr;
#else
  // Try to force an assert in debug build to find use-after-delete
  m_blowfish = (BlowFish *)-1;
  m_fields.clear();
#endif
}

CItem& CItem::operator=(const CItem &that)
{
  if (this != &that) { // Check for self-assignment
    m_fields = that.m_fields;
    m_URFL = that.m_URFL;

    delete m_display_info;
    m_display_info = that.m_display_info == NULL ?
      NULL : that.m_display_info->clone();
    memcpy(m_key, that.m_key, sizeof(m_key));
    delete m_blowfish;
    m_blowfish = nullptr;
  }
  return *this;
}

bool CItem::CompareFields(const CItemField &fthis,
                          const CItem &that, const CItemField &fthat) const
{
  if (fthis.GetLength() != fthat.GetLength() ||
      fthis.GetType() != fthat.GetType())
    return false;
  size_t flength = fthis.GetLength() + BlowFish::BLOCKSIZE;
  unsigned char *dthis = new unsigned char[flength];
  unsigned char *dthat = new unsigned char[flength];
  GetField(fthis, dthis, flength);
  flength = fthis.GetLength() + BlowFish::BLOCKSIZE; // GetField updates length, reset
  that.GetField(fthat, dthat, flength);
  bool retval = (memcmp(dthis, dthat, flength) == 0);
  trashMemory(dthis, flength); trashMemory(dthis, flength);
  delete[] dthis; delete[] dthat;
  return retval;
}

bool CItem::operator==(const CItem &that) const
{
  if (m_fields.size() == that.m_fields.size() &&
      m_URFL.size() == that.m_URFL.size()) {
    /**
     * It would be nice to be able to compare the m_fields
     * and m_URFL directly, but the fields would be
     * encrypted with different keys, making byte-wise
     * field comparisons infeasible.
     */
    FieldConstIter ithis, ithat;
    for (ithis = m_fields.begin(), ithat = that.m_fields.begin();
         ithis != m_fields.end();
         ithis++, ithat++) {
      if (ithis->first != ithat->first)
        return false;
      const CItemField &fthis = ithis->second;
      const CItemField &fthat = ithat->second;
      if (!CompareFields(fthis, that, fthat))
        return false;
    } // for m_fields
  } else
    return false;

  // If we made it so far, now compare the unknown record fields
  // (We already know their sizes are equal)
  if (!m_URFL.empty()) {
    UnknownFieldsConstIter ithis, ithat;
    for (ithis = m_URFL.begin(), ithat = that.m_URFL.begin();
         ithis != m_URFL.end();
         ithis++, ithat++) {
      if (!CompareFields(*ithis, that, *ithat))
        return false;
    } // for m_URFL
  }
  return true;
}

size_t CItem::GetSize() const
{
  size_t length(0);

  for (FieldConstIter fiter = m_fields.begin(); fiter != m_fields.end(); fiter++)
    length += fiter->second.GetLength();

  for (UnknownFieldsConstIter ufiter = m_URFL.begin();
       ufiter != m_URFL.end(); ufiter++)
    length += ufiter->GetLength();

  return length;
}

BlowFish *CItem::MakeBlowFish() const
{
  // Creating a BlowFish object's relatively expensive, so we use
  // the singleton design pattern for the life of the CItem object

  // Following ASSERT is to detect use-after-delete
  ASSERT(m_blowfish != (BlowFish *)-1);

  if(!m_blowfish) {
    m_blowfish = BlowFish::MakeBlowFish(m_key, sizeof(m_key));
  }
  return m_blowfish;
}

void CItem::SetUnknownField(unsigned char type,
                            size_t length,
                            const unsigned char *ufield)
{
  /**
     TODO - check that this unknown field from the XML Import file is now
     known and it should be added as that instead!
  **/

  CItemField unkrfe(type);
  unkrfe.Set(ufield, length, MakeBlowFish());
  m_URFL.push_back(unkrfe);
}

void CItem::Clear()
{
  m_fields.clear();
  m_URFL.clear();
}

void CItem::SetField(int ft, const unsigned char *value, size_t length)
{
  if (length != 0) {
    m_fields[ft].Set(value, length,
                     MakeBlowFish(),
                     static_cast<unsigned char>(ft));
  } else
    m_fields.erase(ft);
}

void CItem::SetField(int ft, const StringX &value)
{
  if (!value.empty()) {
    m_fields[ft].Set(value,
                     MakeBlowFish(),
                     static_cast<unsigned char>(ft));
  } else
    m_fields.erase(ft);
}

static bool pull_string(StringX &str,
                        const unsigned char *data, size_t len)
{
  /**
   * cp_acp is used to force reading data as non-utf8 encoded
   * This is for databases that were incorrectly written, e.g., 3.05.02
   * PWS_CP_ACP is either set externally or via the --CP_ACP argv
   *
   * We use a static variable purely for efficiency, as this won't change
   * over the course of the program.
   */

  static int cp_acp = -1;
  if (cp_acp == -1) {
    cp_acp = pws_os::getenv("PWS_CP_ACP", false).empty() ? 0 : 1;
  }
  CUTF8Conv utf8conv(cp_acp != 0);
  std::vector<unsigned char> v(data, (data + len));
  v.push_back(0); // null terminate for FromUTF8.
  bool utf8status = utf8conv.FromUTF8(&v[0], len, str);
  if (!utf8status) {
    pws_os::Trace(_T("Item.cpp: pull_string(): FromUTF8 failed!\n"));
  }
  trashMemory(&v[0], len);
  return utf8status;
}

bool CItem::SetTextField(int ft, const unsigned char *value,
                         size_t length)
{
  StringX str;
  if (pull_string(str, value, length)) {
    SetField(ft, str);
    return true;
  } else
    return false;
}

void CItem::SetTime(int whichtime, time_t t)
{
  unsigned char buf[sizeof(time_t)];
  putInt(buf, t);
  SetField(whichtime, buf, sizeof(time_t));
}

bool CItem::SetTimeField(int ft, const unsigned char *value,
                         size_t length)
{
  time_t t;
  if (PWSUtil::pull_time(t, value, length)) {
    SetTime(ft, t);
    return true;
  } else
    return false;
}

void CItem::GetField(const CItemField &field,
                     unsigned char *value, size_t &length) const
{
  field.Get(value, length, MakeBlowFish());
}

StringX CItem::GetField(const int ft) const
{
  FieldConstIter fiter = m_fields.find(ft);
  return fiter == m_fields.end() ? _T("") : GetField(fiter->second);
}

StringX CItem::GetField(const CItemField &field) const
{
  StringX retval;
  field.Get(retval, MakeBlowFish());
  return retval;
}

void CItem::GetTime(int whichtime, time_t &t) const
{
  FieldConstIter fiter = m_fields.find(whichtime);
  if (fiter != m_fields.end()) {
    unsigned char in[TwoFish::BLOCKSIZE]; // required by GetField
    size_t tlen = sizeof(in); // ditto

    CItem::GetField(fiter->second, in, tlen);
    if (tlen != 0) {
    // time field's store in native time_t size, regardless of
    // the representation on file
      ASSERT(tlen == sizeof(t));
      if (!PWSUtil::pull_time(t, in, tlen))
        ASSERT(0);
    } else {
      t = 0;
    }
  } else // fiter == m_fields.end()
    t = 0;
}
<commit_msg>Cleanup failed debug attempt<commit_after>/*
* Copyright (c) 2003-2016 Rony Shapiro <ronys@pwsafe.org>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/
/// \file Item.cpp
//-----------------------------------------------------------------------------

#include "Item.h"
#include "BlowFish.h"
#include "TwoFish.h"
#include "PWSrand.h"
#include "UTF8Conv.h"
#include "Util.h"
#include "os/env.h"

#include <vector>

CItem::CItem()
{
  PWSrand::GetInstance()->GetRandomData( m_key, sizeof(m_key) );
}

CItem::CItem(const CItem &that) :
  m_fields(that.m_fields),
  m_URFL(that.m_URFL),
  m_display_info(that.m_display_info == NULL ?
                 NULL : that.m_display_info->clone())
{
  memcpy(m_key, that.m_key, sizeof(m_key));
}

CItem::~CItem()
{
  delete m_display_info;
  delete m_blowfish;
  // Following protects against possible use-after-delete
  // bug, since new BF will be created, rather than
  // using one with trashed values
  m_blowfish = nullptr;
}

CItem& CItem::operator=(const CItem &that)
{
  if (this != &that) { // Check for self-assignment
    m_fields = that.m_fields;
    m_URFL = that.m_URFL;

    delete m_display_info;
    m_display_info = that.m_display_info == NULL ?
      NULL : that.m_display_info->clone();
    memcpy(m_key, that.m_key, sizeof(m_key));
    delete m_blowfish;
    m_blowfish = nullptr;
  }
  return *this;
}

bool CItem::CompareFields(const CItemField &fthis,
                          const CItem &that, const CItemField &fthat) const
{
  if (fthis.GetLength() != fthat.GetLength() ||
      fthis.GetType() != fthat.GetType())
    return false;
  size_t flength = fthis.GetLength() + BlowFish::BLOCKSIZE;
  unsigned char *dthis = new unsigned char[flength];
  unsigned char *dthat = new unsigned char[flength];
  GetField(fthis, dthis, flength);
  flength = fthis.GetLength() + BlowFish::BLOCKSIZE; // GetField updates length, reset
  that.GetField(fthat, dthat, flength);
  bool retval = (memcmp(dthis, dthat, flength) == 0);
  trashMemory(dthis, flength); trashMemory(dthis, flength);
  delete[] dthis; delete[] dthat;
  return retval;
}

bool CItem::operator==(const CItem &that) const
{
  if (m_fields.size() == that.m_fields.size() &&
      m_URFL.size() == that.m_URFL.size()) {
    /**
     * It would be nice to be able to compare the m_fields
     * and m_URFL directly, but the fields would be
     * encrypted with different keys, making byte-wise
     * field comparisons infeasible.
     */
    FieldConstIter ithis, ithat;
    for (ithis = m_fields.begin(), ithat = that.m_fields.begin();
         ithis != m_fields.end();
         ithis++, ithat++) {
      if (ithis->first != ithat->first)
        return false;
      const CItemField &fthis = ithis->second;
      const CItemField &fthat = ithat->second;
      if (!CompareFields(fthis, that, fthat))
        return false;
    } // for m_fields
  } else
    return false;

  // If we made it so far, now compare the unknown record fields
  // (We already know their sizes are equal)
  if (!m_URFL.empty()) {
    UnknownFieldsConstIter ithis, ithat;
    for (ithis = m_URFL.begin(), ithat = that.m_URFL.begin();
         ithis != m_URFL.end();
         ithis++, ithat++) {
      if (!CompareFields(*ithis, that, *ithat))
        return false;
    } // for m_URFL
  }
  return true;
}

size_t CItem::GetSize() const
{
  size_t length(0);

  for (FieldConstIter fiter = m_fields.begin(); fiter != m_fields.end(); fiter++)
    length += fiter->second.GetLength();

  for (UnknownFieldsConstIter ufiter = m_URFL.begin();
       ufiter != m_URFL.end(); ufiter++)
    length += ufiter->GetLength();

  return length;
}

BlowFish *CItem::MakeBlowFish() const
{
  // Creating a BlowFish object's relatively expensive, so we use
  // the singleton design pattern for the life of the CItem object
  if(!m_blowfish) {
    m_blowfish = BlowFish::MakeBlowFish(m_key, sizeof(m_key));
  }
  return m_blowfish;
}

void CItem::SetUnknownField(unsigned char type,
                            size_t length,
                            const unsigned char *ufield)
{
  /**
     TODO - check that this unknown field from the XML Import file is now
     known and it should be added as that instead!
  **/

  CItemField unkrfe(type);
  unkrfe.Set(ufield, length, MakeBlowFish());
  m_URFL.push_back(unkrfe);
}

void CItem::Clear()
{
  m_fields.clear();
  m_URFL.clear();
}

void CItem::SetField(int ft, const unsigned char *value, size_t length)
{
  if (length != 0) {
    m_fields[ft].Set(value, length,
                     MakeBlowFish(),
                     static_cast<unsigned char>(ft));
  } else
    m_fields.erase(ft);
}

void CItem::SetField(int ft, const StringX &value)
{
  if (!value.empty()) {
    m_fields[ft].Set(value,
                     MakeBlowFish(),
                     static_cast<unsigned char>(ft));
  } else
    m_fields.erase(ft);
}

static bool pull_string(StringX &str,
                        const unsigned char *data, size_t len)
{
  /**
   * cp_acp is used to force reading data as non-utf8 encoded
   * This is for databases that were incorrectly written, e.g., 3.05.02
   * PWS_CP_ACP is either set externally or via the --CP_ACP argv
   *
   * We use a static variable purely for efficiency, as this won't change
   * over the course of the program.
   */

  static int cp_acp = -1;
  if (cp_acp == -1) {
    cp_acp = pws_os::getenv("PWS_CP_ACP", false).empty() ? 0 : 1;
  }
  CUTF8Conv utf8conv(cp_acp != 0);
  std::vector<unsigned char> v(data, (data + len));
  v.push_back(0); // null terminate for FromUTF8.
  bool utf8status = utf8conv.FromUTF8(&v[0], len, str);
  if (!utf8status) {
    pws_os::Trace(_T("Item.cpp: pull_string(): FromUTF8 failed!\n"));
  }
  trashMemory(&v[0], len);
  return utf8status;
}

bool CItem::SetTextField(int ft, const unsigned char *value,
                         size_t length)
{
  StringX str;
  if (pull_string(str, value, length)) {
    SetField(ft, str);
    return true;
  } else
    return false;
}

void CItem::SetTime(int whichtime, time_t t)
{
  unsigned char buf[sizeof(time_t)];
  putInt(buf, t);
  SetField(whichtime, buf, sizeof(time_t));
}

bool CItem::SetTimeField(int ft, const unsigned char *value,
                         size_t length)
{
  time_t t;
  if (PWSUtil::pull_time(t, value, length)) {
    SetTime(ft, t);
    return true;
  } else
    return false;
}

void CItem::GetField(const CItemField &field,
                     unsigned char *value, size_t &length) const
{
  field.Get(value, length, MakeBlowFish());
}

StringX CItem::GetField(const int ft) const
{
  FieldConstIter fiter = m_fields.find(ft);
  return fiter == m_fields.end() ? _T("") : GetField(fiter->second);
}

StringX CItem::GetField(const CItemField &field) const
{
  StringX retval;
  field.Get(retval, MakeBlowFish());
  return retval;
}

void CItem::GetTime(int whichtime, time_t &t) const
{
  FieldConstIter fiter = m_fields.find(whichtime);
  if (fiter != m_fields.end()) {
    unsigned char in[TwoFish::BLOCKSIZE]; // required by GetField
    size_t tlen = sizeof(in); // ditto

    CItem::GetField(fiter->second, in, tlen);
    if (tlen != 0) {
    // time field's store in native time_t size, regardless of
    // the representation on file
      ASSERT(tlen == sizeof(t));
      if (!PWSUtil::pull_time(t, in, tlen))
        ASSERT(0);
    } else {
      t = 0;
    }
  } else // fiter == m_fields.end()
    t = 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

#include "db/builder.h"

#include "db/filename.h"
#include "db/dbformat.h"
#include "db/table_cache.h"
#include "db/version_edit.h"
#include "leveldb/db.h"
#include "leveldb/env.h"
#include "leveldb/iterator.h"

namespace leveldb {

Status BuildTable(const std::string& dbname,
                  Env* env,
                  const Options& options,
                  TableCache* table_cache,
                  Iterator* iter,
                  FileMetaData* meta) {
  Status s;
  meta->file_size = 0;
  iter->SeekToFirst();

  std::string fname = TableFileName(dbname, meta->number);
  if (iter->Valid()) {
    WritableFile* file;
    s = env->NewWritableFile(fname, &file);
    if (!s.ok()) {
      return s;
    }

    TableBuilder* builder = new TableBuilder(options, file);
    meta->smallest.DecodeFrom(iter->key());
    for (; iter->Valid(); iter->Next()) {
      Slice key = iter->key();
      meta->largest.DecodeFrom(key);
      builder->Add(key, iter->value());
    }

    // Finish and check for builder errors
    if (s.ok()) {
      s = builder->Finish();
      if (s.ok()) {
        meta->file_size = builder->FileSize();
        assert(meta->file_size > 0);
      }
    } else {
      builder->Abandon();
    }
    delete builder;

    // Finish and check for file errors
    if (s.ok()) {
      s = file->Sync();
    }
    if (s.ok()) {
      s = file->Close();
    }
    delete file;
    file = NULL;

    if (s.ok()) {
      // Verify that the table is usable
      Iterator* it = table_cache->NewIterator(ReadOptions(),
                                              meta->number,
                                              meta->file_size);
      s = it->status();
      delete it;
    }
  }

  // Check for input iterator errors
  if (!iter->status().ok()) {
    s = iter->status();
  }

  if (s.ok() && meta->file_size > 0) {
    // Keep it
  } else {
    env->DeleteFile(fname);
  }
  return s;
}

}  // namespace leveldb
<commit_msg>Delete builder.cc<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2007 Marc Boris Duerner
 * Copyright (C) 2007 Laurentiu-Gheorghe Crisan
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "selectorimpl.h"
#include "cxxtools/eventloop.h"
#include "cxxtools/mutex.h"
#include <deque>

namespace cxxtools
{

class EventLoop::Impl
{
public:
    Impl()
        : _exitLoop(false),
          _selector(new SelectorImpl()),
          _eventsPerLoop(1024)
        { }
    ~Impl();

    bool eventQueueEmpty()
    { return _eventQueue.empty() && _priorityEventQueue.empty(); }

    Event* front()
    {
        if (_priorityEventQueue.empty())
            return _eventQueue.front();
        else
            return _priorityEventQueue.front();
    }

    void pop_front()
    {
        if (_priorityEventQueue.empty())
            _eventQueue.pop_front();
        else
            _priorityEventQueue.pop_front();
    }

    bool _exitLoop;
    SelectorImpl* _selector;
    std::deque<Event* > _eventQueue;
    std::deque<Event* > _priorityEventQueue;
    RecursiveMutex _queueMutex;
    unsigned _eventsPerLoop;
};

EventLoop::Impl::~Impl()
{
    try
    {
        while ( ! _eventQueue.empty() )
        {
            Event* ev = _eventQueue.front();
            _eventQueue.pop_front();
            ev->destroy();
        }

        while ( ! _priorityEventQueue.empty() )
        {
            Event* ev = _priorityEventQueue.front();
            _priorityEventQueue.pop_front();
            ev->destroy();
        }
    }
    catch(...)
    {}

    delete _selector;
}

EventLoop::EventLoop()
: _impl(new Impl())
{
}

EventLoop::~EventLoop()
{
    delete _impl;
}

unsigned EventLoop::eventsPerLoop()
{
    return _impl->_eventsPerLoop;
}

void EventLoop::eventsPerLoop(unsigned n)
{
    _impl->_eventsPerLoop = n;
}

void EventLoop::onAdd( Selectable& s )
{
    return _impl->_selector->add( s );
}

void EventLoop::onRemove( Selectable& s )
{
    _impl->_selector->remove( s );
}

void EventLoop::onReinit(Selectable& /*s*/)
{
}

void EventLoop::onChanged(Selectable& s)
{
    _impl->_selector->changed(s);
}

void EventLoop::onRun()
{
    started();

    while (true)
    {
        RecursiveLock lock(_impl->_queueMutex);

        if (_impl->_exitLoop)
        {
            _impl->_exitLoop = false;
            break;
        }

        bool eventQueueEmpty = _impl->eventQueueEmpty();
        if (!eventQueueEmpty)
        {
            lock.unlock();
            processEvents(_impl->_eventsPerLoop);
            eventQueueEmpty = _impl->eventQueueEmpty();
        }

        lock.unlock();

        if (eventQueueEmpty)
        {
            idle();

            bool active = wait(idleTimeout());
            if (!active)
                timeout.send();
        }
        else
        {
            // process I/O events
            wait(0);
        }
    }

    exited();
}

bool EventLoop::onWaitUntil(Timespan timeout)
{
    if (_impl->_selector->waitUntil(timeout))
    {
        RecursiveLock lock(_impl->_queueMutex);

        if (!_impl->eventQueueEmpty())
        {
            lock.unlock();
            processEvents(_impl->_eventsPerLoop);
        }

        return true;
    }

    return false;
}

void EventLoop::onWake()
{
    _impl->_selector->wake();
}

void EventLoop::onExit()
{
    RecursiveLock lock(_impl->_queueMutex);
    _impl->_exitLoop = true;
    lock.unlock();

    this->wake();
}

void EventLoop::onQueueEvent(const Event& ev, bool priority)
{
    RecursiveLock lock( _impl->_queueMutex );

    Event* clonedEvent = ev.clone();

    try
    {
        if (priority)
            _impl->_priorityEventQueue.push_back(clonedEvent);
        else
            _impl->_eventQueue.push_back(clonedEvent);
    }
    catch(...)
    {
        clonedEvent->destroy();
        throw;
    }
}

void EventLoop::onCommitEvent(const Event& ev, bool priority)
{
    onQueueEvent(ev, priority);
    _impl->_selector->wake();
}

void EventLoop::onProcessEvents(unsigned max)
{
    unsigned count = 0;

    while (!_impl->_exitLoop)
    {
        RecursiveLock lock(_impl->_queueMutex);

        if (_impl->eventQueueEmpty() || _impl->_exitLoop)
            break;

        Event* ev = _impl->front();
        _impl->pop_front();

        try
        {
            lock.unlock();
            event.send(*ev);
        }
        catch(...)
        {
            ev->destroy();
            throw;
        }

        ev->destroy();

        ++count;
        if (max != 0 && count >= max)
            break;
    }
}

} // namespace cxxtools
<commit_msg>replace try-catch cleanup with temporary object with destructor in event loop<commit_after>/*
 * Copyright (C) 2007 Marc Boris Duerner
 * Copyright (C) 2007 Laurentiu-Gheorghe Crisan
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "selectorimpl.h"
#include "cxxtools/eventloop.h"
#include "cxxtools/mutex.h"
#include <deque>

namespace cxxtools
{
namespace
{
    struct EvPtr
    {
        Event* ev;
        explicit EvPtr(Event* ev_)
            : ev(ev_)
        { }

        ~EvPtr()
        { if (ev) ev->destroy(); }

    };
}

class EventLoop::Impl
{
public:
    Impl()
        : _exitLoop(false),
          _selector(new SelectorImpl()),
          _eventsPerLoop(1024)
        { }
    ~Impl();

    bool eventQueueEmpty()
    { return _eventQueue.empty() && _priorityEventQueue.empty(); }

    Event* front()
    {
        if (_priorityEventQueue.empty())
            return _eventQueue.front();
        else
            return _priorityEventQueue.front();
    }

    void pop_front()
    {
        if (_priorityEventQueue.empty())
            _eventQueue.pop_front();
        else
            _priorityEventQueue.pop_front();
    }

    bool _exitLoop;
    SelectorImpl* _selector;
    std::deque<Event* > _eventQueue;
    std::deque<Event* > _priorityEventQueue;
    RecursiveMutex _queueMutex;
    unsigned _eventsPerLoop;
};

EventLoop::Impl::~Impl()
{
    try
    {
        while ( ! _eventQueue.empty() )
        {
            Event* ev = _eventQueue.front();
            _eventQueue.pop_front();
            ev->destroy();
        }

        while ( ! _priorityEventQueue.empty() )
        {
            Event* ev = _priorityEventQueue.front();
            _priorityEventQueue.pop_front();
            ev->destroy();
        }
    }
    catch(...)
    {}

    delete _selector;
}

EventLoop::EventLoop()
: _impl(new Impl())
{
}

EventLoop::~EventLoop()
{
    delete _impl;
}

unsigned EventLoop::eventsPerLoop()
{
    return _impl->_eventsPerLoop;
}

void EventLoop::eventsPerLoop(unsigned n)
{
    _impl->_eventsPerLoop = n;
}

void EventLoop::onAdd( Selectable& s )
{
    return _impl->_selector->add( s );
}

void EventLoop::onRemove( Selectable& s )
{
    _impl->_selector->remove( s );
}

void EventLoop::onReinit(Selectable& /*s*/)
{
}

void EventLoop::onChanged(Selectable& s)
{
    _impl->_selector->changed(s);
}

void EventLoop::onRun()
{
    started();

    while (true)
    {
        RecursiveLock lock(_impl->_queueMutex);

        if (_impl->_exitLoop)
        {
            _impl->_exitLoop = false;
            break;
        }

        bool eventQueueEmpty = _impl->eventQueueEmpty();
        if (!eventQueueEmpty)
        {
            lock.unlock();
            processEvents(_impl->_eventsPerLoop);
            eventQueueEmpty = _impl->eventQueueEmpty();
        }

        lock.unlock();

        if (eventQueueEmpty)
        {
            idle();

            bool active = wait(idleTimeout());
            if (!active)
                timeout.send();
        }
        else
        {
            // process I/O events
            wait(0);
        }
    }

    exited();
}

bool EventLoop::onWaitUntil(Timespan timeout)
{
    if (_impl->_selector->waitUntil(timeout))
    {
        RecursiveLock lock(_impl->_queueMutex);

        if (!_impl->eventQueueEmpty())
        {
            lock.unlock();
            processEvents(_impl->_eventsPerLoop);
        }

        return true;
    }

    return false;
}

void EventLoop::onWake()
{
    _impl->_selector->wake();
}

void EventLoop::onExit()
{
    RecursiveLock lock(_impl->_queueMutex);
    _impl->_exitLoop = true;
    lock.unlock();

    this->wake();
}

void EventLoop::onQueueEvent(const Event& ev, bool priority)
{
    RecursiveLock lock( _impl->_queueMutex );

    EvPtr cloned(ev.clone());

    if (priority)
        _impl->_priorityEventQueue.push_back(cloned.ev);
    else
        _impl->_eventQueue.push_back(cloned.ev);

    cloned.ev = 0;
}

void EventLoop::onCommitEvent(const Event& ev, bool priority)
{
    onQueueEvent(ev, priority);
    _impl->_selector->wake();
}

void EventLoop::onProcessEvents(unsigned max)
{
    unsigned count = 0;

    while (!_impl->_exitLoop)
    {
        RecursiveLock lock(_impl->_queueMutex);

        if (_impl->eventQueueEmpty() || _impl->_exitLoop)
            break;

        EvPtr ev(_impl->front());
        _impl->pop_front();

        lock.unlock();
        event.send(*ev.ev);

        ++count;
        if (max != 0 && count >= max)
            break;
    }
}

} // namespace cxxtools
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008-2009, Thomas Jaeger <ThJaeger@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include "fire.h"
#include <X11/Xlib.h>
#include <math.h>

Fire::Fire() {
	const char *ofc = "org.freedesktop.compiz";
	GError *error = 0;
	bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
	if (!bus) {
		g_error_free(error);
		throw DBusException();
	}
	char add[256];
	char clear[256];
	snprintf(add, sizeof(add), "/org/freedesktop/compiz/firepaint/screen%d/add_particle", DefaultScreen(dpy));
	snprintf(clear, sizeof(clear), "/org/freedesktop/compiz/firepaint/screen%d/clear_key", DefaultScreen(dpy));

	point_proxy = dbus_g_proxy_new_for_name(bus, ofc, add, ofc);
	clear_proxy = dbus_g_proxy_new_for_name(bus, ofc, clear, ofc);
}

void Fire::add_point(float x, float y) {
	dbus_g_proxy_call_no_reply(point_proxy, "activate",
			G_TYPE_STRING, "root", G_TYPE_INT,    gint(ROOT),
			G_TYPE_STRING, "x",   G_TYPE_DOUBLE, gdouble(x),
			G_TYPE_STRING, "y",   G_TYPE_DOUBLE, gdouble(y),
			G_TYPE_INVALID);
}

void Fire::draw(Point p, Point q) {
	float dist = hypot(p.x-q.x, p.y-q.y);
	leftover -= dist;
	while (leftover < 0.01) {
		add_point(q.x + (q.x-p.x)*leftover/dist, q.y + (q.y-p.y)*leftover/dist);
		leftover += 5.0;
	}
}
void Fire::timeout() {
	dbus_g_proxy_call_no_reply(clear_proxy, "activate",
			G_TYPE_STRING, "root", G_TYPE_INT,    gint(ROOT),
			G_TYPE_INVALID);
}
<commit_msg>Fix build failure due to lack of import<commit_after>/*
 * Copyright (c) 2008-2009, Thomas Jaeger <ThJaeger@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include "fire.h"
#include <X11/Xlib.h>
#include <math.h>
#include <stdio.h>

Fire::Fire() {
	const char *ofc = "org.freedesktop.compiz";
	GError *error = 0;
	bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
	if (!bus) {
		g_error_free(error);
		throw DBusException();
	}
	char add[256];
	char clear[256];
	snprintf(add, sizeof(add), "/org/freedesktop/compiz/firepaint/screen%d/add_particle", DefaultScreen(dpy));
	snprintf(clear, sizeof(clear), "/org/freedesktop/compiz/firepaint/screen%d/clear_key", DefaultScreen(dpy));

	point_proxy = dbus_g_proxy_new_for_name(bus, ofc, add, ofc);
	clear_proxy = dbus_g_proxy_new_for_name(bus, ofc, clear, ofc);
}

void Fire::add_point(float x, float y) {
	dbus_g_proxy_call_no_reply(point_proxy, "activate",
			G_TYPE_STRING, "root", G_TYPE_INT,    gint(ROOT),
			G_TYPE_STRING, "x",   G_TYPE_DOUBLE, gdouble(x),
			G_TYPE_STRING, "y",   G_TYPE_DOUBLE, gdouble(y),
			G_TYPE_INVALID);
}

void Fire::draw(Point p, Point q) {
	float dist = hypot(p.x-q.x, p.y-q.y);
	leftover -= dist;
	while (leftover < 0.01) {
		add_point(q.x + (q.x-p.x)*leftover/dist, q.y + (q.y-p.y)*leftover/dist);
		leftover += 5.0;
	}
}
void Fire::timeout() {
	dbus_g_proxy_call_no_reply(clear_proxy, "activate",
			G_TYPE_STRING, "root", G_TYPE_INT,    gint(ROOT),
			G_TYPE_INVALID);
}
<|endoftext|>


<commit_before>#include <fstream>
#include <iostream>
#include <math.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;
using namespace std;

const double PI = 3.1415926536;
const float angle2step = 6875.4935;
const float std_z = -270;

typedef struct angles {
    float a;
    float b;
    float r;
} angles;

typedef struct xyz {
    float x;
    float y;
    float z;
} xyz;

angles cal_angle(xyz coord);
string f_dirsteps(xyz curr, xyz next);
string num2str(int i);
void gen_coord(string file_path);
xyz find_dot(xyz circle, int *cp_img, int width, int height);
xyz convert_coord(xyz origin_coord, int width, int height);

xyz init_coord = {280, 0, -250};

int main() {
    gen_coord("../data/img/line.jpg");
    return 0;
}

void gen_coord(string file_path) {
    Mat src = imread(file_path, 0);
    ofstream out("../data/text/out_step.txt");
    int width = src.cols;
    int height = src.rows;
    int cp_img[height][width];

    for (int h = 0; h < height; h++) {
        uchar *P = src.ptr<uchar>(h);
        for (int w = 0; w < width; w++) {
            cp_img[h][w] = P[w];
        }
    }
    xyz center = {0, 0, 0};
    xyz next_center = {-1, -1, -1};
    int find_tag = 0;
    for (int h = 0; h < height; h++) {
        for (int w = 0; w < width; w++) {
            if (cp_img[h][w] > 240) {
                center = {w, h, 0};
                cp_img[h][w] = 0;
                find_tag = 1;
                break;
            }
        }
        if (find_tag == 1)
            break;
    }

    out << f_dirsteps(init_coord, convert_coord(center, width, height));
    center.z = 1;
    while (1) {
        next_center = find_dot(center, *cp_img, width, height);
        //        cout << next_center.x << " " << next_center.y << " " <<
        //        next_center.z
        //      << endl;
        if (int(next_center.z) == -1)
            break;

        if (int(next_center.z) > 30) {
            xyz temp1 = center;
            temp1.z = 0;
            out << f_dirsteps(convert_coord(center, width, height),
                              convert_coord(temp1, width, height));
            next_center.z = 0;
            xyz temp2 = next_center;
            out << f_dirsteps(convert_coord(temp1, width, height),
                              convert_coord(temp2, width, height));
            next_center.z = 1;
            out << f_dirsteps(convert_coord(temp2, width, height),
                              convert_coord(next_center, width, height));
        } else {
            next_center.z = 1;
            out << f_dirsteps(convert_coord(center, width, height),
                              convert_coord(next_center, width, height));
        }

        cp_img[int(center.y)][int(center.x)] = 0;
        center = next_center;
    }
    next_center = center;
    next_center.z = 0;
    out << f_dirsteps(convert_coord(center, width, height),
                      convert_coord(next_center, width, height));
    out << f_dirsteps(convert_coord(next_center, width, height), init_coord);
    out.close();
}

xyz find_dot(xyz center, int *cp_img, int width, int height) {
    int x = center.x;
    int y = center.y;
    xyz next_dot;
    /*    int map[height][width];
        for (int h = 0; h < height; h++) {
            for (int w = 0; w < width; w++) {
                map[h][w] = *(cp_img + width * h + w);
            }
        }
     */
    int max_cr = max(max(max(x, y), abs(x - width - 1)), abs(y - height - 1));
    for (int cr = 1; cr < max_cr + 1; cr++) {       //分层找点
        for (int dn = -cr + 1; dn < cr + 1; dn++) { //下面的边
            if (y + cr + 1 > height)
                break;
            if (x + dn < 0)
                continue;
            if (x + dn + 1 > width)
                break;
            // if (map[x + dn][y + cr] > 245) {
            if (*(cp_img + width * (x + dn) + y + cr) > 245) {
                next_dot = {x + dn, y + cr, cr};
                *(cp_img + width * (x + dn) + y + cr) = 0;
                return next_dot;
            }
        }

        for (int rt = -cr + 1; rt < cr + 1; rt++) { //右面的边
            if (x + cr + 1 > width)
                break;
            if (y - rt + 1 > height)
                continue;
            if (y - rt < 0)
                break;
            //  if (map[x + cr][y - rt] > 245) {
            if (*(cp_img + width * (x + cr) + y - rt) > 245) {
                next_dot = {x + cr, y - rt, cr};
                *(cp_img + width * (x + cr) + y - rt) = 0;
                return next_dot;
            }
        }

        for (int up = -cr + 1; up < cr + 1; up++) { //上面的边
            if (y - cr < 0)
                break;
            if (x - up + 1 > width)
                continue;
            if (x - up < 0)
                break;
            // if (map[x - up][y - cr] > 245) {
            if (*(cp_img + width * (x - up) + y - cr) > 245) {
                next_dot = {x - up, y - cr, cr};
                *(cp_img + width * (x - up) + y - cr) = 0;
                return next_dot;
            }
        }

        for (int lt = -cr + 1; lt < cr + 1; lt++) { //左面的边
            if (x - cr < 0)
                break;
            if (y + lt < 0)
                continue;
            if (y + lt + 1 > height)
                break;
            // if (map[x - cr][y + lt] > 245) {
            if (*(cp_img + width * (x - cr) + y + lt) > 245) {
                next_dot = {x - cr, y + lt, cr};
                *(cp_img + width * (x - cr) + y + lt) = 0;
                return next_dot;
            }
        }
    }
    next_dot = {-1, -1, -1};
    return next_dot;
}

angles cal_angle(xyz coord) {
    float p = 0.0;
    angles angle;
    if (coord.x >= 0)
        angle.a = asin(coord.y / sqrt(coord.x * coord.x + coord.y * coord.y));
    else
        angle.a =
            asin(-coord.y / sqrt(coord.x * coord.x + coord.y * coord.y)) - PI;

    coord.y = coord.y - 80 * sin(angle.a);
    coord.x = coord.x - 80 * cos(angle.a);
    p = sqrt(coord.x * coord.x + coord.y * coord.y + coord.z * coord.z);
    angle.b = (acos((45 / p) + (p / 500)) + asin(-coord.z / p));
    angle.r = (acos((p * p - 22500) / (400 * p)) + acos(-coord.z / p));

    return angle;
}

string f_dirsteps(xyz curr, xyz next) {
    string fpath = "$";
    cout << curr.x << " " << curr.y << " " << curr.z << endl;
    angles curr_angles = cal_angle(curr);
    angles next_angles = cal_angle(next);
    float angle_a = next_angles.a - curr_angles.a;
    float angle_b = next_angles.b - curr_angles.b;
    float angle_r = next_angles.r - curr_angles.r;

    int a_step = round(angle_a * angle2step);
    int b_step = round(angle_b * angle2step);
    int r_step = round(angle_r * angle2step);

    if (!(a_step || b_step || r_step))
        return "";
    if (angle_a >= 0)
        fpath = fpath + "1" + num2str(a_step) + "#";
    else
        fpath = fpath + "0" + num2str(-a_step) + "#";

    if (angle_b >= 0)
        fpath = fpath + "1" + num2str(b_step) + "#";
    else
        fpath = fpath + "0" + num2str(-b_step) + "#";

    if (angle_r >= 0)
        fpath = fpath + "1" + num2str(r_step) + "#";
    else
        fpath = fpath + "0" + num2str(-r_step) + "#";

    fpath = fpath + "@";
    return fpath;
}

string num2str(int i) {
    stringstream ss;
    ss << i;
    return ss.str();
}

xyz convert_coord(xyz origin_coord, int width, int height) {
    xyz cvt_coord;
    int std_width = 7 * width;
    int std_height = 10 * height;
    float ratio;
    if (width >= height) {
        if (std_width < std_height) {
            ratio = 210.0 / height;
            cvt_coord.x = 330 - int(origin_coord.y * ratio);
            cvt_coord.y = (50 - (300 - int(width * ratio)) / 2) -
                          int(origin_coord.x * ratio);
            cvt_coord.z = std_z - 10 * origin_coord.z;
        } else {
            ratio = 300.0 / width;
            cvt_coord.x = (330 - (210 - int(height * ratio)) / 2) -
                          int(origin_coord.y * ratio);
            cvt_coord.y = 50 - int(origin_coord.x * ratio);
            cvt_coord.z = std_z - 10 * origin_coord.z;
        }
    } else {
        if (std_width < std_height) {
            ratio = 300.0 / height;
            cvt_coord.x = (120 + (210 - int(width * ratio)) / 2) +
                          int(origin_coord.x * ratio);
            cvt_coord.y = 50 - int(origin_coord.y * ratio);
            cvt_coord.z = std_z - 10 * origin_coord.z;
        } else {
            ratio = 210.0 / width;
            cvt_coord.x = 120 + int(origin_coord.x * ratio);
            cvt_coord.y = (50 - (300 - int(height * ratio)) / 2) -
                          int(origin_coord.y * ratio);
            cvt_coord.z = std_z - 10 * origin_coord.z;
        }
    }
    return cvt_coord;
}<commit_msg>fixed the core dump<commit_after>#include <fstream>
#include <iostream>
#include <math.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;
using namespace std;

const double PI = 3.1415926536;
const float angle2step = 6875.4935;
const float std_z = -270;

typedef struct angles {
    float a;
    float b;
    float r;
} angles;

typedef struct xyz {
    float x;
    float y;
    float z;
} xyz;

angles cal_angle(xyz coord);
string f_dirsteps(xyz curr, xyz next);
string num2str(int i);
void gen_coord(string file_path);
xyz find_dot(xyz circle, int *cp_img, int width, int height);
xyz convert_coord(xyz origin_coord, int width, int height);

xyz init_coord = {280, 0, -250};

int main() {
    gen_coord("../data/img/line.jpg");
    return 0;
}

void gen_coord(string file_path) {
    Mat src = imread(file_path, 0);
    ofstream out("../data/text/out_step.txt");
    int width = src.cols;
    int height = src.rows;
    int cp_img[height][width];
    cout << width << " " << height << endl;
    for (int h = 0; h < height; h++) {
        uchar *P = src.ptr<uchar>(h);
        for (int w = 0; w < width; w++) {
            cp_img[h][w] = P[w];
        }
    }
    xyz center = {0, 0, 0};
    xyz next_center = {-1, -1, -1};
    int find_tag = 0;
    for (int h = 0; h < height; h++) {
        for (int w = 0; w < width; w++) {
            if (cp_img[h][w] > 240) {
                center = {w, h, 0};
                cp_img[h][w] = 0;
                find_tag = 1;
                break;
            }
        }
        if (find_tag == 1)
            break;
    }

    out << f_dirsteps(init_coord, convert_coord(center, width, height));
    center.z = 1;
    while (1) {
        next_center = find_dot(center, *cp_img, width, height);
        // cout << next_center.x << " " << next_center.y << " " << next_center.z
        //    << endl;
        if (int(next_center.z) == -1)
            break;

        if (int(next_center.z) > 30) {
            xyz temp1 = center;
            temp1.z = 0;
            out << f_dirsteps(convert_coord(center, width, height),
                              convert_coord(temp1, width, height));
            next_center.z = 0;
            xyz temp2 = next_center;
            out << f_dirsteps(convert_coord(temp1, width, height),
                              convert_coord(temp2, width, height));
            next_center.z = 1;
            out << f_dirsteps(convert_coord(temp2, width, height),
                              convert_coord(next_center, width, height));
        } else {
            next_center.z = 1;
            out << f_dirsteps(convert_coord(center, width, height),
                              convert_coord(next_center, width, height));
        }
        cp_img[int(center.y)][int(center.x)] = 0;
        center = next_center;
    }
    next_center = center;
    next_center.z = 0;
    out << f_dirsteps(convert_coord(center, width, height),
                      convert_coord(next_center, width, height));
    out << f_dirsteps(convert_coord(next_center, width, height), init_coord);
    out.close();
}

xyz find_dot(xyz center, int *cp_img, int width, int height) {
    int x = center.x;
    int y = center.y;
    xyz next_dot;

    int max_cr = max(max(max(x, y), abs(x - width + 1)), abs(y - height + 1));
    for (int cr = 1; cr < max_cr + 1; cr++) {       //分层找点
        for (int dn = -cr + 1; dn < cr + 1; dn++) { //下面的边
            if (y + cr + 1 > height)
                break;
            if (x + dn < 0)
                continue;
            if (x + dn + 1 > width)
                break;

            if (*(cp_img + width * (y + cr) + x + dn) > 245) {
                next_dot = {x + dn, y + cr, cr};
                *(cp_img + width * (y + cr) + x + dn) = 0;
                return next_dot;
            }
        }

        for (int rt = -cr + 1; rt < cr + 1; rt++) { //右面的边
            if (x + cr + 1 > width)
                break;
            if (y - rt + 2 > height)
                continue;
            if (y - rt < 0)
                break;

            if (*(cp_img + width * (y - rt) + x + cr) > 245) {
                next_dot = {x + cr, y - rt, cr};
                *(cp_img + width * (y - rt) + x + cr) = 0;
                return next_dot;
            }
        }

        for (int up = -cr + 1; up < cr + 1; up++) { //上面的边
            if (y - cr < 0)
                break;
            if (x - up + 2 > width)
                continue;
            if (x - up < 0)
                break;

            if (*(cp_img + width * (y - cr) + x - up) > 245) {
                next_dot = {x - up, y - cr, cr};
                *(cp_img + width * (y - cr) + x - up) = 0;
                return next_dot;
            }
        }

        for (int lt = -cr + 1; lt < cr + 1; lt++) { //左面的边
            if (x - cr < 0)
                break;
            if (y + lt < 0)
                continue;
            if (y + lt + 1 > height)
                break;

            if (*(cp_img + width * (y + lt) + x - cr) > 245) {
                next_dot = {x - cr, y + lt, cr};
                *(cp_img + width * (y + lt) + x - cr) = 0;
                return next_dot;
            }
        }
    }
    next_dot = {-1, -1, -1};
    return next_dot;
}

angles cal_angle(xyz coord) {
    float p = 0.0;
    angles angle;
    if (coord.x >= 0)
        angle.a = asin(coord.y / sqrt(coord.x * coord.x + coord.y * coord.y));
    else
        angle.a =
            asin(-coord.y / sqrt(coord.x * coord.x + coord.y * coord.y)) - PI;

    coord.y = coord.y - 80 * sin(angle.a);
    coord.x = coord.x - 80 * cos(angle.a);
    p = sqrt(coord.x * coord.x + coord.y * coord.y + coord.z * coord.z);
    angle.b = (acos((45 / p) + (p / 500)) + asin(-coord.z / p));
    angle.r = (acos((p * p - 22500) / (400 * p)) + acos(-coord.z / p));

    return angle;
}

string f_dirsteps(xyz curr, xyz next) {
    string fpath = "$";
    //  cout << curr.x << " " << curr.y << " " << curr.z << endl;
    angles curr_angles = cal_angle(curr);
    angles next_angles = cal_angle(next);
    float angle_a = next_angles.a - curr_angles.a;
    float angle_b = next_angles.b - curr_angles.b;
    float angle_r = next_angles.r - curr_angles.r;

    int a_step = round(angle_a * angle2step);
    int b_step = round(angle_b * angle2step);
    int r_step = round(angle_r * angle2step);

    if (!(a_step || b_step || r_step))
        return "";
    if (angle_a >= 0)
        fpath = fpath + "1" + num2str(a_step) + "#";
    else
        fpath = fpath + "0" + num2str(-a_step) + "#";

    if (angle_b >= 0)
        fpath = fpath + "1" + num2str(b_step) + "#";
    else
        fpath = fpath + "0" + num2str(-b_step) + "#";

    if (angle_r >= 0)
        fpath = fpath + "1" + num2str(r_step) + "#";
    else
        fpath = fpath + "0" + num2str(-r_step) + "#";

    fpath = fpath + "@";
    return fpath;
}

string num2str(int i) {
    stringstream ss;
    ss << i;
    return ss.str();
}

xyz convert_coord(xyz origin_coord, int width, int height) {
    xyz cvt_coord;
    int std_width;
    int std_height;
    float ratio;
    if (width >= height) {
        std_width = 7 * width;
        std_height = 10 * height;
        if (std_width < std_height) {
            ratio = 210.0 / height;
            cvt_coord.x = 330 - int(origin_coord.y * ratio);
            cvt_coord.y = (50 - (300 - int(width * ratio)) / 2) -
                          int(origin_coord.x * ratio);
            cvt_coord.z = std_z - 10 * origin_coord.z;
        } else {
            ratio = 300.0 / width;
            cvt_coord.x = (330 - (210 - int(height * ratio)) / 2) -
                          int(origin_coord.y * ratio);
            cvt_coord.y = 50 - int(origin_coord.x * ratio);
            cvt_coord.z = std_z - 10 * origin_coord.z;
        }
    } else {
        std_width = 10 * width;
        std_height = 7 * height;
        if (std_width < std_height) {
            ratio = 300.0 / height;
            cvt_coord.x = (120 + (210 - int(width * ratio)) / 2) +
                          int(origin_coord.x * ratio);
            cvt_coord.y = 50 - int(origin_coord.y * ratio);
            cvt_coord.z = std_z - 10 * origin_coord.z;
        } else {
            ratio = 210.0 / width;
            cvt_coord.x = 120 + int(origin_coord.x * ratio);
            cvt_coord.y = (50 - (300 - int(height * ratio)) / 2) -
                          int(origin_coord.y * ratio);
            cvt_coord.z = std_z - 10 * origin_coord.z;
        }
    }
    return cvt_coord;
}<|endoftext|>


<commit_before>#pragma once

#include <QGLWidget>
#include <QOpenGLFunctions>
#include <QTime>

#include <array>
#include <random>
#include <memory>

#include "textured_rect.hpp"
#include "bullet.hpp"
#include "space.hpp"
#include "unordered_map"
#include "images.hpp"

class GameWindow;

double constexpr PI = 3.14159265;

QT_FORWARD_DECLARE_CLASS(QOpenGLTexture)
QT_FORWARD_DECLARE_CLASS(QOpenGLShader)
QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram)

class GLWidget : public QGLWidget, protected QOpenGLFunctions
{
  Q_OBJECT
public:
  GLWidget(GameWindow * mw,
           QColor const & background,
           size_t const & level = 1);
  ~GLWidget();

protected:
  void resizeGL(int w, int h) override;
  void paintGL() override;
  void initializeGL() override;

  void Update(float elapsedSeconds);
  void RenderAlien();
  void RenderSpaceShip();
  void RenderBullet();
  void RenderObstacle();
  void RenderStar(float blend);
  void AddStar();
  void CheckHitSpaceShip();
  void KillSpaceShip(uint damage);
  void CheckHitAlien();
  void mousePressEvent(QMouseEvent * e) override;
  void mouseDoubleClickEvent(QMouseEvent * e) override;
  void mouseMoveEvent(QMouseEvent * e) override;
  void mouseReleaseEvent(QMouseEvent * e) override;
  void wheelEvent(QWheelEvent * e) override;
  void keyPressEvent(QKeyEvent * e) override;
  void keyReleaseEvent(QKeyEvent * e) override;

  void SpaceShipBulletsLogic();
  void AlienBulletsLogic();

  ///
  /// Generate random number between min and max values.
  ///
  /// Look here for more info:
  /// http://www.cplusplus.com/reference/random/uniform_real_distribution/
  ///
  double Random(double min, double max);

private:
  int L2D(int px) const { return px * devicePixelRatio(); }

  GameWindow * m_mainWindow;

  unsigned int m_frames = 0;
  QTime m_time;
  QColor m_background;
  QSize m_screenSize;

  // The current level number.
  size_t m_level = 0;

  // Number of aliens on the current level.
  size_t m_aliensNumber = 0;

  /// m_period is a value between 0.0 and 1.0 .
  /// It as a period.
  float m_period = 0.0f;

  std::vector<std::pair<float,float>> m_random;

  std::shared_ptr<Space> m_space = nullptr;

  TexturedRect * m_texturedRect = nullptr;

  std::array<bool, 4> m_directions = {{ false, false, false, false }};

  std::default_random_engine m_generator;
};
<commit_msg>rearrange code; add comments<commit_after>#pragma once

#include <QGLWidget>
#include <QOpenGLFunctions>
#include <QTime>

#include <array>
#include <random>
#include <memory>

#include "textured_rect.hpp"
#include "bullet.hpp"
#include "space.hpp"
#include "unordered_map"
#include "images.hpp"

class GameWindow;

double constexpr PI = 3.14159265;

QT_FORWARD_DECLARE_CLASS(QOpenGLTexture)
QT_FORWARD_DECLARE_CLASS(QOpenGLShader)
QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram)

class GLWidget : public QGLWidget, protected QOpenGLFunctions
{
  Q_OBJECT
public:
  GLWidget(GameWindow * mw,
           QColor const & background,
           size_t const & level = 1);
  ~GLWidget();

protected:
  void resizeGL(int w, int h) override;
  void paintGL() override;
  void initializeGL() override;

  void Update(float elapsedSeconds);

  /// Mouse and keyboard events.
  void mousePressEvent(QMouseEvent * e) override;
  void mouseDoubleClickEvent(QMouseEvent * e) override;
  void mouseMoveEvent(QMouseEvent * e) override;
  void mouseReleaseEvent(QMouseEvent * e) override;
  void wheelEvent(QWheelEvent * e) override;
  void keyPressEvent(QKeyEvent * e) override;
  void keyReleaseEvent(QKeyEvent * e) override;

  /// Create objects.
  void AddStar();

  /// Render stage.
  void RenderAlien();
  void RenderSpaceShip();
  void RenderBullet();
  void RenderObstacle();
  void RenderStar(float blend);

  /// Logic stage.
  void CheckHitAlien();
  void CheckHitSpaceShip();
  void KillSpaceShip(uint damage);
  void SpaceShipBulletsLogic();
  void AlienBulletsLogic();

  ///
  /// Generate random number between min and max values.
  ///
  /// Look here for more info:
  /// http://www.cplusplus.com/reference/random/uniform_real_distribution/
  ///
  double Random(double min, double max);

private:
  int L2D(int px) const { return px * devicePixelRatio(); }

  GameWindow * m_mainWindow;

  unsigned int m_frames = 0;
  QTime m_time;
  QColor m_background;
  QSize m_screenSize;

  // The current level number.
  size_t m_level = 0;

  // Number of aliens on the current level.
  size_t m_aliensNumber = 0;

  /// m_period is a value between 0.0 and 1.0 .
  /// It as a period.
  float m_period = 0.0f;

  std::vector<std::pair<float,float>> m_random;

  std::shared_ptr<Space> m_space = nullptr;

  TexturedRect * m_texturedRect = nullptr;

  std::array<bool, 4> m_directions = {{ false, false, false, false }};

  std::default_random_engine m_generator;
};
<|endoftext|>


<commit_before>#include <Halide.h>
#include "image_io.h"
#include <time.h>
#include <iostream>
#include <math.h>

using namespace Halide;
using namespace std;

Var x("x"), y("y"), c("c"), bin("bin");
Var cx("cx"), cy("cy");

Expr pi = (float) M_PI;

Func Gradient(Func input) {
  Func grad("grad");
  grad(x, y, c) = Tuple(
      input(x+2, y+1, c) - input(x, y+1, c),
      input(x+1, y+2, c) - input(x+1, y, c));
  return grad;
}

Func Abs(Func input) {
  Func abs("abs");
  abs(x, y, c) = hypot(input(x, y, c)[0], input(x, y, c)[1]);
  return abs;
}

Func Atan2(Func input) {
  Func fatan("fatan");
  fatan(x, y, c) = atan2(input(x, y, c)[1], input(x, y, c)[0]);
  return fatan;
}

Expr BinLookup(Expr angle, Param<uint8_t> nBins) {
  return cast<int8_t>(clamp(floor((angle + pi) * nBins / (2 * pi)), 0, nBins-1));
}

Func Bin(Func angles, Param<uint8_t> nBins) {
  Func bins("bins");
  bins(x, y, c) = BinLookup(angles(x, y, c), nBins);
  return bins;
}

Func Cell(Func bins, Param<uint32_t> cellX, Param<uint32_t> cellY) {
  RDom cell(0, cellX, 0, cellY);
  Func hist("hist");
  hist(x, y, c, bin) = 0;
  hist(x, y, c, bins(cell.x + x*cellX, cell.y + y*cellY, c)) += 1;

  return hist;
}

Func Proj(Func f, Param<uint8_t> nBins) {
  Func proj;
  proj(x, y, c) = f(x, y, c, 0) << 24;
  return proj;
}

int main(int argc, char** argv) {
  using namespace Halide;
  if (argc < 3 || argc > 5) {
    cerr << "USAGE:" << endl
         << "\t" << argv[0] << " INPUT OUTPUT" << endl;
  }
  Image<float> img = load<float>(argv[1]);
  Func input;
  input(x, y, c) = img(x, y, c);
  Param<uint8_t> nBins;
  Param<uint32_t> cellX, cellY;

  int32_t cellSize = 16;
  nBins.set(8);
  cellX.set(cellSize);
  cellY.set(cellSize);
  Func binned = Proj(Cell(Bin(Atan2(Gradient(input)), nBins), cellX, cellY), nBins);
  clock_t c1 = clock();
  binned.compute_root();
  binned.parallel(c);
  binned.vectorize(y, 16);
  binned.compile_jit();
  clock_t c2 = clock();
  cout << "compile: " << (c2 - c1) << endl;
  Image<int32_t> output;
  for (int i = 0; i < 20; i++) {
    clock_t c3 = clock();
    output = binned.realize((img.width() - 2)/cellSize, (img.height() - 2)/cellSize, img.channels());
    clock_t c4 = clock();
    cout << "run      " << (c4 - c3) << endl;
  }
  save(output, argv[2]);
}
<commit_msg>Second version: use lookup table for atan<commit_after>#include <Halide.h>
#include "image_io.h"
#include <time.h>
#include <iostream>
#include <math.h>

using namespace Halide;
using namespace std;

Var x("x"), y("y"), c("c"), bin("bin");
Var cx("cx"), cy("cy");

Expr pi = (float) M_PI;

Func GradientX(Func input) {
  Func gradx("gradx");
  gradx(x, y, c) = clamp(cast<int32_t>(input(x+2, y+1, c)) - cast<int32_t>(input(x, y+1, c)), -256, 256);
  return gradx;
}

Func GradientY(Func input) {
  Func grady("grady");
  grady(x, y, c) = clamp(cast<int32_t>(input(x+1, y+2, c)) - cast<int32_t>(input(x+1, y, c)),-256, 256);
  return grady;
}

Func Abs(Func input) {
  Func abs("abs");
  abs(x, y, c) = hypot(input(x, y, c)[0], input(x, y, c)[1]);
  return abs;
}

Expr BinLookup(Tuple p, Param<uint8_t> nBins) {
  return cast<int8_t>(clamp(floor((atan2(p[1], p[0]) + pi) * nBins / (2 * pi)), 0, nBins-1));
}

Func Bin(Func gradx, Func grady, Func lut) {
  Func bins("bins");
  bins(x, y, c) = lut(gradx(x, y, c)+256, grady(x,y,c)+256);
  return bins;
}

Func Atan2Lut(Param<uint8_t> nBins, Param<uint16_t> central) {
  Func lut("lut");
  Expr xx = x - 256;
  Expr yy = y - 256;
  lut(x, y) = select(xx*xx + yy*yy > central, BinLookup(Tuple(xx, yy), nBins)+1, 0);
  return lut;
}

Func Cell(Func bins, Param<uint32_t> cellX, Param<uint32_t> cellY) {
  RDom cell(0, cellX, 0, cellY);
  Func hist("hist");
  hist(x, y, c, bin) = 0.f;
  hist(x, y, c, bins(cell.x + x*cellX, cell.y + y*cellY, c)) += 1.f;

  return hist;
}

Func Proj(Func f, Param<uint8_t> nBins) {
  Func proj;
  proj(x, y, c) = f(x, y, c, 0)/100;
  return proj;
}

int main(int argc, char** argv) {
  using namespace Halide;
  if (argc < 3 || argc > 5) {
    cerr << "USAGE:" << endl
         << "\t" << argv[0] << " INPUT OUTPUT" << endl;
  }
  Image<int8_t> img = load<int8_t>(argv[1]);
  Func input;
  input(x, y, c) = img(x, y, c);
  Param<uint8_t> nBins;
  Param<uint16_t> central;
  Param<uint32_t> cellX, cellY;

  int32_t cellSize = 16;
  nBins.set(8);
  central.set(30*30);
  cellX.set(cellSize);
  cellY.set(cellSize);
  Func lut = Atan2Lut(nBins, central);
  lut.bound(x, 0, 512);
  lut.bound(y, 0, 512);
  lut.compute_root();

  Func gradx = GradientX(input);
  Func grady = GradientY(input);
  Func binned = Proj(Cell(Bin(gradx, grady, lut), cellX, cellY), nBins);
  clock_t c1 = clock();
  binned.bound(c, 0, 3).unroll(c);
  binned.bound(x, 0, (img.width() - 2)/cellSize);
  binned.bound(y, 0, (img.height() - 2)/cellSize);
  binned.compile_jit();
  binned.compute_root();
  clock_t c2 = clock();
  cout << "compile: " << (c2 - c1) << endl;
  Image<float> output;
  for (int i = 0; i < 20; i++) {
    clock_t c3 = clock();
    output = binned.realize((img.width() - 2)/cellSize, (img.height() - 2)/cellSize, img.channels());
    clock_t c4 = clock();
    cout << "run      " << (c4 - c3) << endl;
  }
  save(output, argv[2]);
}
<|endoftext|>


<commit_before><commit_msg>Fix a race condition in cached_iter evb (#66)<commit_after><|endoftext|>


<commit_before><commit_msg>-Werror,-Wunused-const-variable<commit_after><|endoftext|>


<commit_before><commit_msg>set spacing to output data of vtk image exporter<commit_after><|endoftext|>


<commit_before>//
// File:   map.cc
// Author: ruehle
//
// Created on April 13, 2007, 4:41 PM
//

#include "map.h"
#include <iostream>
#include <tools/matrix.h>
#include <tools/tokenizer.h>
#include <numeric>

using namespace std;

Map::~Map()
{
    vector<BeadMap *>::iterator iter;
    for(iter=_maps.begin();iter!=_maps.end();++iter)
        delete (*iter);
    _maps.clear();
}

void Map::Apply()
{
    vector<BeadMap *>::iterator iter;
    for(iter=_maps.begin();iter!=_maps.end();++iter)
        (*iter)->Apply();
}

void Map_Sphere::Initialize(Molecule *in, Bead *out, Property *opts_bead, Property *opts_map) {
    BeadMap::Initialize(in, out, opts_bead, opts_map);

    vector<string> beads;
    vector<double> weights;
    vector<double> fweights;

    // get the beads
    string s(_opts_bead->get("beads").value());
    Tokenizer tok_beads(s, " \n\t");
    tok_beads.ToVector(beads);

    // get vector of weights
    Tokenizer tok_weights(_opts_map->get("weights").value(), " \n\t");
    tok_weights.ConvertToVector<double>(weights);

    // check weather weights and # beads matches
    if (beads.size() != weights.size())
        throw runtime_error(string("number of subbeads in " +
                opts_bead->get("name").value()
                + "and number of weights in map "
                + opts_map->get("name").value() + " do not match"));

    // normalize the weights
    double norm = 1./ std::accumulate(weights.begin(), weights.end(), 0.);

    transform(weights.begin(), weights.end(), weights.begin(), bind2nd(multiplies<double>(), norm));
    // get the d vector if exists or initialize same as weights
    vector<double> d;
    if(_opts_map->exists("d")) {
        Tokenizer tok_weights(_opts_map->get("d").value(), " \n\t");
        tok_weights.ConvertToVector(d);
        // normalize d coefficients
        norm = 1./std::accumulate(d.begin(), d.end(), 0.);
        transform(d.begin(), d.end(), d.begin(), bind2nd(multiplies<double>(), norm));
    } else {
        // initialize force-weights with weights
        d.resize(weights.size());
        copy(weights.begin(), weights.end(), d.begin());
    }

    // check weather number of d coeffs is correct
    if (beads.size() != d.size()) {
        throw runtime_error(string("number of subbeads in " +
            opts_bead->get("name").value()
            + "and number of d-coefficients in map "
            + opts_map->get("name").value() + " do not match"));
    }

    fweights.resize(weights.size());
    // calculate force weights by d_i/w_i
    for(int i=0; i<weights.size(); ++i) {
        if(weights[i] == 0 && d[i]!=0) {
            throw runtime_error(
                "A d coefficient is nonzero while weights is zero in mapping "
                + opts_map->get("name").value());
        }
        if(weights[i] != 0)
            fweights[i] = d[i] / weights[i];
        else
            fweights[i] = 0;
    }

    for (size_t i = 0; i < beads.size(); ++i) {
        int iin = in->getBeadByName(beads[i]);
        if (iin < 0)
            throw std::runtime_error(string("mapping error: molecule " + beads[i] + " does not exist"));
        AddElem(in->getBead(iin), weights[i], fweights[i]);
    }
}

void Map_Sphere::Apply()
{
    vector<element_t>::iterator iter;
    vec cg(0., 0., 0.), f(0.,0.,0.), vel(0.,0.,0.);
    bool bPos, bVel, bF;
    bPos=bVel=bF=false;
    _out->ParentBeads().clear();
    for(iter = _matrix.begin(); iter != _matrix.end(); ++iter) {
        Bead *bead = iter->_in;
       _out->ParentBeads().push_back(bead->getId());
        if(bead->HasPos()) {
            cg += (*iter)._weight * bead->getPos();
            bPos=true;
        }
        if(bead->HasVel()) {
            vel += (*iter)._weight * bead->getVel();
            bVel = true;
        }
        if(bead->HasF()) {
            f += (*iter)._force_weight * bead->getF();
            bF = true;
        }
    }
    if(bPos)
        _out->setPos(cg);
    if(bVel)
        _out->setVel(vel);
    if(bF)
        _out->setF(f);
}

/// \todo implement this function
void Map_Ellipsoid::Apply()
{
    vector<element_t>::iterator iter;
    vec cg(0., 0., 0.), c(0., 0., 0.), f(0.,0.,0.), vel(0.,0.,0.);
    matrix m(0.);
     bool bPos, bVel, bF;
    bPos=bVel=bF=false;

    int n;
    n = 0;
    _out->ParentBeads().clear();
    for(iter = _matrix.begin(); iter != _matrix.end(); ++iter) {
       Bead *bead = iter->_in;
       _out->ParentBeads().push_back(bead->getId());
       if(bead->HasPos()) {
            cg += (*iter)._weight * bead->getPos();
            bPos=true;
        }
        if(bead->HasVel() == true) {
            vel += (*iter)._weight * bead->getVel();
            bVel = true;
        }
        if(bead->HasF()) {
            /// \todo fix me, right calculation should be F_i = m_cg / sum(w_i) * sum(w_i/m_i*F_i)
            //f += (*iter)._weight * _in->getBeadF((*iter)._in);
            f += (*iter)._force_weight * bead->getF();
            bF = true;
        }

        if((*iter)._weight>0 && bead->HasPos()) {
            c += bead->getPos();
            n++;
        }
    }

    if(bPos)
        _out->setPos(cg);
    if(bVel)
        _out->setVel(vel);
    if(bF)
        _out->setF(f);

    // calculate the tensor of gyration
    c=c/(double)n;
    for(iter = _matrix.begin(); iter != _matrix.end(); ++iter) {
        if((*iter)._weight == 0) continue;
        Bead *bead = iter->_in;
        vec v = bead->getPos() - c;
        //v = vec(1, 0.5, 0) * 0.*(drand48()-0.5)
        //    + vec(0.5, -1, 0) * (drand48()-0.5)
        //    + vec(0, 0, 1) * (drand48()-0.5);

        //Normalize the tensor with 1/number_of_atoms_per_bead
        m[0][0] += v.getX()*v.getX()/(double)_matrix.size();
        m[0][1] += v.getX()*v.getY()/(double)_matrix.size();
        m[0][2] += v.getX()*v.getZ()/(double)_matrix.size();
        m[1][1] += v.getY()*v.getY()/(double)_matrix.size();
        m[1][2] += v.getY()*v.getZ()/(double)_matrix.size();
        m[2][2] += v.getZ()*v.getZ()/(double)_matrix.size();
    }
    m[1][0] = m[0][1];
    m[2][0] = m[0][2];
    m[2][1] = m[1][2];

    // calculate the eigenvectors
    matrix::eigensystem_t es;
    m.SolveEigensystem(es);

    vec eigenv1=es.eigenvecs[0];
    vec eigenv2=es.eigenvecs[1];
    vec eigenv3=es.eigenvecs[2];

    _out->seteigenvec1(eigenv1);
    _out->seteigenvec2(eigenv2);
    _out->seteigenvec3(eigenv3);

    vec u = es.eigenvecs[0];
    vec v = _matrix[1]._in->getPos() - _matrix[0]._in->getPos();
    v.normalize();

    _out->setV(v);

    vec w = _matrix[2]._in->getPos() - _matrix[0]._in->getPos();
    w.normalize();

    //store the eigenvalues for the tensor of gyration
    double eigenvalue1 = es.eigenvalues[0];
    double eigenvalue2 = es.eigenvalues[1];
    double eigenvalue3 = es.eigenvalues[2];

    _out->setval1(eigenvalue1);
    _out->setval2(eigenvalue2);
    _out->setval3(eigenvalue3);

    if((v^w)*u < 0) u=vec(0.,0.,0.)-u;
    _out->setU(u);

    //write out w
    w=u^v;
    w.normalize();
    _out->setW(w);

    //out.BeadV(_out) = v;

    //out.BeadW(_out) = es.eigenvecs[2];
}
<commit_msg>corrected 2 typos<commit_after>//
// File:   map.cc
// Author: ruehle
//
// Created on April 13, 2007, 4:41 PM
//

#include "map.h"
#include <iostream>
#include <tools/matrix.h>
#include <tools/tokenizer.h>
#include <numeric>

using namespace std;

Map::~Map()
{
    vector<BeadMap *>::iterator iter;
    for(iter=_maps.begin();iter!=_maps.end();++iter)
        delete (*iter);
    _maps.clear();
}

void Map::Apply()
{
    vector<BeadMap *>::iterator iter;
    for(iter=_maps.begin();iter!=_maps.end();++iter)
        (*iter)->Apply();
}

void Map_Sphere::Initialize(Molecule *in, Bead *out, Property *opts_bead, Property *opts_map) {
    BeadMap::Initialize(in, out, opts_bead, opts_map);

    vector<string> beads;
    vector<double> weights;
    vector<double> fweights;

    // get the beads
    string s(_opts_bead->get("beads").value());
    Tokenizer tok_beads(s, " \n\t");
    tok_beads.ToVector(beads);

    // get vector of weights
    Tokenizer tok_weights(_opts_map->get("weights").value(), " \n\t");
    tok_weights.ConvertToVector<double>(weights);

    // check weather weights and # beads matches
    if (beads.size() != weights.size())
        throw runtime_error(string("number of subbeads in " +
                opts_bead->get("name").value()
                + " and number of weights in map "
                + opts_map->get("name").value() + " do not match"));

    // normalize the weights
    double norm = 1./ std::accumulate(weights.begin(), weights.end(), 0.);

    transform(weights.begin(), weights.end(), weights.begin(), bind2nd(multiplies<double>(), norm));
    // get the d vector if exists or initialize same as weights
    vector<double> d;
    if(_opts_map->exists("d")) {
        Tokenizer tok_weights(_opts_map->get("d").value(), " \n\t");
        tok_weights.ConvertToVector(d);
        // normalize d coefficients
        norm = 1./std::accumulate(d.begin(), d.end(), 0.);
        transform(d.begin(), d.end(), d.begin(), bind2nd(multiplies<double>(), norm));
    } else {
        // initialize force-weights with weights
        d.resize(weights.size());
        copy(weights.begin(), weights.end(), d.begin());
    }

    // check weather number of d coeffs is correct
    if (beads.size() != d.size()) {
        throw runtime_error(string("number of subbeads in " +
            opts_bead->get("name").value()
            + " and number of d-coefficients in map "
            + opts_map->get("name").value() + " do not match"));
    }

    fweights.resize(weights.size());
    // calculate force weights by d_i/w_i
    for(int i=0; i<weights.size(); ++i) {
        if(weights[i] == 0 && d[i]!=0) {
            throw runtime_error(
                "A d coefficient is nonzero while weights is zero in mapping "
                + opts_map->get("name").value());
        }
        if(weights[i] != 0)
            fweights[i] = d[i] / weights[i];
        else
            fweights[i] = 0;
    }

    for (size_t i = 0; i < beads.size(); ++i) {
        int iin = in->getBeadByName(beads[i]);
        if (iin < 0)
            throw std::runtime_error(string("mapping error: molecule " + beads[i] + " does not exist"));
        AddElem(in->getBead(iin), weights[i], fweights[i]);
    }
}

void Map_Sphere::Apply()
{
    vector<element_t>::iterator iter;
    vec cg(0., 0., 0.), f(0.,0.,0.), vel(0.,0.,0.);
    bool bPos, bVel, bF;
    bPos=bVel=bF=false;
    _out->ParentBeads().clear();
    for(iter = _matrix.begin(); iter != _matrix.end(); ++iter) {
        Bead *bead = iter->_in;
       _out->ParentBeads().push_back(bead->getId());
        if(bead->HasPos()) {
            cg += (*iter)._weight * bead->getPos();
            bPos=true;
        }
        if(bead->HasVel()) {
            vel += (*iter)._weight * bead->getVel();
            bVel = true;
        }
        if(bead->HasF()) {
            f += (*iter)._force_weight * bead->getF();
            bF = true;
        }
    }
    if(bPos)
        _out->setPos(cg);
    if(bVel)
        _out->setVel(vel);
    if(bF)
        _out->setF(f);
}

/// \todo implement this function
void Map_Ellipsoid::Apply()
{
    vector<element_t>::iterator iter;
    vec cg(0., 0., 0.), c(0., 0., 0.), f(0.,0.,0.), vel(0.,0.,0.);
    matrix m(0.);
     bool bPos, bVel, bF;
    bPos=bVel=bF=false;

    int n;
    n = 0;
    _out->ParentBeads().clear();
    for(iter = _matrix.begin(); iter != _matrix.end(); ++iter) {
       Bead *bead = iter->_in;
       _out->ParentBeads().push_back(bead->getId());
       if(bead->HasPos()) {
            cg += (*iter)._weight * bead->getPos();
            bPos=true;
        }
        if(bead->HasVel() == true) {
            vel += (*iter)._weight * bead->getVel();
            bVel = true;
        }
        if(bead->HasF()) {
            /// \todo fix me, right calculation should be F_i = m_cg / sum(w_i) * sum(w_i/m_i*F_i)
            //f += (*iter)._weight * _in->getBeadF((*iter)._in);
            f += (*iter)._force_weight * bead->getF();
            bF = true;
        }

        if((*iter)._weight>0 && bead->HasPos()) {
            c += bead->getPos();
            n++;
        }
    }

    if(bPos)
        _out->setPos(cg);
    if(bVel)
        _out->setVel(vel);
    if(bF)
        _out->setF(f);

    // calculate the tensor of gyration
    c=c/(double)n;
    for(iter = _matrix.begin(); iter != _matrix.end(); ++iter) {
        if((*iter)._weight == 0) continue;
        Bead *bead = iter->_in;
        vec v = bead->getPos() - c;
        //v = vec(1, 0.5, 0) * 0.*(drand48()-0.5)
        //    + vec(0.5, -1, 0) * (drand48()-0.5)
        //    + vec(0, 0, 1) * (drand48()-0.5);

        //Normalize the tensor with 1/number_of_atoms_per_bead
        m[0][0] += v.getX()*v.getX()/(double)_matrix.size();
        m[0][1] += v.getX()*v.getY()/(double)_matrix.size();
        m[0][2] += v.getX()*v.getZ()/(double)_matrix.size();
        m[1][1] += v.getY()*v.getY()/(double)_matrix.size();
        m[1][2] += v.getY()*v.getZ()/(double)_matrix.size();
        m[2][2] += v.getZ()*v.getZ()/(double)_matrix.size();
    }
    m[1][0] = m[0][1];
    m[2][0] = m[0][2];
    m[2][1] = m[1][2];

    // calculate the eigenvectors
    matrix::eigensystem_t es;
    m.SolveEigensystem(es);

    vec eigenv1=es.eigenvecs[0];
    vec eigenv2=es.eigenvecs[1];
    vec eigenv3=es.eigenvecs[2];

    _out->seteigenvec1(eigenv1);
    _out->seteigenvec2(eigenv2);
    _out->seteigenvec3(eigenv3);

    vec u = es.eigenvecs[0];
    vec v = _matrix[1]._in->getPos() - _matrix[0]._in->getPos();
    v.normalize();

    _out->setV(v);

    vec w = _matrix[2]._in->getPos() - _matrix[0]._in->getPos();
    w.normalize();

    //store the eigenvalues for the tensor of gyration
    double eigenvalue1 = es.eigenvalues[0];
    double eigenvalue2 = es.eigenvalues[1];
    double eigenvalue3 = es.eigenvalues[2];

    _out->setval1(eigenvalue1);
    _out->setval2(eigenvalue2);
    _out->setval3(eigenvalue3);

    if((v^w)*u < 0) u=vec(0.,0.,0.)-u;
    _out->setU(u);

    //write out w
    w=u^v;
    w.normalize();
    _out->setW(w);

    //out.BeadV(_out) = v;

    //out.BeadW(_out) = es.eigenvecs[2];
}
<|endoftext|>


<commit_before><commit_msg>Add the definition of 'populateData' function and refer to issue #26 Update 3 for more info<commit_after><|endoftext|>


<commit_before>/*##############################################################################

    Copyright (C) 2011 HPCC Systems.

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

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

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
############################################################################## */

#include "thhashdistrib.ipp"

#include "eclhelper.hpp"
#include "mptag.hpp"
#include "dasess.hpp"
#include "dadfs.hpp"
#include "jhtree.hpp"

#include "thorport.hpp"
#include "thbufdef.hpp"
#include "thmem.hpp"
#include "thexception.hpp"

#define NUMINPARALLEL 16

enum DistributeMode { DM_distrib, DM_dedup, DM_join , DM_groupaggregate, DM_index, DM_redistribute, DM_distribmerge };

class HashDistributeMasterBase : public CMasterActivity
{
    DistributeMode mode;
    mptag_t mptag;
    mptag_t mptag2; // for tag 2
    bool redistribute;
    double skew;
    double targetskew;
public:
    HashDistributeMasterBase(DistributeMode _mode, CMasterGraphElement *info)
        : CMasterActivity(info), mode(_mode)
    {
        mptag = TAG_NULL;
        mptag2 = TAG_NULL;
    }

    ~HashDistributeMasterBase()
    {
        if (mptag!=TAG_NULL)
            container.queryJob().freeMPTag(mptag);
        if (mptag2!=TAG_NULL)
            container.queryJob().freeMPTag(mptag2);
    }

protected:
    virtual void init()
    {
        mptag = container.queryJob().allocateMPTag();
        if (mode==DM_join)
            mptag2 = container.queryJob().allocateMPTag();
    }
    virtual void process()
    {
        ActPrintLog("HashDistributeActivityMaster::process");

        CMasterActivity::process();
        ActPrintLog("HashDistributeActivityMaster::process exit");
    }
    virtual void done()
    {
        ActPrintLog("HashDistributeActivityMaster::done");
        CMasterActivity::done();
        ActPrintLog("HashDistributeActivityMaster::done exit");
    }
    virtual void serializeSlaveData(MemoryBuffer &dst, unsigned slave)
    {
        dst.append((int)mptag);
        if (mode==DM_join)
            dst.append((int)mptag2);
    }
};

class HashDistributeActivityMaster : public HashDistributeMasterBase
{
public:
    HashDistributeActivityMaster(DistributeMode mode, CMasterGraphElement *info) : HashDistributeMasterBase(mode, info) { }
};

class HashJoinDistributeActivityMaster : public HashDistributeActivityMaster
{
    Owned<ProgressInfo> lhsProgress, rhsProgress;

public:
    HashJoinDistributeActivityMaster(DistributeMode mode, CMasterGraphElement *info) : HashDistributeActivityMaster(mode, info)
    {
        lhsProgress.setown(new ProgressInfo);
        rhsProgress.setown(new ProgressInfo);
    }
    virtual void deserializeStats(unsigned node, MemoryBuffer &mb)
    {
        HashDistributeActivityMaster::deserializeStats(node, mb);
        rowcount_t lhsProgressCount, rhsProgressCount;
        mb.read(lhsProgressCount);
        mb.read(rhsProgressCount);
        lhsProgress->set(node, lhsProgressCount);
        rhsProgress->set(node, rhsProgressCount);
    }
    virtual void getXGMML(unsigned idx, IPropertyTree *edge)
    {
        HashDistributeActivityMaster::getXGMML(idx, edge);
        assertex(0 == idx);
        lhsProgress->processInfo();
        rhsProgress->processInfo();

        StringBuffer label;
        label.append("@progressInput-").append(container.queryInput(0)->queryId());
        edge->setPropInt64(label.str(), lhsProgress->queryTotal());
        label.clear().append("@progressInput-").append(container.queryInput(1)->queryId());
        edge->setPropInt64(label.str(), rhsProgress->queryTotal());
    }
};

class IndexDistributeActivityMaster : public HashDistributeMasterBase
{
    MemoryBuffer tlkMb;

public:
    IndexDistributeActivityMaster(CMasterGraphElement *info) : HashDistributeMasterBase(DM_index, info) { }
    virtual void init()
    {
        HashDistributeMasterBase::init();

        // JCSMORE should common up some with indexread
        IHThorKeyedDistributeArg *helper = (IHThorKeyedDistributeArg *)queryHelper();

        StringBuffer scoped;
        queryThorFileManager().addScope(container.queryJob(), helper->getIndexFileName(), scoped);
        Owned<IDistributedFile> f = queryThorFileManager().lookup(container.queryJob(), helper->getIndexFileName());
        if (!f)
            throw MakeActivityException(this, 0, "KeyedDistribute: Failed to find key: %s", scoped.str());
        if (0 == f->numParts())
            throw MakeActivityException(this, 0, "KeyedDistribute: Can't distribute based on an empty key: %s", scoped.str());

        checkFormatCrc(this, f, helper->getFormatCrc(), true);
        Owned<IFileDescriptor> fileDesc = f->getFileDescriptor();
        Owned<IPartDescriptor> tlkDesc = fileDesc->getPart(fileDesc->numParts()-1);
        if (!tlkDesc->queryProperties().hasProp("@kind") || 0 != stricmp("topLevelKey", tlkDesc->queryProperties().queryProp("@kind")))
            throw MakeActivityException(this, 0, "Cannot distribute using a non-distributed key: '%s'", scoped.str());
        unsigned location;
        OwnedIFile iFile;
        StringBuffer filePath;
        if (!getBestFilePart(this, *tlkDesc, iFile, location, filePath))
            throw MakeThorException(TE_FileNotFound, "Top level key part does not exist, for key: %s", f->queryLogicalName());
        OwnedIFileIO iFileIO = iFile->open(IFOread);
        assertex(iFileIO);

        tlkMb.append(iFileIO->size());
        ::read(iFileIO, 0, (size32_t)iFileIO->size(), tlkMb);

        queryThorFileManager().noteFileRead(container.queryJob(), f);
    }

    void serializeSlaveData(MemoryBuffer &dst, unsigned slave)
    {
        HashDistributeMasterBase::serializeSlaveData(dst, slave); // have to chain for standard activity data..
        dst.append(tlkMb);
    }
};

class ReDistributeActivityMaster : public HashDistributeMasterBase
{
    mptag_t statstag;

public:
    ReDistributeActivityMaster(CMasterGraphElement *info) : HashDistributeMasterBase(DM_redistribute, info)
    {
        statstag = container.queryJob().allocateMPTag();
    }
    ~ReDistributeActivityMaster()
    {
        container.queryJob().freeMPTag(statstag);
    }
    void serializeSlaveData(MemoryBuffer &dst, unsigned slave)
    {
        HashDistributeMasterBase::serializeSlaveData(dst, slave); // have to chain for standard activity data..
        dst.append((int)statstag);
    }
    void process()
    {
        ActPrintLog("ReDistributeActivityMaster::process");
        HashDistributeMasterBase::process();
        IHThorHashDistributeArg *helper = (IHThorHashDistributeArg *)queryHelper();
        unsigned n = container.queryJob().querySlaves();
        MemoryAttr ma;
        offset_t *sizes = (offset_t *)ma.allocate(sizeof(offset_t)*n);
        unsigned i;
        try {
            for (i=0;i<n;i++) {
                if (abortSoon)
                    return;
                CMessageBuffer mb;
#ifdef _TRACE
                ActPrintLog("ReDistribute process, Receiving on tag %d",statstag);
#endif
                rank_t sender;
                if (!receiveMsg(mb, RANK_ALL, statstag, &sender)||abortSoon)
                    return;
#ifdef _TRACE
                ActPrintLog("ReDistribute process, Received size from %d",sender);
#endif
                sender--;
                assertex((unsigned)sender<n);
                mb.read(sizes[sender]);
            }
            ActPrintLog("ReDistributeActivityMaster::process sizes got");
            for (i=0;i<n;i++) {
                CMessageBuffer mb;
                mb.append(n*sizeof(offset_t),sizes);
#ifdef _TRACE
                ActPrintLog("ReDistribute process, Replying to node %d tag %d",i+1,statstag);
#endif
                if (!container.queryJob().queryJobComm().send(mb, (rank_t)i+1, statstag))
                    return;
            }
            // check if any max skew broken
            double maxskew = helper->getTargetSkew();
            if (maxskew>helper->getSkew()) {
                offset_t tot = 0;
                for (i=0;i<n;i++)
                    tot += sizes[i];
                offset_t avg = tot/n;
                for (i=0;i<n;i++) {
                    double r = ((double)sizes[i]-(double)avg)/(double)avg;
                    if ((r>=maxskew)||(-r>maxskew)) {
                        throw MakeActivityException(this, TE_DistributeFailedSkewExceeded, "DISTRIBUTE maximum skew exceeded (node %d has %"I64F"d, average is %"I64F"d)",i+1,sizes[i],avg);
                    }
                }
            }

        }
        catch (IException *e) {
            ActPrintLog(e,"ReDistribute");
            throw;
        }
        ActPrintLog("ReDistributeActivityMaster::process exit");
    }
    void abort()
    {
        HashDistributeMasterBase::abort();
        cancelReceiveMsg(RANK_ALL, statstag);
    }
};

CActivityBase *createHashDistributeActivityMaster(CMasterGraphElement *container)
{
    if (container&&(((IHThorHashDistributeArg *)container->queryHelper())->queryHash()==NULL))
        return new ReDistributeActivityMaster(container);
    else
        return new HashDistributeActivityMaster(DM_distrib, container);
}

CActivityBase *createDistributeMergeActivityMaster(CMasterGraphElement *container)
{
    return new HashDistributeActivityMaster(DM_distribmerge, container);
}

CActivityBase *createHashDedupMergeActivityMaster(CMasterGraphElement *container)
{
    if (container->queryLocalOrGrouped())
        return new CMasterActivity(container);
    else
        return new HashDistributeActivityMaster(DM_dedup, container);
}

CActivityBase *createHashJoinActivityMaster(CMasterGraphElement *container)
{
        return new HashJoinDistributeActivityMaster(DM_join, container);
}

CActivityBase *createHashAggregateActivityMaster(CMasterGraphElement *container)
{
    return new HashDistributeActivityMaster(DM_groupaggregate, container);
}

CActivityBase *createKeyedDistributeActivityMaster(CMasterGraphElement *container)
{
    return new IndexDistributeActivityMaster(container);
}
<commit_msg>gh-1476 - Fix regression in hashagg,local<commit_after>/*##############################################################################

    Copyright (C) 2011 HPCC Systems.

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

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

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
############################################################################## */

#include "thhashdistrib.ipp"

#include "eclhelper.hpp"
#include "mptag.hpp"
#include "dasess.hpp"
#include "dadfs.hpp"
#include "jhtree.hpp"

#include "thorport.hpp"
#include "thbufdef.hpp"
#include "thmem.hpp"
#include "thexception.hpp"

#define NUMINPARALLEL 16

enum DistributeMode { DM_distrib, DM_dedup, DM_join , DM_groupaggregate, DM_index, DM_redistribute, DM_distribmerge };

class HashDistributeMasterBase : public CMasterActivity
{
    DistributeMode mode;
    mptag_t mptag;
    mptag_t mptag2; // for tag 2
    bool redistribute;
    double skew;
    double targetskew;
public:
    HashDistributeMasterBase(DistributeMode _mode, CMasterGraphElement *info)
        : CMasterActivity(info), mode(_mode)
    {
        mptag = TAG_NULL;
        mptag2 = TAG_NULL;
    }

    ~HashDistributeMasterBase()
    {
        if (mptag!=TAG_NULL)
            container.queryJob().freeMPTag(mptag);
        if (mptag2!=TAG_NULL)
            container.queryJob().freeMPTag(mptag2);
    }

protected:
    virtual void init()
    {
        mptag = container.queryJob().allocateMPTag();
        if (mode==DM_join)
            mptag2 = container.queryJob().allocateMPTag();
    }
    virtual void process()
    {
        ActPrintLog("HashDistributeActivityMaster::process");

        CMasterActivity::process();
        ActPrintLog("HashDistributeActivityMaster::process exit");
    }
    virtual void done()
    {
        ActPrintLog("HashDistributeActivityMaster::done");
        CMasterActivity::done();
        ActPrintLog("HashDistributeActivityMaster::done exit");
    }
    virtual void serializeSlaveData(MemoryBuffer &dst, unsigned slave)
    {
        dst.append((int)mptag);
        if (mode==DM_join)
            dst.append((int)mptag2);
    }
};

class HashDistributeActivityMaster : public HashDistributeMasterBase
{
public:
    HashDistributeActivityMaster(DistributeMode mode, CMasterGraphElement *info) : HashDistributeMasterBase(mode, info) { }
};

class HashJoinDistributeActivityMaster : public HashDistributeActivityMaster
{
    Owned<ProgressInfo> lhsProgress, rhsProgress;

public:
    HashJoinDistributeActivityMaster(DistributeMode mode, CMasterGraphElement *info) : HashDistributeActivityMaster(mode, info)
    {
        lhsProgress.setown(new ProgressInfo);
        rhsProgress.setown(new ProgressInfo);
    }
    virtual void deserializeStats(unsigned node, MemoryBuffer &mb)
    {
        HashDistributeActivityMaster::deserializeStats(node, mb);
        rowcount_t lhsProgressCount, rhsProgressCount;
        mb.read(lhsProgressCount);
        mb.read(rhsProgressCount);
        lhsProgress->set(node, lhsProgressCount);
        rhsProgress->set(node, rhsProgressCount);
    }
    virtual void getXGMML(unsigned idx, IPropertyTree *edge)
    {
        HashDistributeActivityMaster::getXGMML(idx, edge);
        assertex(0 == idx);
        lhsProgress->processInfo();
        rhsProgress->processInfo();

        StringBuffer label;
        label.append("@progressInput-").append(container.queryInput(0)->queryId());
        edge->setPropInt64(label.str(), lhsProgress->queryTotal());
        label.clear().append("@progressInput-").append(container.queryInput(1)->queryId());
        edge->setPropInt64(label.str(), rhsProgress->queryTotal());
    }
};

class IndexDistributeActivityMaster : public HashDistributeMasterBase
{
    MemoryBuffer tlkMb;

public:
    IndexDistributeActivityMaster(CMasterGraphElement *info) : HashDistributeMasterBase(DM_index, info) { }
    virtual void init()
    {
        HashDistributeMasterBase::init();

        // JCSMORE should common up some with indexread
        IHThorKeyedDistributeArg *helper = (IHThorKeyedDistributeArg *)queryHelper();

        StringBuffer scoped;
        queryThorFileManager().addScope(container.queryJob(), helper->getIndexFileName(), scoped);
        Owned<IDistributedFile> f = queryThorFileManager().lookup(container.queryJob(), helper->getIndexFileName());
        if (!f)
            throw MakeActivityException(this, 0, "KeyedDistribute: Failed to find key: %s", scoped.str());
        if (0 == f->numParts())
            throw MakeActivityException(this, 0, "KeyedDistribute: Can't distribute based on an empty key: %s", scoped.str());

        checkFormatCrc(this, f, helper->getFormatCrc(), true);
        Owned<IFileDescriptor> fileDesc = f->getFileDescriptor();
        Owned<IPartDescriptor> tlkDesc = fileDesc->getPart(fileDesc->numParts()-1);
        if (!tlkDesc->queryProperties().hasProp("@kind") || 0 != stricmp("topLevelKey", tlkDesc->queryProperties().queryProp("@kind")))
            throw MakeActivityException(this, 0, "Cannot distribute using a non-distributed key: '%s'", scoped.str());
        unsigned location;
        OwnedIFile iFile;
        StringBuffer filePath;
        if (!getBestFilePart(this, *tlkDesc, iFile, location, filePath))
            throw MakeThorException(TE_FileNotFound, "Top level key part does not exist, for key: %s", f->queryLogicalName());
        OwnedIFileIO iFileIO = iFile->open(IFOread);
        assertex(iFileIO);

        tlkMb.append(iFileIO->size());
        ::read(iFileIO, 0, (size32_t)iFileIO->size(), tlkMb);

        queryThorFileManager().noteFileRead(container.queryJob(), f);
    }

    void serializeSlaveData(MemoryBuffer &dst, unsigned slave)
    {
        HashDistributeMasterBase::serializeSlaveData(dst, slave); // have to chain for standard activity data..
        dst.append(tlkMb);
    }
};

class ReDistributeActivityMaster : public HashDistributeMasterBase
{
    mptag_t statstag;

public:
    ReDistributeActivityMaster(CMasterGraphElement *info) : HashDistributeMasterBase(DM_redistribute, info)
    {
        statstag = container.queryJob().allocateMPTag();
    }
    ~ReDistributeActivityMaster()
    {
        container.queryJob().freeMPTag(statstag);
    }
    void serializeSlaveData(MemoryBuffer &dst, unsigned slave)
    {
        HashDistributeMasterBase::serializeSlaveData(dst, slave); // have to chain for standard activity data..
        dst.append((int)statstag);
    }
    void process()
    {
        ActPrintLog("ReDistributeActivityMaster::process");
        HashDistributeMasterBase::process();
        IHThorHashDistributeArg *helper = (IHThorHashDistributeArg *)queryHelper();
        unsigned n = container.queryJob().querySlaves();
        MemoryAttr ma;
        offset_t *sizes = (offset_t *)ma.allocate(sizeof(offset_t)*n);
        unsigned i;
        try {
            for (i=0;i<n;i++) {
                if (abortSoon)
                    return;
                CMessageBuffer mb;
#ifdef _TRACE
                ActPrintLog("ReDistribute process, Receiving on tag %d",statstag);
#endif
                rank_t sender;
                if (!receiveMsg(mb, RANK_ALL, statstag, &sender)||abortSoon)
                    return;
#ifdef _TRACE
                ActPrintLog("ReDistribute process, Received size from %d",sender);
#endif
                sender--;
                assertex((unsigned)sender<n);
                mb.read(sizes[sender]);
            }
            ActPrintLog("ReDistributeActivityMaster::process sizes got");
            for (i=0;i<n;i++) {
                CMessageBuffer mb;
                mb.append(n*sizeof(offset_t),sizes);
#ifdef _TRACE
                ActPrintLog("ReDistribute process, Replying to node %d tag %d",i+1,statstag);
#endif
                if (!container.queryJob().queryJobComm().send(mb, (rank_t)i+1, statstag))
                    return;
            }
            // check if any max skew broken
            double maxskew = helper->getTargetSkew();
            if (maxskew>helper->getSkew()) {
                offset_t tot = 0;
                for (i=0;i<n;i++)
                    tot += sizes[i];
                offset_t avg = tot/n;
                for (i=0;i<n;i++) {
                    double r = ((double)sizes[i]-(double)avg)/(double)avg;
                    if ((r>=maxskew)||(-r>maxskew)) {
                        throw MakeActivityException(this, TE_DistributeFailedSkewExceeded, "DISTRIBUTE maximum skew exceeded (node %d has %"I64F"d, average is %"I64F"d)",i+1,sizes[i],avg);
                    }
                }
            }

        }
        catch (IException *e) {
            ActPrintLog(e,"ReDistribute");
            throw;
        }
        ActPrintLog("ReDistributeActivityMaster::process exit");
    }
    void abort()
    {
        HashDistributeMasterBase::abort();
        cancelReceiveMsg(RANK_ALL, statstag);
    }
};

CActivityBase *createHashDistributeActivityMaster(CMasterGraphElement *container)
{
    if (container&&(((IHThorHashDistributeArg *)container->queryHelper())->queryHash()==NULL))
        return new ReDistributeActivityMaster(container);
    else
        return new HashDistributeActivityMaster(DM_distrib, container);
}

CActivityBase *createDistributeMergeActivityMaster(CMasterGraphElement *container)
{
    return new HashDistributeActivityMaster(DM_distribmerge, container);
}

CActivityBase *createHashDedupMergeActivityMaster(CMasterGraphElement *container)
{
    if (container->queryLocalOrGrouped())
        return new CMasterActivity(container);
    else
        return new HashDistributeActivityMaster(DM_dedup, container);
}

CActivityBase *createHashJoinActivityMaster(CMasterGraphElement *container)
{
        return new HashJoinDistributeActivityMaster(DM_join, container);
}

CActivityBase *createHashAggregateActivityMaster(CMasterGraphElement *container)
{
    if (container->queryLocalOrGrouped())
        return new CMasterActivity(container);
    else
        return new HashDistributeActivityMaster(DM_groupaggregate, container);
}

CActivityBase *createKeyedDistributeActivityMaster(CMasterGraphElement *container)
{
    return new IndexDistributeActivityMaster(container);
}
<|endoftext|>