<commit_before>#include "TextInputWidget.hpp"
#include <iostream>

gsf::TextInputWidget::TextInputWidget(float width, float height, sf::Font &font)
: ChildWidget{ width, height }
//, m_text{ "", font, 12, sf::Color::Black }
, m_text{ nullptr }
, m_cursor{ "|", font, 12 }
, m_scrollable{ nullptr }
, m_isFocused{ false }
, m_cursorPos{ 0 }
, m_lBreaksBefCur{ 0 }
, m_isCursorShown{ true }
, m_blinkFreq{ 0.8f }
, m_lastBlinkTime{ 0.f }
, m_minBreakCharCnt{ 0 }
{
    std::unique_ptr<TextWidget> text{
        std::make_unique<TextWidget>("", font, 12, sf::Color::Black) };
    std::unique_ptr<ScrollableWidget> scrollabe{
        std::make_unique<ScrollableWidget>(width, height) };
    m_scrollable = scrollabe.get();
    m_text = text.get();
    scrollabe->setBackgroundColor(sf::Color::Red);
    scrollabe->attachChild(std::move(text));
    //attachChild(std::move(text));
    attachChild(std::move(scrollabe));
    m_cursor.setFillColor(sf::Color::Black);

    //m_text.setFont(font);
    //m_text.setCharacterSize(12);
    //m_text.setTextColor(sf::Color::Black);
    //m_text.setOrigin(0.f, 0.f);
    //m_text.setPosition(0.f, 0.f);
    //m_scrollableWidget.attachChild();
}

void gsf::TextInputWidget::setText(const std::string &text)
{
   m_text->setText(text);
}

std::string gsf::TextInputWidget::getText() const
{
   return m_text->getText().toAnsiString();
}

void gsf::TextInputWidget::setCharacterSize(const unsigned int size)
{
   m_text->setCharacterSize(size);
}

unsigned int gsf::TextInputWidget::getCharacterSize() const
{
   return m_text->getCharacterSize();
}

void gsf::TextInputWidget::setTextColor(const sf::Color color)
{
   m_text->setTextColor(color);
}

sf::Color gsf::TextInputWidget::getTextColor() const
{
   return m_text->getTextColor();
}

bool gsf::TextInputWidget::isFocused() const
{
    return m_isFocused;
}

void gsf::TextInputWidget::setIsVerticalScrollEnabled(bool isEnabled)
{
    m_scrollable->setIsVerticalScrollEnabled(isEnabled);
}

bool gsf::TextInputWidget::isVerticalScrollEnabled() const
{
    return m_scrollable->isVerticalScrollEnabled();
}

void gsf::TextInputWidget::setIsHorizontalScrollEnabled(bool isEnabled)
{
    m_scrollable->setIsHorizontalScrollEnabled(isEnabled);
}

bool gsf::TextInputWidget::isHorizontalScrollEnabled() const
{
    return m_scrollable->isHorizontalScrollEnabled();
}

void gsf::TextInputWidget::drawCurrent(sf::RenderTarget &target,
        sf::RenderStates states) const
{

}

void gsf::TextInputWidget::drawCurrentAfterChildren(sf::RenderTarget &target,
                    sf::RenderStates states) const
{
    // Draw cursor after children, so that children are not drawn over cursor
    if (m_isCursorShown)
    {
        target.draw(m_cursor, states);
    }
}

void gsf::TextInputWidget::updateCurrent(float dt)
{
    // Update cursor stuff
    m_lastBlinkTime += dt;
    if (m_lastBlinkTime >= m_blinkFreq)
    {
        m_isCursorShown = !m_isCursorShown;
        m_lastBlinkTime = 0.f;
    }
    //std::wstring text{ m_currentText };
    //std::wstring text{ m_shownText };
    //m_text->setText(text);
}

bool gsf::TextInputWidget::handleEventCurrent(sf::Event &event)
{
    //bool handled{ ChildWidget::handleEvent(event) };/*||
      //  m_scrollable->handleEventWidget(event) };*/
    // Check if actual Widget is focused
    if (event.type == sf::Event::MouseButtonPressed)
    {
        sf::Vector2f mousePos{ (float) event.mouseButton.x,
        (float) event.mouseButton.y };
        bool isMouseInShownArea{ getShownArea().contains(mousePos) };
        bool intersecting{ isIntersecting(mousePos) };
        if (isMouseInShownArea && intersecting)
        {
            m_isFocused = true;
        }
        else
        {
            m_isFocused = false;
        }
    }
    if (event.type == sf::Event::KeyPressed && m_isFocused)
    {
        switch (event.key.code)
        {
        case sf::Keyboard::Left:
            if (m_cursorPos > 0)
            {
                m_cursorPos--;
            }
            // when cursor is moved it should be drawn so we reset its status
            resetCursorStatus();
            adjustShownText();
            return true;
        case sf::Keyboard::Right:
            if (m_cursorPos < m_currentText.length())
            {
                m_cursorPos++;
            }
            resetCursorStatus();
            adjustShownText();
            m_cursor.setPosition
                (m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
            return true;
        default: break;
        }
    }
    // If Widget is focused and Text entered, handle entered text
    if (m_isFocused && event.type == sf::Event::TextEntered)
    {
        // To handle umlauts and other 'exotic' chars we use widestring
        // and wide char
        //std::wstring actualTxt{ m_text.getString().toWideString() };
        wchar_t c{ static_cast<wchar_t>(event.text.unicode) };
        std::cout << "Entered: " << c << std::endl;
        switch (c)
        {
        // Backspace
        case 8:
            if (m_currentText.length() > 0)
            {
                // Remove chars right of cursor when there are chars
                if (m_cursorPos > 0 && m_cursorPos < m_currentText.length())
                {
                    m_currentText.erase(m_cursorPos - 1, 1);
                    m_cursorPos--;
                }
                // When cursos is at the end of the text, p
                // place cursor behind char which we want to delete,
                else if (m_cursorPos == m_currentText.length())
                {
                    // Delete last char
                    m_currentText.pop_back();
                    m_cursorPos--;
                }
            }
            break;
        // Delete Pressed
        case 127:
            if (m_currentText.length() > 0 &&
                    m_cursorPos < m_currentText.length())
            {
                m_currentText.erase(m_cursorPos, 1);
            }
            break;
        // Enter key
        case 13: m_currentText.insert(m_cursorPos, L"\n"); m_cursorPos++; break;
        // Add char to text
        default: m_currentText.insert(m_cursorPos, std::wstring() + c); m_cursorPos++;
        }
        resetCursorStatus();
        m_shownText = m_currentText;
        m_text->setText(m_shownText);
        adjustShownText();
        m_cursor.setPosition(m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
        m_scrollable->recalculateScroll();
        m_scrollable->scrollToRight();
        m_scrollable->scrollToBottom();
        return true;
    }
    return false;
    //return handled;
}

void gsf::TextInputWidget::adjustShownText()
{
    /*
    if (m_scrollable->isHorizontalScrollEnabled() || m_currentText.size() == 0)
        return;

    m_lBreaksBefCur = 0;
    m_text->setText("");
    m_shownText = L"";
    // Add min cnt of chars we had in the past for a line break
    m_shownText = m_currentText.substr(0, m_minBreakCharCnt);
    // Start searching by the min cnt of chars we had in the past
    bool done{ false };
    unsigned int actualPos = m_minBreakCharCnt;
    do
    {
        m_text->setText(m_shownText);
        // Search expotenzial the pos where text dont fits anymore, and then
        // search binary in this area
        int i{ 1 };
        while(m_text->getWidth() < m_scrollable->getWidth())
        {
            wchar_t c{ m_currentText[actualPos + i - 1] };
            m_shownText += c;
        }
        // The search area is now between i / 2 and i -1
        // In this area we now search binary

        // Remove chars util the text fits in its parent
        while(m_text->getWidth() > m_scrollable->getWidth())
        {
            m_shownText.pop_back();
            actualPos--;
            m_text->setText(m_shownText);
            // The minimum has changed
            m_minBreakCharCnt--;
        };

    } while (!done);
    */

    // advance is the with of the glyph
    //float advance { m_text->getFont().getGlyph(c, m_text->getCharacterSize(),
    //    false).advance };
    if (!m_scrollable->isHorizontalScrollEnabled())
    {
        //std::cout << "POS: (" << m_text->findCharacterPos(1).x  << "|"
        //    << m_text->findCharacterPos(0).y << ")" << std::endl;
        m_lBreaksBefCur = 0;
        //m_text->setText("");
        sf::Text tmpText("", m_text->getFont(), m_text->getCharacterSize());
        std::wstring tmpString{ L"" };
        std::wstring shownString{ L"" };
        //m_shownText = L"";
        unsigned int charCntLine{ 0 };
        for (unsigned int i{ 0 }; i < m_currentText.size(); i++)
        {
            wchar_t c{ m_currentText[i] };
            float advance { m_text->getFont().getGlyph(c, m_text->getCharacterSize(),
                    false).advance };
            std::cout << "Advance: " << advance << std::endl;

            tmpString += c;
            tmpText.setString(tmpString);
            // Text is out of widget so add a line break before the last added char
            if (tmpText.findCharacterPos(i + 1).x > m_scrollable->getWidth())
            {
                if (i < m_cursorPos)
                {
                    // We have to increase the "line breaks befor cursor" counter
                    // so we add the cursor later on the right position
                    m_lBreaksBefCur++;
                }
                shownString += tmpString.substr(i - charCntLine, charCntLine);
                shownString += L"\n";
                tmpString = L"";
                tmpString += c;
                charCntLine = 1;
            }
            else
            {
                charCntLine++;
            }
        }
        shownString += tmpString;
        m_shownText = shownString;
        m_text->setText(m_shownText);
    }
    /*
    if (!m_scrollable->isHorizontalScrollEnabled())
    {
        //std::cout << "POS: (" << m_text->findCharacterPos(1).x  << "|"
        //    << m_text->findCharacterPos(0).y << ")" << std::endl;
        m_lBreaksBefCur = 0;
        m_text->setText("");
        m_shownText = L"";
        for (unsigned int i{ 0 }; i != m_currentText.size(); i++)
        {
            wchar_t c{ m_currentText[i] };
            m_shownText += c;
            m_text->setText(m_shownText);
            // Text is out of widget so add a line break before the last added char
            if (m_text->findCharacterPos(i).x > m_scrollable->getWidth())
            {
                if (i < m_cursorPos)
                {
                    // We have to increase the "line breaks befor cursor" counter
                    // so we add the cursor later on the right position
                    m_lBreaksBefCur++;
                }
                m_shownText.insert(m_shownText.size() - 2, L"\n");
            }
        }
        m_text->setText(m_shownText);
    }
    */
}

void gsf::TextInputWidget::resetCursorStatus()
{
    m_lastBlinkTime = 0.f;
    m_isCursorShown = true;
}
<commit_msg>Increase speed of line break method<commit_after>#include "TextInputWidget.hpp"
#include <iostream>

gsf::TextInputWidget::TextInputWidget(float width, float height, sf::Font &font)
: ChildWidget{ width, height }
//, m_text{ "", font, 12, sf::Color::Black }
, m_text{ nullptr }
, m_cursor{ "|", font, 12 }
, m_scrollable{ nullptr }
, m_isFocused{ false }
, m_cursorPos{ 0 }
, m_lBreaksBefCur{ 0 }
, m_isCursorShown{ true }
, m_blinkFreq{ 0.8f }
, m_lastBlinkTime{ 0.f }
, m_minBreakCharCnt{ 0 }
{
    std::unique_ptr<TextWidget> text{
        std::make_unique<TextWidget>("", font, 12, sf::Color::Black) };
    std::unique_ptr<ScrollableWidget> scrollabe{
        std::make_unique<ScrollableWidget>(width, height) };
    m_scrollable = scrollabe.get();
    m_text = text.get();
    scrollabe->setBackgroundColor(sf::Color::Red);
    scrollabe->attachChild(std::move(text));
    //attachChild(std::move(text));
    attachChild(std::move(scrollabe));
    m_cursor.setFillColor(sf::Color::Black);

    //m_text.setFont(font);
    //m_text.setCharacterSize(12);
    //m_text.setTextColor(sf::Color::Black);
    //m_text.setOrigin(0.f, 0.f);
    //m_text.setPosition(0.f, 0.f);
    //m_scrollableWidget.attachChild();
}

void gsf::TextInputWidget::setText(const std::string &text)
{
   m_text->setText(text);
}

std::string gsf::TextInputWidget::getText() const
{
   return m_text->getText().toAnsiString();
}

void gsf::TextInputWidget::setCharacterSize(const unsigned int size)
{
   m_text->setCharacterSize(size);
}

unsigned int gsf::TextInputWidget::getCharacterSize() const
{
   return m_text->getCharacterSize();
}

void gsf::TextInputWidget::setTextColor(const sf::Color color)
{
   m_text->setTextColor(color);
}

sf::Color gsf::TextInputWidget::getTextColor() const
{
   return m_text->getTextColor();
}

bool gsf::TextInputWidget::isFocused() const
{
    return m_isFocused;
}

void gsf::TextInputWidget::setIsVerticalScrollEnabled(bool isEnabled)
{
    m_scrollable->setIsVerticalScrollEnabled(isEnabled);
}

bool gsf::TextInputWidget::isVerticalScrollEnabled() const
{
    return m_scrollable->isVerticalScrollEnabled();
}

void gsf::TextInputWidget::setIsHorizontalScrollEnabled(bool isEnabled)
{
    m_scrollable->setIsHorizontalScrollEnabled(isEnabled);
}

bool gsf::TextInputWidget::isHorizontalScrollEnabled() const
{
    return m_scrollable->isHorizontalScrollEnabled();
}

void gsf::TextInputWidget::drawCurrent(sf::RenderTarget &target,
        sf::RenderStates states) const
{

}

void gsf::TextInputWidget::drawCurrentAfterChildren(sf::RenderTarget &target,
                    sf::RenderStates states) const
{
    // Draw cursor after children, so that children are not drawn over cursor
    if (m_isCursorShown)
    {
        target.draw(m_cursor, states);
    }
}

void gsf::TextInputWidget::updateCurrent(float dt)
{
    // Update cursor stuff
    m_lastBlinkTime += dt;
    if (m_lastBlinkTime >= m_blinkFreq)
    {
        m_isCursorShown = !m_isCursorShown;
        m_lastBlinkTime = 0.f;
    }
    //std::wstring text{ m_currentText };
    //std::wstring text{ m_shownText };
    //m_text->setText(text);
}

bool gsf::TextInputWidget::handleEventCurrent(sf::Event &event)
{
    //bool handled{ ChildWidget::handleEvent(event) };/*||
      //  m_scrollable->handleEventWidget(event) };*/
    // Check if actual Widget is focused
    if (event.type == sf::Event::MouseButtonPressed)
    {
        sf::Vector2f mousePos{ (float) event.mouseButton.x,
        (float) event.mouseButton.y };
        bool isMouseInShownArea{ getShownArea().contains(mousePos) };
        bool intersecting{ isIntersecting(mousePos) };
        if (isMouseInShownArea && intersecting)
        {
            m_isFocused = true;
        }
        else
        {
            m_isFocused = false;
        }
    }
    if (event.type == sf::Event::KeyPressed && m_isFocused)
    {
        switch (event.key.code)
        {
        case sf::Keyboard::Left:
            if (m_cursorPos > 0)
            {
                m_cursorPos--;
            }
            // when cursor is moved it should be drawn so we reset its status
            resetCursorStatus();
            adjustShownText();
            return true;
        case sf::Keyboard::Right:
            if (m_cursorPos < m_currentText.length())
            {
                m_cursorPos++;
            }
            resetCursorStatus();
            adjustShownText();
            m_cursor.setPosition
                (m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
            return true;
        default: break;
        }
    }
    // If Widget is focused and Text entered, handle entered text
    if (m_isFocused && event.type == sf::Event::TextEntered)
    {
        // To handle umlauts and other 'exotic' chars we use widestring
        // and wide char
        //std::wstring actualTxt{ m_text.getString().toWideString() };
        wchar_t c{ static_cast<wchar_t>(event.text.unicode) };
        std::cout << "Entered: " << c << std::endl;
        switch (c)
        {
        // Backspace
        case 8:
            if (m_currentText.length() > 0)
            {
                // Remove chars right of cursor when there are chars
                if (m_cursorPos > 0 && m_cursorPos < m_currentText.length())
                {
                    m_currentText.erase(m_cursorPos - 1, 1);
                    m_cursorPos--;
                }
                // When cursos is at the end of the text, p
                // place cursor behind char which we want to delete,
                else if (m_cursorPos == m_currentText.length())
                {
                    // Delete last char
                    m_currentText.pop_back();
                    m_cursorPos--;
                }
            }
            break;
        // Delete Pressed
        case 127:
            if (m_currentText.length() > 0 &&
                    m_cursorPos < m_currentText.length())
            {
                m_currentText.erase(m_cursorPos, 1);
            }
            break;
        // Enter key
        case 13: m_currentText.insert(m_cursorPos, L"\n"); m_cursorPos++; break;
        // Add char to text
        default: m_currentText.insert(m_cursorPos, std::wstring() + c); m_cursorPos++;
        }
        resetCursorStatus();
        m_shownText = m_currentText;
        m_text->setText(m_shownText);
        adjustShownText();
        m_cursor.setPosition(m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
        m_scrollable->recalculateScroll();
        m_scrollable->scrollToRight();
        m_scrollable->scrollToBottom();
        return true;
    }
    return false;
    //return handled;
}

void gsf::TextInputWidget::adjustShownText()
{
    /*
    if (m_scrollable->isHorizontalScrollEnabled() || m_currentText.size() == 0)
        return;

    m_lBreaksBefCur = 0;
    m_text->setText("");
    m_shownText = L"";
    // Add min cnt of chars we had in the past for a line break
    m_shownText = m_currentText.substr(0, m_minBreakCharCnt);
    // Start searching by the min cnt of chars we had in the past
    bool done{ false };
    unsigned int actualPos = m_minBreakCharCnt;
    do
    {
        m_text->setText(m_shownText);
        // Search expotenzial the pos where text dont fits anymore, and then
        // search binary in this area
        int i{ 1 };
        while(m_text->getWidth() < m_scrollable->getWidth())
        {
            wchar_t c{ m_currentText[actualPos + i - 1] };
            m_shownText += c;
        }
        // The search area is now between i / 2 and i -1
        // In this area we now search binary

        // Remove chars util the text fits in its parent
        while(m_text->getWidth() > m_scrollable->getWidth())
        {
            m_shownText.pop_back();
            actualPos--;
            m_text->setText(m_shownText);
            // The minimum has changed
            m_minBreakCharCnt--;
        };

    } while (!done);
    */

    // advance is the with of the glyph
    //float advance { m_text->getFont().getGlyph(c, m_text->getCharacterSize(),
    //    false).advance };
    if (!m_scrollable->isHorizontalScrollEnabled())
    {
        //std::cout << "POS: (" << m_text->findCharacterPos(1).x  << "|"
        //    << m_text->findCharacterPos(0).y << ")" << std::endl;
        m_lBreaksBefCur = 0;
        //m_text->setText("");
        std::wstring shownString{ L"" };
        unsigned int charCntLine{ 0 };
        float lineWidth{ 0.f };
        for (unsigned int i{ 0 }; i < m_currentText.size(); i++)
        {
            wchar_t c{ m_currentText[i] };
            float cWidth { m_text->getFont().getGlyph(c, m_text->getCharacterSize(),
                    false).advance };
            lineWidth += cWidth;
            // Text is out of widget so add a line break before the last added char
            if (lineWidth > m_scrollable->getWidth())
            {
                if (i < m_cursorPos)
                {
                    // We have to increase the "line breaks befor cursor" counter
                    // so we add the cursor later on the right position
                    m_lBreaksBefCur++;
                }
                //shownString += m_currentText.substr(i - charCntLine, charCntLine);
                shownString += L"\n";
                shownString += c;
                charCntLine = 1;
                lineWidth = cWidth;
            }
            else
            {
                charCntLine++;
                shownString += c;
            }
        }
        m_shownText = shownString;
        m_text->setText(m_shownText);
    }
    /*
    if (!m_scrollable->isHorizontalScrollEnabled())
    {
        //std::cout << "POS: (" << m_text->findCharacterPos(1).x  << "|"
        //    << m_text->findCharacterPos(0).y << ")" << std::endl;
        m_lBreaksBefCur = 0;
        m_text->setText("");
        m_shownText = L"";
        for (unsigned int i{ 0 }; i != m_currentText.size(); i++)
        {
            wchar_t c{ m_currentText[i] };
            m_shownText += c;
            m_text->setText(m_shownText);
            // Text is out of widget so add a line break before the last added char
            if (m_text->findCharacterPos(i).x > m_scrollable->getWidth())
            {
                if (i < m_cursorPos)
                {
                    // We have to increase the "line breaks befor cursor" counter
                    // so we add the cursor later on the right position
                    m_lBreaksBefCur++;
                }
                m_shownText.insert(m_shownText.size() - 2, L"\n");
            }
        }
        m_text->setText(m_shownText);
    }
    */
}

void gsf::TextInputWidget::resetCursorStatus()
{
    m_lastBlinkTime = 0.f;
    m_isCursorShown = true;
}
<|endoftext|>


<commit_before>#ifndef THREAD_H
#define THREAD_H

#include <pthread.h>

#include <boost/noncopyable.hpp>

template <class T>
class Thread : boost::noncopyable {
private:
  pthread_t t;
public:
  Thread(T const& to_run);
};

template <class T>
static void* _os_thread_bounce_fun(void *v) {
  /*
   * consider using a smart pointer instead of
   * this dorky try-catch.
   */
  T* t = (T*) v;
  try {
    (*t)();
    delete t;
  } catch (...) {
    delete t;
    throw;
  }
  return NULL;
}

template <class T>
Thread<T>::Thread(T const& to_run) {
  /*
   * to_run is just used as a template; the new thread is
   * given a copy, which that thread is responsible for
   * deleting.
   * Necessary since we just detach the thread and therefore
   * cannot easily determine when or if the thread is
   * already dead, and therefore if we should or shouldn't
   * delete to_run.
   */
  pthread_create(&t, NULL, _os_thread_bounce_fun<T>, new T(to_run));
  pthread_detach(t); // consider allowing to join
  /*alternatively: consider joining on destruction of Thread<T>*/
}

class Mutex : boost::noncopyable {
private:
  pthread_mutex_t m;
  // prevent user from using anything other than a Lock object
  void lock() { pthread_mutex_lock(&m); } // consider throwing if an error occurs
  bool trylock() { return pthread_mutex_trylock(&m) == 0; }
  void unlock() { pthread_mutex_unlock(&m); }
public:
  Mutex() { pthread_mutex_init(&m, NULL); }
  ~Mutex() { pthread_mutex_destroy(&m); }

  friend class Lock;
  friend class TryLock;
  friend class CondVar;
};

class Lock : boost::noncopyable {
private:
  Mutex* m;
public:
  explicit Lock(Mutex& nm) : m(&nm) { nm.lock(); }
  ~Lock() { m->unlock(); }

  friend class CondVar;
};

class TryLock : boost::noncopyable {
private:
  Mutex* m;
public:
  explicit TryLock(Mutex& nm) {
    m = (nm.trylock()) ? &nm : 0 ;
  }
  ~TryLock() { if(m) m->unlock(); }

  friend class CondVar;

  /*safe bool idiom*/
  typedef Mutex* (TryLock::*unspecified_bool_type);
  operator unspecified_bool_type() const {
    return m ? &TryLock::m : 0 ;
  }
};

class CondVar : boost::noncopyable {
private:
  pthread_cond_t cv;
public:
  CondVar() { pthread_cond_init(&cv, NULL); }
  ~CondVar() { pthread_cond_destroy(&cv); }
  // prevent user from not locking the mutex - get a
  // Lock object instead of a Mutex.
  void wait(Lock const& l) { pthread_cond_wait(&cv, &(l.m->m)); }
  // consider throwing on error

  void wait(TryLock const& l) { pthread_cond_wait(&cv, &(l.m->m)); }
  // should throw an error if trylock hasn't acquired

  // only error is an uninitialized condvar; since
  // constructing a valid object requires calling the
  // ctor, that is unlikely to happen.
  void signal(void) { pthread_cond_signal(&cv); }
  void broadcast(void) { pthread_cond_broadcast(&cv); }
};

#endif // THREAD_H
<commit_msg>os/thread.hpp: Changed to use smart pointer<commit_after>#ifndef THREAD_H
#define THREAD_H

#include <pthread.h>

#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>

template <class T>
class Thread : boost::noncopyable {
private:
  pthread_t t;
public:
  Thread(T const& to_run);
};

template <class T>
static void* _os_thread_bounce_fun(void *v) {
  boost::scoped_ptr<T> t((T*) v);
  (*t)();
  return NULL;
}

template <class T>
Thread<T>::Thread(T const& to_run) {
  /*
   * to_run is just used as a template; the new thread is
   * given a copy, which that thread is responsible for
   * deleting.
   * Necessary since we just detach the thread and therefore
   * cannot easily determine when or if the thread is
   * already dead, and therefore if we should or shouldn't
   * delete to_run.
   */
  pthread_create(&t, NULL, _os_thread_bounce_fun<T>, new T(to_run));
  pthread_detach(t); // consider allowing to join
  /*alternatively: consider joining on destruction of Thread<T>*/
}

class Mutex : boost::noncopyable {
private:
  pthread_mutex_t m;
  // prevent user from using anything other than a Lock object
  void lock() { pthread_mutex_lock(&m); } // consider throwing if an error occurs
  bool trylock() { return pthread_mutex_trylock(&m) == 0; }
  void unlock() { pthread_mutex_unlock(&m); }
public:
  Mutex() { pthread_mutex_init(&m, NULL); }
  ~Mutex() { pthread_mutex_destroy(&m); }

  friend class Lock;
  friend class TryLock;
  friend class CondVar;
};

class Lock : boost::noncopyable {
private:
  Mutex* m;
public:
  explicit Lock(Mutex& nm) : m(&nm) { nm.lock(); }
  ~Lock() { m->unlock(); }

  friend class CondVar;
};

class TryLock : boost::noncopyable {
private:
  Mutex* m;
public:
  explicit TryLock(Mutex& nm) {
    m = (nm.trylock()) ? &nm : 0 ;
  }
  ~TryLock() { if(m) m->unlock(); }

  friend class CondVar;

  /*safe bool idiom*/
  typedef Mutex* (TryLock::*unspecified_bool_type);
  operator unspecified_bool_type() const {
    return m ? &TryLock::m : 0 ;
  }
};

class CondVar : boost::noncopyable {
private:
  pthread_cond_t cv;
public:
  CondVar() { pthread_cond_init(&cv, NULL); }
  ~CondVar() { pthread_cond_destroy(&cv); }
  // prevent user from not locking the mutex - get a
  // Lock object instead of a Mutex.
  void wait(Lock const& l) { pthread_cond_wait(&cv, &(l.m->m)); }
  // consider throwing on error

  void wait(TryLock const& l) { pthread_cond_wait(&cv, &(l.m->m)); }
  // should throw an error if trylock hasn't acquired

  // only error is an uninitialized condvar; since
  // constructing a valid object requires calling the
  // ctor, that is unlikely to happen.
  void signal(void) { pthread_cond_signal(&cv); }
  void broadcast(void) { pthread_cond_broadcast(&cv); }
};

#endif // THREAD_H
<|endoftext|>


<commit_before>/*
    Copyright (c) 2008 Volker Krause <vkrause@kde.org>
    Copyright (c) 2010 Bertjan Broeksema <broeksema@kde.org>

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

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/
#include "agentprocessinstance.h"

#include "agenttype.h"
#include "processcontrol.h"

#include "libs/xdgbasedirs_p.h"
#include "shared/akdebug.h"

using namespace Akonadi;

AgentProcessInstance::AgentProcessInstance( AgentManager *manager )
  : AgentInstance( manager )
  , mController( 0 )
{ }

bool AgentProcessInstance::start( const AgentType &agentInfo )
{
  Q_ASSERT( !identifier().isEmpty() );
  if ( identifier().isEmpty() )
    return false;

  setAgentType( agentInfo.identifier );

  const QString executable = XdgBaseDirs::findExecutableFile( agentInfo.exec );
  if ( executable.isEmpty() ) {
    akError() << Q_FUNC_INFO << "Unable to find agent executable" << agentInfo.exec;
    return false;
  }

  mController = new Akonadi::ProcessControl( this );
  QStringList arguments;
  arguments << "--identifier" << identifier();
  mController->start( executable, arguments );
  return true;
}

void AgentProcessInstance::quit()
{
  mController->setCrashPolicy( Akonadi::ProcessControl::StopOnCrash );
  AgentInstance::quit();
}

void AgentProcessInstance::cleanup()
{
  mController->setCrashPolicy( Akonadi::ProcessControl::StopOnCrash );
  AgentInstance::cleanup();
}

void AgentProcessInstance::restartWhenIdle()
{
  if ( status() == 0 ) {
    mController->restartOnceWhenFinished();
    quit();
  }
}
<commit_msg>Actually, the akonadi_agent_launcher way of starting agents isn't *that* different from agents that have their own executable. So hijack the AgentProcessInstance class for launched agent plugins as well.<commit_after>/*
    Copyright (c) 2008 Volker Krause <vkrause@kde.org>
    Copyright (c) 2010 Bertjan Broeksema <broeksema@kde.org>

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

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/
#include "agentprocessinstance.h"

#include "agenttype.h"
#include "processcontrol.h"

#include "libs/xdgbasedirs_p.h"
#include "shared/akdebug.h"

using namespace Akonadi;

AgentProcessInstance::AgentProcessInstance( AgentManager *manager )
  : AgentInstance( manager )
  , mController( 0 )
{ }

bool AgentProcessInstance::start( const AgentType &agentInfo )
{
  Q_ASSERT( !identifier().isEmpty() );
  if ( identifier().isEmpty() )
    return false;

  setAgentType( agentInfo.identifier );

  const QString executable = XdgBaseDirs::findExecutableFile( agentInfo.exec );
  if ( executable.isEmpty() ) {
    akError() << Q_FUNC_INFO << "Unable to find agent executable" << agentInfo.exec;
    return false;
  }

  mController = new Akonadi::ProcessControl( this );
  Q_ASSERT( agentInfo.launchMethod == AgentType::Process ||
            agentInfo.launchMethod == AgentType::Launcher );

  if ( agentInfo.launchMethod == AgentType::Process ) {
    QStringList arguments;
    arguments << "--identifier" << identifier();
    mController->start( executable, arguments );
  } else {
    Q_ASSERT( agentInfo.launchMethod == AgentType::Launcher );
    QStringList arguments;
    arguments << executable << identifier();
    mController->start( QLatin1String( "akonadi_agent_launcher" ), arguments );
  }
  return true;
}

void AgentProcessInstance::quit()
{
  mController->setCrashPolicy( Akonadi::ProcessControl::StopOnCrash );
  AgentInstance::quit();
}

void AgentProcessInstance::cleanup()
{
  mController->setCrashPolicy( Akonadi::ProcessControl::StopOnCrash );
  AgentInstance::cleanup();
}

void AgentProcessInstance::restartWhenIdle()
{
  if ( status() == 0 ) {
    mController->restartOnceWhenFinished();
    quit();
  }
}
<|endoftext|>


<commit_before>/*
 * opencog/atoms/base/Handle.cc
 *
 * Copyright (C) 2002-2007 Novamente LLC
 * Copyright (C) 2013 Linas Vepstas <linas@linas.org>
 * All Rights Reserved
 *
 * Written by Thiago Maia <thiago@vettatech.com>
 *            Andre Senna <senna@vettalabs.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <climits>
#include <opencog/atoms/base/Handle.h>
#include <opencog/atoms/base/Atom.h>
#include <opencog/atomspace/AtomTable.h>

namespace opencog {

const Handle Handle::UNDEFINED;
const AtomPtr Handle::NULL_POINTER;

Handle::Handle(const UUID u)
{
	_ptr = do_res(u)._ptr;
}

UUID Handle::value(void) const
{
    const Atom* a = operator->();
    // The is link/node is a low-cost way of checking if the
    // pointer really is an atom pointer, and not just protoAtom,
    // which does not have a uuid.
    if (a and (a->isLink() or a->isNode())) return a->getUUID();
    return ULONG_MAX;
}

// ===================================================
// Atom comparison.

#if 0
bool Handle::atoms_eq(const AtomPtr& a, const AtomPtr& b)
{
    if (a == b) return true;
    if (NULL == a or NULL == b) return false;
    return *a == *b;
}
#endif

bool Handle::atoms_less(const Atom* pa, const Atom* pb)
{
    if (pa == pb) return false;
    if (NULL == pa) return true;
    if (NULL == pb) return false;

    const Atom* a(dynamic_cast<const Atom*>(pa));
    const Atom* b(dynamic_cast<const Atom*>(pb));
    UUID ua = a->getUUID();
    UUID ub = b->getUUID();
    if (INVALID_UUID != ua or INVALID_UUID != ub) return ua < ub;

    // If both UUID's are invalid, we still need to compare
    // the atoms somehow. The need to compare in some "reasonable"
    // way, so that OrderedHandleSet works correctly when it uses
    // the std::less<Handle> operator, which calls this function.
    // Performing an address-space comparison is all I can think
    // of...
    // if (*a == *b) return false; lets not do this cpu-time-waster...
    return a < b;
}

bool Handle::content_based_atoms_less(const Atom* a, const Atom* b)
{
    if (a == b) return false;
    if (nullptr == a) return true;
    if (nullptr == b) return false;

    // Otherwise we compare them by content. This is expensive but
    // useful when you really want a deterministic comparison.
    return a->operator<(*b);
}

// ===================================================
// Handle resolution stuff.

// Its a vector, not a set, because its priority ranked.
std::vector<const AtomTable*> Handle::_resolver;

void Handle::set_resolver(const AtomTable* tab)
{
    _resolver.push_back(tab);
}

void Handle::clear_resolver(const AtomTable* tab)
{
    auto it = std::find(_resolver.begin(), _resolver.end(), tab);
    if (it != _resolver.end())
        _resolver.erase(it);
}

// Search several atomspaces, in order.  First one to come up with
// the atom wins.  Seems to work, for now.
inline Handle Handle::do_res(UUID uuid)
{
    if (INVALID_UUID == uuid) return Handle();
    for (const AtomTable* at : _resolver) {
        Handle h(at->getHandle(uuid));
        if (NULL != h) return h;
    }
    return Handle();
}

std::string h_to_string(const Handle& h)
{
	if ((AtomPtr)h == nullptr)
		return "nullatom\n";
	else
		return h->toString();
}
std::string hp_to_string(const HandlePair& hp)
{
	std::stringstream ss;
	ss << "first:" << std::endl << h_to_string(hp.first);
	ss << "second:" << std::endl << h_to_string(hp.second);
	return ss.str();
}
std::string hs_to_string(const HandleSeq& hs)
{
	std::stringstream ss; std::operator<<(ss, hs); return ss.str();
}
std::string ohs_to_string(const OrderedHandleSet& ohs)
{
	std::stringstream ss; std::operator<<(ss, ohs); return ss.str();
}
std::string uhs_to_string(const UnorderedHandleSet& uhs)
{
	std::stringstream ss; std::operator<<(ss, uhs); return ss.str();
}
std::string hmap_to_string(const HandleMap& hmap)
{
	std::stringstream ss;
	ss << "size = " << hmap.size() << std::endl;
	int i = 0;
	for (const auto& p : hmap) {
		ss << "key[" << i << "]:" << std::endl << h_to_string(p.first)
		   << "value[" << i << "]:" << std::endl << h_to_string(p.second);
		i++;
	}
	return ss.str();
}
std::string hmultimap_to_string(const HandleMultimap& hmultimap)
{
	std::stringstream ss;
	ss << "size = " << hmultimap.size() << std::endl;
	int i = 0;
	for (const auto& p : hmultimap) {
		ss << "key[" << i << "]:" << std::endl << h_to_string(p.first)
		   << "value[" << i << "]:" << std::endl;
		for (const auto s : p.second)
			ss << h_to_string(s);
		i++;
	}
	return ss.str();
}
std::string hmaps_to_string(const HandleMapSeq& hms)
{
	std::stringstream ss;
	ss << "size = " << hms.size() << std::endl;
	for (unsigned i = 0; i < hms.size(); i++)
		ss << "--- map[" << i << "] ---" << std::endl
		   << hmap_to_string(hms[i]);
	return ss.str();
}
std::string hmapset_to_string(const HandleMapSet& hms)
{
	std::stringstream ss;
	ss << "size = " << hms.size() << std::endl;
	unsigned i = 0;
	for (const HandleMap& hm : hms) {
		ss << "--- map[" << i << "] ---" << std::endl
		   << hmap_to_string(hm);
		++i;
	}
	return ss.str();
}
std::string hps_to_string(const HandlePairSeq& hps)
{
	std::stringstream ss;
	ss << "size = " << hps.size() << std::endl;
	size_t i = 0;
	for (const std::pair<Handle, Handle>& hp : hps) {
		ss << "atom.first[" << i << "]:" << std::endl << h_to_string(hp.first);
		ss << "atom.second[" << i << "]:" << std::endl << h_to_string(hp.second);
		i++;
	}
	return ss.str();
}
std::string atomtype_to_string(Type type)
{
	std::stringstream ss;
	ss << classserver().getTypeName(type) << std::endl;
	return ss.str();
}
std::string aptr_to_string(const AtomPtr& aptr)
{
	return h_to_string(aptr->getHandle());
}
std::string lptr_to_string(const LinkPtr& lptr)
{
	return h_to_string(lptr->getHandle());
}

std::string oc_to_string(const Handle& h)
{
	return h_to_string(h);
}
std::string oc_to_string(const HandlePair& hp)
{
	return hp_to_string(hp);
}
std::string oc_to_string(const HandleSeq& hs)
{
	return hs_to_string(hs);
}
std::string oc_to_string(const OrderedHandleSet& ohs)
{
	return ohs_to_string(ohs);
}
std::string oc_to_string(const UnorderedHandleSet& uhs)
{
	return uhs_to_string(uhs);
}
std::string oc_to_string(const HandleMap& hm)
{
	return hmap_to_string(hm);
}
std::string oc_to_string(const HandleMultimap& hmm)
{
	return hmultimap_to_string(hmm);
}
std::string oc_to_string(const HandleMapSeq& hms)
{
	return hmaps_to_string(hms);
}
std::string oc_to_string(const HandleMapSet& hms)
{
	return hmapset_to_string(hms);
}
std::string oc_to_string(const HandlePairSeq& hps)
{
	return hps_to_string(hps);
}
std::string oc_to_string(Type type)
{
	return atomtype_to_string(type);
}
std::string oc_to_string(const AtomPtr& aptr)
{
	return aptr_to_string(aptr);
}
std::string oc_to_string(const LinkPtr& lptr)
{
	return lptr_to_string(lptr);
}

} // ~namespace opencog

namespace std {

// Hack around the lack template use in Handle.h due to circular dependencies
#define GEN_HANDLE_CONTAINER_OSTREAM_OPERATOR(T) \
ostream& operator<<(ostream& out, const T& hs) { \
	out << "size = " << hs.size() << endl; \
	size_t i = 0; \
	for (const opencog::Handle& h : hs) { \
		out << "atom[" << i << "]:" << endl << h_to_string(h); \
		i++; \
	} \
	return out; \
}
GEN_HANDLE_CONTAINER_OSTREAM_OPERATOR(opencog::HandleSeq)
GEN_HANDLE_CONTAINER_OSTREAM_OPERATOR(opencog::OrderedHandleSet)
GEN_HANDLE_CONTAINER_OSTREAM_OPERATOR(opencog::UnorderedHandleSet)

} // ~namespace std
<commit_msg>Clarifying remark for all the gunk in this file.<commit_after>/*
 * opencog/atoms/base/Handle.cc
 *
 * Copyright (C) 2002-2007 Novamente LLC
 * Copyright (C) 2013 Linas Vepstas <linas@linas.org>
 * All Rights Reserved
 *
 * Written by Thiago Maia <thiago@vettatech.com>
 *            Andre Senna <senna@vettalabs.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <climits>
#include <opencog/atoms/base/Handle.h>
#include <opencog/atoms/base/Atom.h>
#include <opencog/atomspace/AtomTable.h>

namespace opencog {

const Handle Handle::UNDEFINED;
const AtomPtr Handle::NULL_POINTER;

Handle::Handle(const UUID u)
{
	_ptr = do_res(u)._ptr;
}

UUID Handle::value(void) const
{
    const Atom* a = operator->();
    // The is link/node is a low-cost way of checking if the
    // pointer really is an atom pointer, and not just protoAtom,
    // which does not have a uuid.
    if (a and (a->isLink() or a->isNode())) return a->getUUID();
    return ULONG_MAX;
}

// ===================================================
// Atom comparison.

#if 0
bool Handle::atoms_eq(const AtomPtr& a, const AtomPtr& b)
{
    if (a == b) return true;
    if (NULL == a or NULL == b) return false;
    return *a == *b;
}
#endif

bool Handle::atoms_less(const Atom* pa, const Atom* pb)
{
    if (pa == pb) return false;
    if (NULL == pa) return true;
    if (NULL == pb) return false;

    const Atom* a(dynamic_cast<const Atom*>(pa));
    const Atom* b(dynamic_cast<const Atom*>(pb));
    UUID ua = a->getUUID();
    UUID ub = b->getUUID();
    if (INVALID_UUID != ua or INVALID_UUID != ub) return ua < ub;

    // If both UUID's are invalid, we still need to compare
    // the atoms somehow. The need to compare in some "reasonable"
    // way, so that OrderedHandleSet works correctly when it uses
    // the std::less<Handle> operator, which calls this function.
    // Performing an address-space comparison is all I can think
    // of...
    // if (*a == *b) return false; lets not do this cpu-time-waster...
    return a < b;
}

bool Handle::content_based_atoms_less(const Atom* a, const Atom* b)
{
    if (a == b) return false;
    if (nullptr == a) return true;
    if (nullptr == b) return false;

    // Otherwise we compare them by content. This is expensive but
    // useful when you really want a deterministic comparison.
    return a->operator<(*b);
}

// ===================================================
// Handle resolution stuff.

// Its a vector, not a set, because its priority ranked.
std::vector<const AtomTable*> Handle::_resolver;

void Handle::set_resolver(const AtomTable* tab)
{
    _resolver.push_back(tab);
}

void Handle::clear_resolver(const AtomTable* tab)
{
    auto it = std::find(_resolver.begin(), _resolver.end(), tab);
    if (it != _resolver.end())
        _resolver.erase(it);
}

// Search several atomspaces, in order.  First one to come up with
// the atom wins.  Seems to work, for now.
inline Handle Handle::do_res(UUID uuid)
{
    if (INVALID_UUID == uuid) return Handle();
    for (const AtomTable* at : _resolver) {
        Handle h(at->getHandle(uuid));
        if (NULL != h) return h;
    }
    return Handle();
}

// The rest of this file is devoted to printing utilities used only
// during GDB debugging.  Thus, you won't find these anywhere in the
// code base.
std::string h_to_string(const Handle& h)
{
	if ((AtomPtr)h == nullptr)
		return "nullatom\n";
	else
		return h->toString();
}
std::string hp_to_string(const HandlePair& hp)
{
	std::stringstream ss;
	ss << "first:" << std::endl << h_to_string(hp.first);
	ss << "second:" << std::endl << h_to_string(hp.second);
	return ss.str();
}
std::string hs_to_string(const HandleSeq& hs)
{
	std::stringstream ss; std::operator<<(ss, hs); return ss.str();
}
std::string ohs_to_string(const OrderedHandleSet& ohs)
{
	std::stringstream ss; std::operator<<(ss, ohs); return ss.str();
}
std::string uhs_to_string(const UnorderedHandleSet& uhs)
{
	std::stringstream ss; std::operator<<(ss, uhs); return ss.str();
}
std::string hmap_to_string(const HandleMap& hmap)
{
	std::stringstream ss;
	ss << "size = " << hmap.size() << std::endl;
	int i = 0;
	for (const auto& p : hmap) {
		ss << "key[" << i << "]:" << std::endl << h_to_string(p.first)
		   << "value[" << i << "]:" << std::endl << h_to_string(p.second);
		i++;
	}
	return ss.str();
}
std::string hmultimap_to_string(const HandleMultimap& hmultimap)
{
	std::stringstream ss;
	ss << "size = " << hmultimap.size() << std::endl;
	int i = 0;
	for (const auto& p : hmultimap) {
		ss << "key[" << i << "]:" << std::endl << h_to_string(p.first)
		   << "value[" << i << "]:" << std::endl;
		for (const auto s : p.second)
			ss << h_to_string(s);
		i++;
	}
	return ss.str();
}
std::string hmaps_to_string(const HandleMapSeq& hms)
{
	std::stringstream ss;
	ss << "size = " << hms.size() << std::endl;
	for (unsigned i = 0; i < hms.size(); i++)
		ss << "--- map[" << i << "] ---" << std::endl
		   << hmap_to_string(hms[i]);
	return ss.str();
}
std::string hmapset_to_string(const HandleMapSet& hms)
{
	std::stringstream ss;
	ss << "size = " << hms.size() << std::endl;
	unsigned i = 0;
	for (const HandleMap& hm : hms) {
		ss << "--- map[" << i << "] ---" << std::endl
		   << hmap_to_string(hm);
		++i;
	}
	return ss.str();
}
std::string hps_to_string(const HandlePairSeq& hps)
{
	std::stringstream ss;
	ss << "size = " << hps.size() << std::endl;
	size_t i = 0;
	for (const std::pair<Handle, Handle>& hp : hps) {
		ss << "atom.first[" << i << "]:" << std::endl << h_to_string(hp.first);
		ss << "atom.second[" << i << "]:" << std::endl << h_to_string(hp.second);
		i++;
	}
	return ss.str();
}
std::string atomtype_to_string(Type type)
{
	std::stringstream ss;
	ss << classserver().getTypeName(type) << std::endl;
	return ss.str();
}
std::string aptr_to_string(const AtomPtr& aptr)
{
	return h_to_string(aptr->getHandle());
}
std::string lptr_to_string(const LinkPtr& lptr)
{
	return h_to_string(lptr->getHandle());
}

std::string oc_to_string(const Handle& h)
{
	return h_to_string(h);
}
std::string oc_to_string(const HandlePair& hp)
{
	return hp_to_string(hp);
}
std::string oc_to_string(const HandleSeq& hs)
{
	return hs_to_string(hs);
}
std::string oc_to_string(const OrderedHandleSet& ohs)
{
	return ohs_to_string(ohs);
}
std::string oc_to_string(const UnorderedHandleSet& uhs)
{
	return uhs_to_string(uhs);
}
std::string oc_to_string(const HandleMap& hm)
{
	return hmap_to_string(hm);
}
std::string oc_to_string(const HandleMultimap& hmm)
{
	return hmultimap_to_string(hmm);
}
std::string oc_to_string(const HandleMapSeq& hms)
{
	return hmaps_to_string(hms);
}
std::string oc_to_string(const HandleMapSet& hms)
{
	return hmapset_to_string(hms);
}
std::string oc_to_string(const HandlePairSeq& hps)
{
	return hps_to_string(hps);
}
std::string oc_to_string(Type type)
{
	return atomtype_to_string(type);
}
std::string oc_to_string(const AtomPtr& aptr)
{
	return aptr_to_string(aptr);
}
std::string oc_to_string(const LinkPtr& lptr)
{
	return lptr_to_string(lptr);
}

} // ~namespace opencog

namespace std {

// Hack around the lack template use in Handle.h due to circular dependencies
#define GEN_HANDLE_CONTAINER_OSTREAM_OPERATOR(T) \
ostream& operator<<(ostream& out, const T& hs) { \
	out << "size = " << hs.size() << endl; \
	size_t i = 0; \
	for (const opencog::Handle& h : hs) { \
		out << "atom[" << i << "]:" << endl << h_to_string(h); \
		i++; \
	} \
	return out; \
}
GEN_HANDLE_CONTAINER_OSTREAM_OPERATOR(opencog::HandleSeq)
GEN_HANDLE_CONTAINER_OSTREAM_OPERATOR(opencog::OrderedHandleSet)
GEN_HANDLE_CONTAINER_OSTREAM_OPERATOR(opencog::UnorderedHandleSet)

} // ~namespace std
<|endoftext|>


<commit_before>//===--- AttributeList.cpp --------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the AttributeList class implementation
//
//===----------------------------------------------------------------------===//

#include "clang/Parse/AttributeList.h"
#include "clang/Basic/IdentifierTable.h"
using namespace clang;

AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
                             IdentifierInfo *pName, SourceLocation pLoc,
                             ActionBase::ExprTy **ExprList, unsigned numArgs,
                             AttributeList *n, bool declspec)
  : AttrName(aName), AttrLoc(aLoc), ParmName(pName), ParmLoc(pLoc),
    NumArgs(numArgs), Next(n), DeclspecAttribute(declspec) {

  if (numArgs == 0)
    Args = 0;
  else {
    Args = new ActionBase::ExprTy*[numArgs];
    memcpy(Args, ExprList, numArgs*sizeof(Args[0]));
  }
}

AttributeList::~AttributeList() {
  if (Args) {
    // FIXME: before we delete the vector, we need to make sure the Expr's
    // have been deleted. Since ActionBase::ExprTy is "void", we are dependent
    // on the actions module for actually freeing the memory. The specific
    // hooks are ActOnDeclarator, ActOnTypeName, ActOnParamDeclaratorType,
    // ParseField, ParseTag. Once these routines have freed the expression,
    // they should zero out the Args slot (to indicate the memory has been
    // freed). If any element of the vector is non-null, we should assert.
    delete [] Args;
  }
  delete Next;
}

AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
  const char *Str = Name->getName();
  unsigned Len = Name->getLength();

  // Normalize the attribute name, __foo__ becomes foo.
  if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
      Str[Len - 2] == '_' && Str[Len - 1] == '_') {
    Str += 2;
    Len -= 4;
  }

  // FIXME: Hand generating this is neither smart nor efficient.
  switch (Len) {
  case 4:
    if (!memcmp(Str, "weak", 4)) return AT_weak;
    if (!memcmp(Str, "pure", 4)) return AT_pure;
    if (!memcmp(Str, "mode", 4)) return AT_mode;
    if (!memcmp(Str, "used", 4)) return AT_used;
    break;
  case 5:
    if (!memcmp(Str, "alias", 5)) return AT_alias;
    if (!memcmp(Str, "const", 5)) return AT_const;
    break;
  case 6:
    if (!memcmp(Str, "packed", 6)) return AT_packed;
    if (!memcmp(Str, "malloc", 6)) return AT_malloc;
    if (!memcmp(Str, "format", 6)) return AT_format;
    if (!memcmp(Str, "unused", 6)) return AT_unused;
    if (!memcmp(Str, "blocks", 6)) return AT_blocks;
    break;
  case 7:
    if (!memcmp(Str, "aligned", 7)) return AT_aligned;
    if (!memcmp(Str, "cleanup", 7)) return AT_cleanup;
    if (!memcmp(Str, "nodebug", 7)) return AT_nodebug;
    if (!memcmp(Str, "nonnull", 7)) return AT_nonnull;
    if (!memcmp(Str, "nothrow", 7)) return AT_nothrow;
    if (!memcmp(Str, "objc_gc", 7)) return AT_objc_gc;
    if (!memcmp(Str, "regparm", 7)) return AT_regparm;
    if (!memcmp(Str, "section", 7)) return AT_section;
    if (!memcmp(Str, "stdcall", 7)) return AT_stdcall;
    break;
  case 8:
    if (!memcmp(Str, "annotate", 8)) return AT_annotate;
    if (!memcmp(Str, "noreturn", 8)) return AT_noreturn;
    if (!memcmp(Str, "noinline", 8)) return AT_noinline;
    if (!memcmp(Str, "fastcall", 8)) return AT_fastcall;
    if (!memcmp(Str, "iboutlet", 8)) return AT_IBOutlet;
    if (!memcmp(Str, "sentinel", 8)) return AT_sentinel;
    if (!memcmp(Str, "NSObject", 8)) return AT_nsobject;
    break;
  case 9:
    if (!memcmp(Str, "dllimport", 9)) return AT_dllimport;
    if (!memcmp(Str, "dllexport", 9)) return AT_dllexport;
    if (!memcmp(Str, "may_alias", 9)) return IgnoredAttribute; // FIXME: TBAA
    break;
  case 10:
    if (!memcmp(Str, "deprecated", 10)) return AT_deprecated;
    if (!memcmp(Str, "visibility", 10)) return AT_visibility;
    if (!memcmp(Str, "destructor", 10)) return AT_destructor;
    if (!memcmp(Str, "format_arg", 10)) return AT_format_arg;
    if (!memcmp(Str, "gnu_inline", 10)) return AT_gnu_inline;
    break;
  case 11:
    if (!memcmp(Str, "weak_import", 11)) return AT_weak_import;
    if (!memcmp(Str, "vector_size", 11)) return AT_vector_size;
    if (!memcmp(Str, "constructor", 11)) return AT_constructor;
    if (!memcmp(Str, "unavailable", 11)) return AT_unavailable;
    break;
  case 12:
    if (!memcmp(Str, "overloadable", 12)) return AT_overloadable;
    break;
  case 13:
    if (!memcmp(Str, "address_space", 13)) return AT_address_space;
    if (!memcmp(Str, "always_inline", 13)) return AT_always_inline;
    if (!memcmp(Str, "vec_type_hint", 13)) return IgnoredAttribute;
    break;
  case 14:
    if (!memcmp(Str, "objc_exception", 14)) return AT_objc_exception;
    break;
  case 15:
    if (!memcmp(Str, "ext_vector_type", 15)) return AT_ext_vector_type;
    break;
  case 17:
    if (!memcmp(Str, "transparent_union", 17)) return AT_transparent_union;
    if (!memcmp(Str, "analyzer_noreturn", 17)) return AT_analyzer_noreturn;
    break;
  case 18:
    if (!memcmp(Str, "warn_unused_result", 18)) return AT_warn_unused_result;
    break;
  case 19:
    if (!memcmp(Str, "ns_returns_retained", 19)) return AT_ns_returns_retained;
    if (!memcmp(Str, "cf_returns_retained", 19)) return AT_cf_returns_retained;
    break;
  case 20:
    if (!memcmp(Str, "reqd_work_group_size", 20)) return AT_reqd_wg_size;
  case 22:
    if (!memcmp(Str, "no_instrument_function", 22))
      return AT_no_instrument_function;
    break;
  }
  return UnknownAttribute;
}
<commit_msg>Rewrite AttributeList::getKind to use StringRef API.<commit_after>//===--- AttributeList.cpp --------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the AttributeList class implementation
//
//===----------------------------------------------------------------------===//

#include "clang/Parse/AttributeList.h"
#include "clang/Basic/IdentifierTable.h"
using namespace clang;

AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
                             IdentifierInfo *pName, SourceLocation pLoc,
                             ActionBase::ExprTy **ExprList, unsigned numArgs,
                             AttributeList *n, bool declspec)
  : AttrName(aName), AttrLoc(aLoc), ParmName(pName), ParmLoc(pLoc),
    NumArgs(numArgs), Next(n), DeclspecAttribute(declspec) {

  if (numArgs == 0)
    Args = 0;
  else {
    Args = new ActionBase::ExprTy*[numArgs];
    memcpy(Args, ExprList, numArgs*sizeof(Args[0]));
  }
}

AttributeList::~AttributeList() {
  if (Args) {
    // FIXME: before we delete the vector, we need to make sure the Expr's
    // have been deleted. Since ActionBase::ExprTy is "void", we are dependent
    // on the actions module for actually freeing the memory. The specific
    // hooks are ActOnDeclarator, ActOnTypeName, ActOnParamDeclaratorType,
    // ParseField, ParseTag. Once these routines have freed the expression,
    // they should zero out the Args slot (to indicate the memory has been
    // freed). If any element of the vector is non-null, we should assert.
    delete [] Args;
  }
  delete Next;
}

AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
  llvm::StringRef AttrName = Name->getNameStr();

  // Normalize the attribute name, __foo__ becomes foo.
  if (AttrName.startswith("__") && AttrName.endswith("__"))
    AttrName = AttrName.substr(2, AttrName.size() - 4);

  // FIXME: Hand generating this is neither smart nor efficient.
  const char *Str = AttrName.data();
  switch (AttrName.size()) {
  case 4:
    if (!memcmp(Str, "weak", 4)) return AT_weak;
    if (!memcmp(Str, "pure", 4)) return AT_pure;
    if (!memcmp(Str, "mode", 4)) return AT_mode;
    if (!memcmp(Str, "used", 4)) return AT_used;
    break;
  case 5:
    if (!memcmp(Str, "alias", 5)) return AT_alias;
    if (!memcmp(Str, "const", 5)) return AT_const;
    break;
  case 6:
    if (!memcmp(Str, "packed", 6)) return AT_packed;
    if (!memcmp(Str, "malloc", 6)) return AT_malloc;
    if (!memcmp(Str, "format", 6)) return AT_format;
    if (!memcmp(Str, "unused", 6)) return AT_unused;
    if (!memcmp(Str, "blocks", 6)) return AT_blocks;
    break;
  case 7:
    if (!memcmp(Str, "aligned", 7)) return AT_aligned;
    if (!memcmp(Str, "cleanup", 7)) return AT_cleanup;
    if (!memcmp(Str, "nodebug", 7)) return AT_nodebug;
    if (!memcmp(Str, "nonnull", 7)) return AT_nonnull;
    if (!memcmp(Str, "nothrow", 7)) return AT_nothrow;
    if (!memcmp(Str, "objc_gc", 7)) return AT_objc_gc;
    if (!memcmp(Str, "regparm", 7)) return AT_regparm;
    if (!memcmp(Str, "section", 7)) return AT_section;
    if (!memcmp(Str, "stdcall", 7)) return AT_stdcall;
    break;
  case 8:
    if (!memcmp(Str, "annotate", 8)) return AT_annotate;
    if (!memcmp(Str, "noreturn", 8)) return AT_noreturn;
    if (!memcmp(Str, "noinline", 8)) return AT_noinline;
    if (!memcmp(Str, "fastcall", 8)) return AT_fastcall;
    if (!memcmp(Str, "iboutlet", 8)) return AT_IBOutlet;
    if (!memcmp(Str, "sentinel", 8)) return AT_sentinel;
    if (!memcmp(Str, "NSObject", 8)) return AT_nsobject;
    break;
  case 9:
    if (!memcmp(Str, "dllimport", 9)) return AT_dllimport;
    if (!memcmp(Str, "dllexport", 9)) return AT_dllexport;
    if (!memcmp(Str, "may_alias", 9)) return IgnoredAttribute; // FIXME: TBAA
    break;
  case 10:
    if (!memcmp(Str, "deprecated", 10)) return AT_deprecated;
    if (!memcmp(Str, "visibility", 10)) return AT_visibility;
    if (!memcmp(Str, "destructor", 10)) return AT_destructor;
    if (!memcmp(Str, "format_arg", 10)) return AT_format_arg;
    if (!memcmp(Str, "gnu_inline", 10)) return AT_gnu_inline;
    break;
  case 11:
    if (!memcmp(Str, "weak_import", 11)) return AT_weak_import;
    if (!memcmp(Str, "vector_size", 11)) return AT_vector_size;
    if (!memcmp(Str, "constructor", 11)) return AT_constructor;
    if (!memcmp(Str, "unavailable", 11)) return AT_unavailable;
    break;
  case 12:
    if (!memcmp(Str, "overloadable", 12)) return AT_overloadable;
    break;
  case 13:
    if (!memcmp(Str, "address_space", 13)) return AT_address_space;
    if (!memcmp(Str, "always_inline", 13)) return AT_always_inline;
    if (!memcmp(Str, "vec_type_hint", 13)) return IgnoredAttribute;
    break;
  case 14:
    if (!memcmp(Str, "objc_exception", 14)) return AT_objc_exception;
    break;
  case 15:
    if (!memcmp(Str, "ext_vector_type", 15)) return AT_ext_vector_type;
    break;
  case 17:
    if (!memcmp(Str, "transparent_union", 17)) return AT_transparent_union;
    if (!memcmp(Str, "analyzer_noreturn", 17)) return AT_analyzer_noreturn;
    break;
  case 18:
    if (!memcmp(Str, "warn_unused_result", 18)) return AT_warn_unused_result;
    break;
  case 19:
    if (!memcmp(Str, "ns_returns_retained", 19)) return AT_ns_returns_retained;
    if (!memcmp(Str, "cf_returns_retained", 19)) return AT_cf_returns_retained;
    break;
  case 20:
    if (!memcmp(Str, "reqd_work_group_size", 20)) return AT_reqd_wg_size;
  case 22:
    if (!memcmp(Str, "no_instrument_function", 22))
      return AT_no_instrument_function;
    break;
  }
  return UnknownAttribute;
}
<|endoftext|>


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

#include <cstdio>
#include <cstring>
#include <string>
#include "debug_info.h"

namespace amx_profiler {

DebugInfo::DebugInfo()
 : amxdbg_(0)
{
}

DebugInfo::DebugInfo(const AMX_DBG *amxdbg)
 : amxdbg_(new AMX_DBG)
{
  std::memcpy(amxdbg_, amxdbg, sizeof(AMX_DBG));
}

DebugInfo::DebugInfo(const std::string &filename)
 : amxdbg_(0)
{
  Load(filename);
}

void DebugInfo::Load(const std::string &filename) {
  std::FILE* fp = std::fopen(filename.c_str(), "rb");
  if (fp != 0) {
    amxdbg_ = new AMX_DBG;
    if (dbg_LoadInfo(amxdbg_, fp) != AMX_ERR_NONE)
      delete amxdbg_;
    fclose(fp);
  }
}

void DebugInfo::Unload() {
  if (amxdbg_ != 0) {
    dbg_FreeInfo(amxdbg_);
    delete amxdbg_;
  }
}

long DebugInfo::LookupLine(Address address) const {
  long line = 0;
  dbg_LookupLine(amxdbg_, address, &line);
  return line;
}

std::string DebugInfo::LookupFile(Address address) const {
  std::string result;
  const char *file;
  if (dbg_LookupFile(amxdbg_, address, &file) == AMX_ERR_NONE)
    result.assign(file);
  return result;
}

std::string DebugInfo::LookupFunction(Address address) const {
  std::string result;
  const char *function;
  if (dbg_LookupFunction(amxdbg_, address, &function) == AMX_ERR_NONE)
    result.assign(function);
  return result;
}

std::string DebugInfo::LookupFunctionExact(Address address) const {
  std::string result;
  const char *function;
  if (dbg_LookupFunctionExact(amxdbg_, address, &function) == AMX_ERR_NONE)
    result.assign(function);
  return result;
}

} // namespace amx_profiler

<commit_msg>Fix DebugInfo being left in invalid state when loading fails<commit_after>// Copyright (c) 2011-2013, Zeex
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include <cstdio>
#include <cstring>
#include <string>
#include "debug_info.h"

namespace amx_profiler {

DebugInfo::DebugInfo()
 : amxdbg_(0)
{
}

DebugInfo::DebugInfo(const AMX_DBG *amxdbg)
 : amxdbg_(new AMX_DBG)
{
  std::memcpy(amxdbg_, amxdbg, sizeof(AMX_DBG));
}

DebugInfo::DebugInfo(const std::string &filename)
 : amxdbg_(0)
{
  Load(filename);
}

void DebugInfo::Load(const std::string &filename) {
  std::FILE* fp = std::fopen(filename.c_str(), "rb");
  if (fp != 0) {
    AMX_DBG amxdbg;
    if (dbg_LoadInfo(&amxdbg, fp) == AMX_ERR_NONE) {
      amxdbg_ = new AMX_DBG(amxdbg);
    }
    fclose(fp);
  }
}

void DebugInfo::Unload() {
  if (amxdbg_ != 0) {
    dbg_FreeInfo(amxdbg_);
    delete amxdbg_;
  }
}

long DebugInfo::LookupLine(Address address) const {
  long line = 0;
  dbg_LookupLine(amxdbg_, address, &line);
  return line;
}

std::string DebugInfo::LookupFile(Address address) const {
  std::string result;
  const char *file;
  if (dbg_LookupFile(amxdbg_, address, &file) == AMX_ERR_NONE)
    result.assign(file);
  return result;
}

std::string DebugInfo::LookupFunction(Address address) const {
  std::string result;
  const char *function;
  if (dbg_LookupFunction(amxdbg_, address, &function) == AMX_ERR_NONE)
    result.assign(function);
  return result;
}

std::string DebugInfo::LookupFunctionExact(Address address) const {
  std::string result;
  const char *function;
  if (dbg_LookupFunctionExact(amxdbg_, address, &function) == AMX_ERR_NONE)
    result.assign(function);
  return result;
}

} // namespace amx_profiler

<|endoftext|>


<commit_before>/*
 *   Copyright 2012 Coherent Theory LLC
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as
 *   published by the Free Software Foundation; either version 2, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "assethandler.h"

#include <QDebug>
#include <QDir>
#include <QLibraryInfo>
#include <QPluginLoader>

#include "installjob.h"

namespace Bodega
{

class AssetHandler::Private
{
public:
    Private()
        : ops(0)
    {
    }

    AssetOperations *ops;
};

AssetHandler::AssetHandler(QObject *parent)
    : QObject(parent),
      d(new Private)
{
}

AssetHandler::~AssetHandler()
{
    delete d;
}

void AssetHandler::setOperations(AssetOperations *operations)
{
    d->ops = operations;
}

AssetOperations *AssetHandler::operations() const
{
    return d->ops;
}

QString AssetHandler::launchText() const
{
    return QString();
}

bool AssetHandler::isInstalled() const
{
    return false;
}

Bodega::InstallJob *AssetHandler::install(QNetworkReply *reply, Session *session)
{
    return new InstallJob(reply, session);
}

Bodega::UninstallJob *AssetHandler::uninstall(Session *session)
{
    //return new UninstallJob();
    return 0;
}

AssetHandler *AssetHandler::create(const QString &type, AssetOperations *parent)
{
    QString plugin;
    //FIXME: a better registration system is badly needed
    if (type == QLatin1String("application/epub+zip") ||
        type == QLatin1String("application/pdf")) {
        plugin = QLatin1String("epub");
    } else if (type == QLatin1String("application/x-plasma")) {
        plugin = QLatin1String("plasmoid");
    } else if (type == QLatin1String("application/x-desktop-wallpaper")) {
        plugin = QLatin1String("wallpaper");
    }

    AssetHandler * handler = 0;

    if (!plugin.isEmpty()) {
        QDir pluginsDir(QLibraryInfo::location(QLibraryInfo::PluginsPath) + QLatin1String("/bodegaassethandlers/"));
        //FIXME: the .so is non-portable. need some ifdef's here if this is to work on non-UNIX.
        //remind me why QPluginLoader doesn't do this when QLibrary does?
        const QString path = pluginsDir.absoluteFilePath(QLatin1String("lib") + plugin + QLatin1String("handlerplugin.so"));
        QPluginLoader pluginLoader(path);

        QObject *plugin = pluginLoader.instance();
        if (plugin) {
            handler = qobject_cast<Bodega::AssetHandler *>(plugin);
        } else {
            qWarning() << "Plugin load failed" << pluginLoader.errorString() << path;
        }

        if (!handler) {
            delete plugin;
        }
    }

    if (!handler) {
        handler = new AssetHandler;
    }

    handler->setParent(parent);
    handler->setOperations(parent);
    return handler;
}

void AssetHandler::launch()
{
}

} // namespace Bodega

#include "assethandler.moc"

<commit_msg>manage rpm mimetype<commit_after>/*
 *   Copyright 2012 Coherent Theory LLC
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as
 *   published by the Free Software Foundation; either version 2, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "assethandler.h"

#include <QDebug>
#include <QDir>
#include <QLibraryInfo>
#include <QPluginLoader>

#include "installjob.h"

namespace Bodega
{

class AssetHandler::Private
{
public:
    Private()
        : ops(0)
    {
    }

    AssetOperations *ops;
};

AssetHandler::AssetHandler(QObject *parent)
    : QObject(parent),
      d(new Private)
{
}

AssetHandler::~AssetHandler()
{
    delete d;
}

void AssetHandler::setOperations(AssetOperations *operations)
{
    d->ops = operations;
}

AssetOperations *AssetHandler::operations() const
{
    return d->ops;
}

QString AssetHandler::launchText() const
{
    return QString();
}

bool AssetHandler::isInstalled() const
{
    return false;
}

Bodega::InstallJob *AssetHandler::install(QNetworkReply *reply, Session *session)
{
    return new InstallJob(reply, session);
}

Bodega::UninstallJob *AssetHandler::uninstall(Session *session)
{
    //return new UninstallJob();
    return 0;
}

AssetHandler *AssetHandler::create(const QString &type, AssetOperations *parent)
{
    QString plugin;
    //FIXME: a better registration system is badly needed
    if (type == QLatin1String("application/epub+zip") ||
        type == QLatin1String("application/pdf")) {
        plugin = QLatin1String("epub");
    } else if (type == QLatin1String("application/x-plasma")) {
        plugin = QLatin1String("plasmoid");
    } else if (type == QLatin1String("application/x-desktop-wallpaper")) {
        plugin = QLatin1String("wallpaper");
    } else if (type == QLatin1String("application/x-rpm")) {
        plugin = QLatin1String("rpm");
    }

    AssetHandler * handler = 0;

    if (!plugin.isEmpty()) {
        QDir pluginsDir(QLibraryInfo::location(QLibraryInfo::PluginsPath) + QLatin1String("/bodegaassethandlers/"));
        //FIXME: the .so is non-portable. need some ifdef's here if this is to work on non-UNIX.
        //remind me why QPluginLoader doesn't do this when QLibrary does?
        const QString path = pluginsDir.absoluteFilePath(QLatin1String("lib") + plugin + QLatin1String("handlerplugin.so"));
        QPluginLoader pluginLoader(path);

        QObject *plugin = pluginLoader.instance();
        if (plugin) {
            handler = qobject_cast<Bodega::AssetHandler *>(plugin);
        } else {
            qWarning() << "Plugin load failed" << pluginLoader.errorString() << path;
        }

        if (!handler) {
            delete plugin;
        }
    }

    if (!handler) {
        handler = new AssetHandler;
    }

    handler->setParent(parent);
    handler->setOperations(parent);
    return handler;
}

void AssetHandler::launch()
{
}

} // namespace Bodega

#include "assethandler.moc"

<|endoftext|>


<commit_before>/* Copyright (C) 2003 MySQL AB

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

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

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include <NDBT.hpp>
#include <NDBT_Test.hpp>
#include <HugoTransactions.hpp>
#include <UtilTransactions.hpp>
#include <random.h>
#include <getarg.h>

struct Parameter {
  const char * name;
  unsigned value;
  unsigned min;
  unsigned max;
};

#define P_OPER    0
#define P_RANGE   1
#define P_ROWS    2
#define P_LOOPS   3
#define P_CREATE  4
#define P_LOAD    5

#define P_MAX 6

/**
 * operation
 * 0 - serial pk
 * 1 - batch pk
 * 2 - serial uniq
 * 3 - batch uniq
 * 4 - index eq
 * 5 - range scan
 * 6 - ordered range scan
 * 7 - interpreted scan
 */
static const char * g_ops[] = {
  "serial pk",
  "batch pk",
  "serial uniq index access",
  "batch uniq index access",
  "index eq-bound",
  "index range",
  "index ordered",
  "interpreted scan"
};

#define P_OP_TYPES 8
static Uint64 g_times[P_OP_TYPES];

static
Parameter
g_paramters[] = {
  { "operation",   0, 0, 6 }, // 0
  { "range",    1000, 1, ~0 },// 1 no of rows to read
  { "size",  1000000, 1, ~0 },// 2 rows in tables
  { "iterations",  3, 1, ~0 },// 3
  { "create_drop", 0, 0, 1 }, // 4
  { "data",        0, 0, 1 }  // 5
};

static Ndb* g_ndb = 0;
static const NdbDictionary::Table * g_tab;
static const NdbDictionary::Index * g_i_unique;
static const NdbDictionary::Index * g_i_ordered;
static char g_table[256];
static char g_unique[256];
static char g_ordered[256];
static char g_buffer[2*1024*1024];

int create_table();
int load_table();
int run_read();
int clear_table();
int drop_table();
void print_result();

int
main(int argc, const char** argv){
  int verbose = 1;
  int optind = 0;

  struct getargs args[1+P_MAX] = {
    { "verbose", 'v', arg_flag, &verbose, "Print verbose status", "verbose" }
  };
  const int num_args = 1 + P_MAX;
  for(int i = 0; i<P_MAX; i++){
    args[i+1].long_name = g_paramters[i].name;
    args[i+1].short_name = * g_paramters[i].name;
    args[i+1].type = arg_integer;
    args[i+1].value = &g_paramters[i].value;
    BaseString tmp;
    tmp.assfmt("min: %d max: %d", g_paramters[i].min, g_paramters[i].max);
    args[i+1].help = strdup(tmp.c_str());
    args[i+1].arg_help = 0;
  }

  if(getarg(args, num_args, argc, argv, &optind)) {
    arg_printusage(args, num_args, argv[0], "tabname1 tabname2 ...");
    return NDBT_WRONGARGS;
  }

  myRandom48Init(NdbTick_CurrentMillisecond());

  g_ndb = new Ndb("TEST_DB");
  if(g_ndb->init() != 0){
    g_err << "init() failed" << endl;
    goto error;
  }
  if(g_ndb->waitUntilReady() != 0){
    g_err << "Wait until ready failed" << endl;
    goto error;
  }
  for(int i = optind; i<argc; i++){
    const char * T = argv[i];
    g_info << "Testing " << T << endl;
    snprintf(g_table, sizeof(g_table), T);
    snprintf(g_ordered, sizeof(g_ordered), "IDX_O_%s", T);
    snprintf(g_unique, sizeof(g_unique), "IDX_U_%s", T);
    if(create_table())
      goto error;
    if(load_table())
      goto error;
    for(int l = 0; l<g_paramters[P_LOOPS].value; l++){
      for(int j = 0; j<P_OP_TYPES; j++){
	g_paramters[P_OPER].value = j;
	if(run_read())
	  goto error;
      }
    }
    print_result();
  }

  if(g_ndb) delete g_ndb;
  return NDBT_OK;
error:
  if(g_ndb) delete g_ndb;
  return NDBT_FAILED;
}

int
create_table(){
  NdbDictionary::Dictionary* dict = g_ndb->getDictionary();
  assert(dict);
  if(g_paramters[P_CREATE].value){
    const NdbDictionary::Table * pTab = NDBT_Tables::getTable(g_table);
    assert(pTab);
    NdbDictionary::Table copy = * pTab;
    copy.setLogging(false);
    if(dict->createTable(copy) != 0){
      g_err << "Failed to create table: " << g_table << endl;
      return -1;
    }

    NdbDictionary::Index x(g_ordered);
    x.setTable(g_table);
    x.setType(NdbDictionary::Index::OrderedIndex);
    x.setLogging(false);
    for (unsigned k = 0; k < copy.getNoOfColumns(); k++){
      if(copy.getColumn(k)->getPrimaryKey()){
	x.addColumn(copy.getColumn(k)->getName());
      }
    }

    if(dict->createIndex(x) != 0){
      g_err << "Failed to create index: " << endl;
      return -1;
    }

    x.setName(g_unique);
    x.setType(NdbDictionary::Index::UniqueHashIndex);
    if(dict->createIndex(x) != 0){
      g_err << "Failed to create index: " << endl;
      return -1;
    }
  }
  g_tab = dict->getTable(g_table);
  g_i_unique = dict->getIndex(g_unique, g_table);
  g_i_ordered = dict->getIndex(g_ordered, g_table);
  assert(g_tab);
  assert(g_i_unique);
  assert(g_i_ordered);
  return 0;
}

int
drop_table(){
  if(!g_paramters[P_CREATE].value)
    return 0;
  if(g_ndb->getDictionary()->dropTable(g_tab->getName()) != 0){
    g_err << "Failed to drop table: " << g_tab->getName() << endl;
    return -1;
  }
  g_tab = 0;
  return 0;
}

int
load_table(){
  if(!g_paramters[P_LOAD].value)
    return 0;

  int rows = g_paramters[P_ROWS].value;
  HugoTransactions hugoTrans(* g_tab);
  if (hugoTrans.loadTable(g_ndb, rows)){
    g_err.println("Failed to load %s with %d rows", g_tab->getName(), rows);
    return -1;
  }
  return 0;
}

int
clear_table(){
  if(!g_paramters[P_LOAD].value)
    return 0;
  int rows = g_paramters[P_ROWS].value;

  UtilTransactions utilTrans(* g_tab);
  if (utilTrans.clearTable(g_ndb,  rows) != 0){
    g_err.println("Failed to clear table %s", g_tab->getName());
    return -1;
  }
  return 0;
}

inline
void err(NdbError e){
  ndbout << e << endl;
}

int
run_read(){
  int iter = g_paramters[P_LOOPS].value;
  NDB_TICKS start1, stop;
  int sum_time= 0;

  const Uint32 rows = g_paramters[P_ROWS].value;
  const Uint32 range = g_paramters[P_RANGE].value;

  start1 = NdbTick_CurrentMillisecond();
  NdbConnection * pTrans = g_ndb->startTransaction();
  if(!pTrans){
    g_err << "Failed to start transaction" << endl;
    err(g_ndb->getNdbError());
    return -1;
  }

  NdbOperation * pOp;
  NdbScanOperation * pSp;
  NdbIndexOperation * pUp;
  NdbIndexScanOperation * pIp;
  NdbResultSet * rs = (NdbResultSet*)~0;

  Uint32 start_row = rand() % (rows - range);
  Uint32 stop_row = start_row + range;

  /**
   * 0 - serial pk
   * 1 - batch pk
   * 2 - serial uniq
   * 3 - batch uniq
   * 4 - index eq
   * 5 - range scan
   * 6 - interpreted scan
   */
  int check = 0;
  void* res = (void*)~0;
  const Uint32 pk = 0;
  Uint32 cnt = 0;
  for(; start_row < stop_row; start_row++){
    switch(g_paramters[P_OPER].value){
    case 0:
      pOp = pTrans->getNdbOperation(g_table);
      check = pOp->readTuple();
      check = pOp->equal(pk, start_row);
      break;
    case 1:
      for(; start_row<stop_row; start_row++){
	pOp = pTrans->getNdbOperation(g_table);
	check = pOp->readTuple();
	check = pOp->equal(pk, start_row);
	for(int j = 0; j<g_tab->getNoOfColumns(); j++){
	  res = pOp->getValue(j);
	  assert(res);
	}
      }
      break;
    case 2:
      pOp = pTrans->getNdbIndexOperation(g_unique, g_table);
      check = pOp->readTuple();
      check = pOp->equal(pk, start_row);
      break;
    case 3:
      for(; start_row<stop_row; start_row++){
	pOp = pTrans->getNdbIndexOperation(g_unique, g_table);
	check = pOp->readTuple();
	check = pOp->equal(pk, start_row);
	for(int j = 0; j<g_tab->getNoOfColumns(); j++){
	  res = pOp->getValue(j);
	  assert(res);
	}
      }
      break;
    case 4:
      pOp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
      rs = pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
      check = pIp->setBound(pk, NdbIndexScanOperation::BoundEQ, &start_row);
      break;
    case 5:
      pOp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
      rs = pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
      check = pIp->setBound(pk, NdbIndexScanOperation::BoundLE, &start_row);
      check = pIp->setBound(pk, NdbIndexScanOperation::BoundGT, &stop_row);
      start_row = stop_row;
      break;
    case 6:
      pOp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
      rs = pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0, true);
      check = pIp->setBound(pk, NdbIndexScanOperation::BoundLE, &start_row);
      check = pIp->setBound(pk, NdbIndexScanOperation::BoundGT, &stop_row);
      start_row = stop_row;
      break;
    case 7:
      pOp = pSp = pTrans->getNdbScanOperation(g_table);
      rs = pSp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
      NdbScanFilter filter(pOp) ;
      filter.begin(NdbScanFilter::AND);
      filter.ge(pk, start_row);
      filter.lt(pk, stop_row);
      filter.end();
      start_row = stop_row;
      break;
    }

    assert(res);
    if(check != 0){
      ndbout << pOp->getNdbError() << endl;
      ndbout << pTrans->getNdbError() << endl;
    }
    assert(check == 0);
    assert(rs);

    for(int j = 0; j<g_tab->getNoOfColumns(); j++){
      res = pOp->getValue(j);
      assert(res);
    }

    check = pTrans->execute(NoCommit);
    if(check != 0){
      ndbout << pTrans->getNdbError() << endl;
    }
    assert(check == 0);
    if(g_paramters[P_OPER].value >= 4){
      while((check = rs->nextResult(true)) == 0){
	cnt++;
      }

      if(check == -1){
	err(pTrans->getNdbError());
	return -1;
      }
      assert(check == 1);
      rs->close();
    }
  }
  assert(g_paramters[P_OPER].value < 4 || (cnt == range));

  pTrans->close();

  stop = NdbTick_CurrentMillisecond();
  g_times[g_paramters[P_OPER].value] += (stop - start1);
  return 0;
}

void
print_result(){
  for(int i = 0; i<P_OP_TYPES; i++){
    g_err.println("%s avg: %u us/row", g_ops[i],
		  (1000*g_times[i])/g_paramters[P_RANGE].value);
  }
}
<commit_msg>testReadPerf  Divide by loops aswell<commit_after>/* Copyright (C) 2003 MySQL AB

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

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

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include <NDBT.hpp>
#include <NDBT_Test.hpp>
#include <HugoTransactions.hpp>
#include <UtilTransactions.hpp>
#include <random.h>
#include <getarg.h>

struct Parameter {
  const char * name;
  unsigned value;
  unsigned min;
  unsigned max;
};

#define P_OPER    0
#define P_RANGE   1
#define P_ROWS    2
#define P_LOOPS   3
#define P_CREATE  4
#define P_LOAD    5

#define P_MAX 6

/**
 * operation
 * 0 - serial pk
 * 1 - batch pk
 * 2 - serial uniq
 * 3 - batch uniq
 * 4 - index eq
 * 5 - range scan
 * 6 - ordered range scan
 * 7 - interpreted scan
 */
static const char * g_ops[] = {
  "serial pk",
  "batch pk",
  "serial uniq index access",
  "batch uniq index access",
  "index eq-bound",
  "index range",
  "index ordered",
  "interpreted scan"
};

#define P_OP_TYPES 8
static Uint64 g_times[P_OP_TYPES];

static
Parameter
g_paramters[] = {
  { "operation",   0, 0, 6 }, // 0
  { "range",    1000, 1, ~0 },// 1 no of rows to read
  { "size",  1000000, 1, ~0 },// 2 rows in tables
  { "iterations",  3, 1, ~0 },// 3
  { "create_drop", 0, 0, 1 }, // 4
  { "data",        0, 0, 1 }  // 5
};

static Ndb* g_ndb = 0;
static const NdbDictionary::Table * g_tab;
static const NdbDictionary::Index * g_i_unique;
static const NdbDictionary::Index * g_i_ordered;
static char g_table[256];
static char g_unique[256];
static char g_ordered[256];
static char g_buffer[2*1024*1024];

int create_table();
int load_table();
int run_read();
int clear_table();
int drop_table();
void print_result();

int
main(int argc, const char** argv){
  int verbose = 1;
  int optind = 0;

  struct getargs args[1+P_MAX] = {
    { "verbose", 'v', arg_flag, &verbose, "Print verbose status", "verbose" }
  };
  const int num_args = 1 + P_MAX;
  for(int i = 0; i<P_MAX; i++){
    args[i+1].long_name = g_paramters[i].name;
    args[i+1].short_name = * g_paramters[i].name;
    args[i+1].type = arg_integer;
    args[i+1].value = &g_paramters[i].value;
    BaseString tmp;
    tmp.assfmt("min: %d max: %d", g_paramters[i].min, g_paramters[i].max);
    args[i+1].help = strdup(tmp.c_str());
    args[i+1].arg_help = 0;
  }

  if(getarg(args, num_args, argc, argv, &optind)) {
    arg_printusage(args, num_args, argv[0], "tabname1 tabname2 ...");
    return NDBT_WRONGARGS;
  }

  myRandom48Init(NdbTick_CurrentMillisecond());

  g_ndb = new Ndb("TEST_DB");
  if(g_ndb->init() != 0){
    g_err << "init() failed" << endl;
    goto error;
  }
  if(g_ndb->waitUntilReady() != 0){
    g_err << "Wait until ready failed" << endl;
    goto error;
  }
  for(int i = optind; i<argc; i++){
    const char * T = argv[i];
    g_info << "Testing " << T << endl;
    snprintf(g_table, sizeof(g_table), T);
    snprintf(g_ordered, sizeof(g_ordered), "IDX_O_%s", T);
    snprintf(g_unique, sizeof(g_unique), "IDX_U_%s", T);
    if(create_table())
      goto error;
    if(load_table())
      goto error;
    for(int l = 0; l<g_paramters[P_LOOPS].value; l++){
      for(int j = 0; j<P_OP_TYPES; j++){
	g_paramters[P_OPER].value = j;
	if(run_read())
	  goto error;
      }
    }
    print_result();
  }

  if(g_ndb) delete g_ndb;
  return NDBT_OK;
error:
  if(g_ndb) delete g_ndb;
  return NDBT_FAILED;
}

int
create_table(){
  NdbDictionary::Dictionary* dict = g_ndb->getDictionary();
  assert(dict);
  if(g_paramters[P_CREATE].value){
    const NdbDictionary::Table * pTab = NDBT_Tables::getTable(g_table);
    assert(pTab);
    NdbDictionary::Table copy = * pTab;
    copy.setLogging(false);
    if(dict->createTable(copy) != 0){
      g_err << "Failed to create table: " << g_table << endl;
      return -1;
    }

    NdbDictionary::Index x(g_ordered);
    x.setTable(g_table);
    x.setType(NdbDictionary::Index::OrderedIndex);
    x.setLogging(false);
    for (unsigned k = 0; k < copy.getNoOfColumns(); k++){
      if(copy.getColumn(k)->getPrimaryKey()){
	x.addColumn(copy.getColumn(k)->getName());
      }
    }

    if(dict->createIndex(x) != 0){
      g_err << "Failed to create index: " << endl;
      return -1;
    }

    x.setName(g_unique);
    x.setType(NdbDictionary::Index::UniqueHashIndex);
    if(dict->createIndex(x) != 0){
      g_err << "Failed to create index: " << endl;
      return -1;
    }
  }
  g_tab = dict->getTable(g_table);
  g_i_unique = dict->getIndex(g_unique, g_table);
  g_i_ordered = dict->getIndex(g_ordered, g_table);
  assert(g_tab);
  assert(g_i_unique);
  assert(g_i_ordered);
  return 0;
}

int
drop_table(){
  if(!g_paramters[P_CREATE].value)
    return 0;
  if(g_ndb->getDictionary()->dropTable(g_tab->getName()) != 0){
    g_err << "Failed to drop table: " << g_tab->getName() << endl;
    return -1;
  }
  g_tab = 0;
  return 0;
}

int
load_table(){
  if(!g_paramters[P_LOAD].value)
    return 0;

  int rows = g_paramters[P_ROWS].value;
  HugoTransactions hugoTrans(* g_tab);
  if (hugoTrans.loadTable(g_ndb, rows)){
    g_err.println("Failed to load %s with %d rows", g_tab->getName(), rows);
    return -1;
  }
  return 0;
}

int
clear_table(){
  if(!g_paramters[P_LOAD].value)
    return 0;
  int rows = g_paramters[P_ROWS].value;

  UtilTransactions utilTrans(* g_tab);
  if (utilTrans.clearTable(g_ndb,  rows) != 0){
    g_err.println("Failed to clear table %s", g_tab->getName());
    return -1;
  }
  return 0;
}

inline
void err(NdbError e){
  ndbout << e << endl;
}

int
run_read(){
  int iter = g_paramters[P_LOOPS].value;
  NDB_TICKS start1, stop;
  int sum_time= 0;

  const Uint32 rows = g_paramters[P_ROWS].value;
  const Uint32 range = g_paramters[P_RANGE].value;

  start1 = NdbTick_CurrentMillisecond();
  NdbConnection * pTrans = g_ndb->startTransaction();
  if(!pTrans){
    g_err << "Failed to start transaction" << endl;
    err(g_ndb->getNdbError());
    return -1;
  }

  NdbOperation * pOp;
  NdbScanOperation * pSp;
  NdbIndexOperation * pUp;
  NdbIndexScanOperation * pIp;
  NdbResultSet * rs = (NdbResultSet*)~0;

  Uint32 start_row = rand() % (rows - range);
  Uint32 stop_row = start_row + range;

  /**
   * 0 - serial pk
   * 1 - batch pk
   * 2 - serial uniq
   * 3 - batch uniq
   * 4 - index eq
   * 5 - range scan
   * 6 - interpreted scan
   */
  int check = 0;
  void* res = (void*)~0;
  const Uint32 pk = 0;
  Uint32 cnt = 0;
  for(; start_row < stop_row; start_row++){
    switch(g_paramters[P_OPER].value){
    case 0:
      pOp = pTrans->getNdbOperation(g_table);
      check = pOp->readTuple();
      check = pOp->equal(pk, start_row);
      break;
    case 1:
      for(; start_row<stop_row; start_row++){
	pOp = pTrans->getNdbOperation(g_table);
	check = pOp->readTuple();
	check = pOp->equal(pk, start_row);
	for(int j = 0; j<g_tab->getNoOfColumns(); j++){
	  res = pOp->getValue(j);
	  assert(res);
	}
      }
      break;
    case 2:
      pOp = pTrans->getNdbIndexOperation(g_unique, g_table);
      check = pOp->readTuple();
      check = pOp->equal(pk, start_row);
      break;
    case 3:
      for(; start_row<stop_row; start_row++){
	pOp = pTrans->getNdbIndexOperation(g_unique, g_table);
	check = pOp->readTuple();
	check = pOp->equal(pk, start_row);
	for(int j = 0; j<g_tab->getNoOfColumns(); j++){
	  res = pOp->getValue(j);
	  assert(res);
	}
      }
      break;
    case 4:
      pOp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
      rs = pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
      check = pIp->setBound(pk, NdbIndexScanOperation::BoundEQ, &start_row);
      break;
    case 5:
      pOp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
      rs = pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
      check = pIp->setBound(pk, NdbIndexScanOperation::BoundLE, &start_row);
      check = pIp->setBound(pk, NdbIndexScanOperation::BoundGT, &stop_row);
      start_row = stop_row;
      break;
    case 6:
      pOp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
      rs = pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0, true);
      check = pIp->setBound(pk, NdbIndexScanOperation::BoundLE, &start_row);
      check = pIp->setBound(pk, NdbIndexScanOperation::BoundGT, &stop_row);
      start_row = stop_row;
      break;
    case 7:
      pOp = pSp = pTrans->getNdbScanOperation(g_table);
      rs = pSp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
      NdbScanFilter filter(pOp) ;
      filter.begin(NdbScanFilter::AND);
      filter.ge(pk, start_row);
      filter.lt(pk, stop_row);
      filter.end();
      start_row = stop_row;
      break;
    }

    assert(res);
    if(check != 0){
      ndbout << pOp->getNdbError() << endl;
      ndbout << pTrans->getNdbError() << endl;
    }
    assert(check == 0);
    assert(rs);

    for(int j = 0; j<g_tab->getNoOfColumns(); j++){
      res = pOp->getValue(j);
      assert(res);
    }

    check = pTrans->execute(NoCommit);
    if(check != 0){
      ndbout << pTrans->getNdbError() << endl;
    }
    assert(check == 0);
    if(g_paramters[P_OPER].value >= 4){
      while((check = rs->nextResult(true)) == 0){
	cnt++;
      }

      if(check == -1){
	err(pTrans->getNdbError());
	return -1;
      }
      assert(check == 1);
      rs->close();
    }
  }
  assert(g_paramters[P_OPER].value < 4 || (cnt == range));

  pTrans->close();

  stop = NdbTick_CurrentMillisecond();
  g_times[g_paramters[P_OPER].value] += (stop - start1);
  return 0;
}

void
print_result(){
  for(int i = 0; i<P_OP_TYPES; i++){
    g_err.println("%s avg: %u us/row", g_ops[i],
		  (1000*g_times[i])/(g_paramters[P_RANGE].value*g_paramters[P_LOOPS].value));
  }
}
<|endoftext|>