<commit_before>#include"panelview.h"

#include<QString>
#include<QSize>
#include<QUrl>

#include<QGraphicsView>
#include<QGraphicsScene>
#include<QWidget>
#include<QDesktopWidget>

#include<QGLFramebufferObject>
#include<QPainter>

#include<QPaintEvent>
#include<QKeyEvent>
#include<QMouseEvent>
#include<QTabletEvent>

#include<QDeclarativeEngine>
#include<QDeclarativeContext>
#include<QDeclarativeView>
#include<QDeclarativeItem>

#include<QApplication>

PMonitor::PMonitor(void) : Dialog(false, false, false)
{
    const int width = qApp->desktop()->rect().width();
    const int height = qApp->desktop()->rect().height();

    setSceneRect(0, 0, width, height);
    setViewportUpdateMode(QGraphicsView::NoViewportUpdate);

    setAttribute(Qt::WA_NoSystemBackground);
    setCacheMode(QGraphicsView::CacheNone);
    setOptimizationFlags(
        QGraphicsView::DontSavePainterState |
        QGraphicsView::DontAdjustForAntialiasing);

    viewport()->setAttribute(Qt::WA_TranslucentBackground, false);
    scene()->setItemIndexMethod(QGraphicsScene::NoIndex);

    rootContext()->setContextProperty("screenWidth", width);
    rootContext()->setContextProperty("screenHeight", height);

    setSource(QUrl::fromLocalFile("/usr/share/meego-ux-panels/main.qml"));
}

PanelView::PanelView(void) : Dialog(false, false, true),
        QDeclarativeImageProvider(QDeclarativeImageProvider::Image)
{
    const int width = qApp->desktop()->rect().width();
    const int height = qApp->desktop()->rect().height();

    int j, k, total=1, cur_width, cur_height;
    QList<QObject *> kids;
    QDeclarativeItem *dec;
    QObject *child;

    r = new PMonitor();

    if(((child = r->rootObject()->findChild<QDeclarativeItem *>("appPage"))
         == NULL) |
       ((child =  child->findChild<QDeclarativeItem *>("PC")) == NULL) |
       ((child = child->findChild<QDeclarativeItem *>("PLV")) == NULL)) {
        qFatal("Upgrade your version of MeeGo-UX-Panels");
    }
    fwidth = child->property("contentWidth").toInt();
    r->rootObject()->setProperty("width", fwidth);
    r->rootObject()->setProperty("height", height);

    QObject::connect(r->scene(), SIGNAL(changed(const QList<QRectF>&)),
            this, SLOT(invalidate(const QList<QRectF>&)));

    setSceneRect(0, 0, width, height);

    const int p_width = fwidth /  NUM_C;
    const int p_height = height / NUM_R;
    for(j = 0; j < NUM_P; j++) {
        cache[j] = new QImage(p_width, p_height,
             QImage::Format_ARGB32_Premultiplied);
    }

    qobject_cast<QGLWidget *>(viewport())->makeCurrent();
    fbo = new QGLFramebufferObject(p_width, p_height,
             QGLFramebufferObject::CombinedDepthStencil);

    engine()->addImageProvider(QLatin1String("gen"), this);

    setSource(QUrl::fromLocalFile("/usr/share/meego-ux-daemon/real.qml"));
    rootObject()->setProperty("contentWidth", fwidth);
    rootObject()->setProperty("contentHeight", height);
    rootObject()->setProperty("width", width);
    rootObject()->setProperty("height", height);

    dec =  qobject_cast<QDeclarativeItem*>(rootObject());
    kids = dec->children();

    for(j = 0, cur_height =0; j < NUM_R; j++, cur_height += p_height) {
        for(k = 0, cur_width = 0; k < NUM_C; k++, cur_width += p_width) {
            kids.at(total)->setProperty("width", p_width);
            kids.at(total)->setProperty("height", p_height);
            kids.at(total)->setProperty("x", cur_width);
            kids.at(total)->setProperty("y", cur_height);

            QString source = QString(ISRC);
            source += QString::number(total-1);
            kids.at(total)->setProperty("source", source);
            total++;
        }
    }

    setOptimizationFlags(
        QGraphicsView::DontSavePainterState |
        QGraphicsView::DontAdjustForAntialiasing);

    setCacheMode(QGraphicsView::CacheBackground);
    scene()->setItemIndexMethod(QGraphicsScene::NoIndex);
    viewport()->setAttribute(Qt::WA_OpaquePaintEvent);

    create_bg();
}

PanelView::~PanelView(void)
{
    int i;

    for(i = 0; i < NUM_P; i++) {
        delete cache[i];
    }

    delete r;
    delete background;
    delete bg_window;

    delete fbo;
}

void PanelView::keyPressEvent(QKeyEvent *e)
{
    r->keyPressEvent(e);
}

void PanelView::keyReleaseEvent(QKeyEvent *e)
{
    r->keyReleaseEvent(e);
}

void PanelView::mouseDoubleClickEvent(QMouseEvent *e)
{
    r->mouseDoubleClickEvent(e);
}

void PanelView::mousePressEvent(QMouseEvent *e)
{
    QDeclarativeItem *ro;

    ro = qobject_cast<QDeclarativeItem *>(rootObject());
    QPoint np(e->x() + ro->property("contentX").toDouble(), e->y());
    QMouseEvent ne(e->type(), np, e->button(), e->buttons(), e->modifiers());

    bg_window->mousePressEvent(e);
    r->mousePressEvent(&ne);
    QDeclarativeView::mousePressEvent(e);
}

void PanelView::mouseReleaseEvent(QMouseEvent *e)
{
    bg_window->mouseReleaseEvent(e);
    r->mouseReleaseEvent(e);
    QDeclarativeView::mouseReleaseEvent(e);
}

void PanelView::tabletEvent(QTabletEvent *e)
{
    r->tabletEvent(e);
}

QImage PanelView::requestImage(const QString &id, QSize *size,
        const QSize &resize)
{
    Q_UNUSED(size);
    Q_UNUSED(resize);

    int i = id.toInt();

    while(i >= NUM_P) {
        i -= NUM_P;
    }

    return *cache[i];
}

static QRectF consolidate_width(const QList<QRectF> &region)
{
    qreal l,r, t, b;
    int i;

    l = region.at(0).x();
    r = region.at(0).x() + region.at(0).width();
    t = region.at(0).y();
    b = region.at(0).y() + region.at(0).height();

    for(i = 1; i < region.count(); i++) {
        const double _l = region.at(i).x();
        const double _r = region.at(i).x() + region.at(i).width();
        const double _t = region.at(i).y();
        const double _b = region.at(i).y() + region.at(i).height();
        if(_l < l) {
            l = _l;
        }
        if(_r> r) {
            r = _r;
        }
        if(_t < t) {
            t = _t;
        }
        if(_b > b) {
            b = _b;
        }
    }

    return QRectF(l, t, r -l, b - t);
}

void PanelView::invalidate(const QList<QRectF> &region)
{
    const int height = qApp->desktop()->rect().height();
    const int p_width = fwidth /  NUM_C;
    const int p_height = height / NUM_R;

    int i, j, c_width, c_height, total=0;

    if(region.count() > 0) {
        QRectF n = consolidate_width(region);
        for(i = 0, c_height =0; i < NUM_R; i++, c_height += p_height) {
            for(j =0, c_width=0; j < NUM_C; j++, c_width += p_width) {
                QRectF d(c_width, c_height , p_width, p_height);
                if(d.intersects(n)) {
                    draw_single(total);
                }
                total++;
            }
        }
    }
}

inline void PanelView::draw_single(int i)
{
    const int height = qApp->desktop()->rect().height();
    const int p_width = fwidth /  NUM_C;
    const int p_height = height / NUM_R;

    static const QDeclarativeItem *dec = qobject_cast<QDeclarativeItem *>
        (rootObject());
    static const QList<QObject *> kids = dec->children();

    int c, _r=0,k;
    QImage *old;
    QString src;
    QPainter p;

    c = i;
    while(c >= NUM_C) {
        _r++;
        c -= NUM_C;
    }

    qobject_cast<QGLWidget *>(viewport())->makeCurrent();
    p.begin(fbo);
        glClear(GL_COLOR_BUFFER_BIT);
        r->viewport()->render(&p, QPoint(), QRegion(
            p_width * c, p_height *_r,
            p_width, p_height));
    p.end();

    old = cache[i];
    cache[i] = new QImage(fbo->toImage());
    delete old;

    src = kids.at(i+1)->property("source").toString();
    k = src.right(src.size() - ISRC_LEN).toInt();
    src.truncate(ISRC_LEN);
    k += NUM_P;
    src += QString::number(k);
    kids.at(i+1)->setProperty("source", src);
}

void PanelView::create_bg(void)
{
    const int width = qApp->desktop()->rect().width();
    const int height = qApp->desktop()->rect().height();

    bg_window = new PMonitor();
    bg_window->setSource(QUrl::fromLocalFile(
        "/usr/share/meego-ux-daemon/background.qml"));
    background = new QImage(width, height,
         QImage::Format_ARGB32_Premultiplied);

    QObject::connect(bg_window->scene(), SIGNAL(changed(const QList<QRectF>&)),
            this, SLOT(bg_changed(void)));
}

void PanelView::bg_changed(void)
{
    QPainter bg_painter(background);
        bg_window->viewport()->render(&bg_painter);
    bg_painter.end();

    QBrush br(*background);
    br.setStyle(Qt::TexturePattern);
    setBackgroundBrush(br);

    scene()->invalidate(QRectF(0,0,0,0), QGraphicsScene::BackgroundLayer);
}

<commit_msg>Map mouseReleaseEvent into scene coordinates<commit_after>#include"panelview.h"

#include<QString>
#include<QSize>
#include<QUrl>

#include<QGraphicsView>
#include<QGraphicsScene>
#include<QWidget>
#include<QDesktopWidget>

#include<QGLFramebufferObject>
#include<QPainter>

#include<QPaintEvent>
#include<QKeyEvent>
#include<QMouseEvent>
#include<QTabletEvent>

#include<QDeclarativeEngine>
#include<QDeclarativeContext>
#include<QDeclarativeView>
#include<QDeclarativeItem>

#include<QApplication>

PMonitor::PMonitor(void) : Dialog(false, false, false)
{
    const int width = qApp->desktop()->rect().width();
    const int height = qApp->desktop()->rect().height();

    setSceneRect(0, 0, width, height);
    setViewportUpdateMode(QGraphicsView::NoViewportUpdate);

    setAttribute(Qt::WA_NoSystemBackground);
    setCacheMode(QGraphicsView::CacheNone);
    setOptimizationFlags(
        QGraphicsView::DontSavePainterState |
        QGraphicsView::DontAdjustForAntialiasing);

    viewport()->setAttribute(Qt::WA_TranslucentBackground, false);
    scene()->setItemIndexMethod(QGraphicsScene::NoIndex);

    rootContext()->setContextProperty("screenWidth", width);
    rootContext()->setContextProperty("screenHeight", height);

    setSource(QUrl::fromLocalFile("/usr/share/meego-ux-panels/main.qml"));
}

PanelView::PanelView(void) : Dialog(false, false, true),
        QDeclarativeImageProvider(QDeclarativeImageProvider::Image)
{
    const int width = qApp->desktop()->rect().width();
    const int height = qApp->desktop()->rect().height();

    int j, k, total=1, cur_width, cur_height;
    QList<QObject *> kids;
    QDeclarativeItem *dec;
    QObject *child;

    r = new PMonitor();

    if(((child = r->rootObject()->findChild<QDeclarativeItem *>("appPage"))
         == NULL) |
       ((child =  child->findChild<QDeclarativeItem *>("PC")) == NULL) |
       ((child = child->findChild<QDeclarativeItem *>("PLV")) == NULL)) {
        qFatal("Upgrade your version of MeeGo-UX-Panels");
    }
    fwidth = child->property("contentWidth").toInt();
    r->rootObject()->setProperty("width", fwidth);
    r->rootObject()->setProperty("height", height);

    QObject::connect(r->scene(), SIGNAL(changed(const QList<QRectF>&)),
            this, SLOT(invalidate(const QList<QRectF>&)));

    setSceneRect(0, 0, width, height);

    const int p_width = fwidth /  NUM_C;
    const int p_height = height / NUM_R;
    for(j = 0; j < NUM_P; j++) {
        cache[j] = new QImage(p_width, p_height,
             QImage::Format_ARGB32_Premultiplied);
    }

    qobject_cast<QGLWidget *>(viewport())->makeCurrent();
    fbo = new QGLFramebufferObject(p_width, p_height,
             QGLFramebufferObject::CombinedDepthStencil);

    engine()->addImageProvider(QLatin1String("gen"), this);

    setSource(QUrl::fromLocalFile("/usr/share/meego-ux-daemon/real.qml"));
    rootObject()->setProperty("contentWidth", fwidth);
    rootObject()->setProperty("contentHeight", height);
    rootObject()->setProperty("width", width);
    rootObject()->setProperty("height", height);

    dec =  qobject_cast<QDeclarativeItem*>(rootObject());
    kids = dec->children();

    for(j = 0, cur_height =0; j < NUM_R; j++, cur_height += p_height) {
        for(k = 0, cur_width = 0; k < NUM_C; k++, cur_width += p_width) {
            kids.at(total)->setProperty("width", p_width);
            kids.at(total)->setProperty("height", p_height);
            kids.at(total)->setProperty("x", cur_width);
            kids.at(total)->setProperty("y", cur_height);

            QString source = QString(ISRC);
            source += QString::number(total-1);
            kids.at(total)->setProperty("source", source);
            total++;
        }
    }

    setOptimizationFlags(
        QGraphicsView::DontSavePainterState |
        QGraphicsView::DontAdjustForAntialiasing);

    setCacheMode(QGraphicsView::CacheBackground);
    scene()->setItemIndexMethod(QGraphicsScene::NoIndex);
    viewport()->setAttribute(Qt::WA_OpaquePaintEvent);

    create_bg();
}

PanelView::~PanelView(void)
{
    int i;

    for(i = 0; i < NUM_P; i++) {
        delete cache[i];
    }

    delete r;
    delete background;
    delete bg_window;

    delete fbo;
}

void PanelView::keyPressEvent(QKeyEvent *e)
{
    r->keyPressEvent(e);
}

void PanelView::keyReleaseEvent(QKeyEvent *e)
{
    r->keyReleaseEvent(e);
}

void PanelView::mouseDoubleClickEvent(QMouseEvent *e)
{
    r->mouseDoubleClickEvent(e);
}

void PanelView::mousePressEvent(QMouseEvent *e)
{
    QDeclarativeItem *ro;

    ro = qobject_cast<QDeclarativeItem *>(rootObject());
    QPoint np(e->x() + ro->property("contentX").toDouble(), e->y());
    QMouseEvent ne(e->type(), np, e->button(), e->buttons(), e->modifiers());

    bg_window->mousePressEvent(e);
    r->mousePressEvent(&ne);
    QDeclarativeView::mousePressEvent(e);
}

void PanelView::mouseReleaseEvent(QMouseEvent *e)
{
    QDeclarativeItem *ro;

    ro = qobject_cast<QDeclarativeItem *>(rootObject());
    QPoint np(e->x() + ro->property("contentX").toDouble(), e->y());
    QMouseEvent ne(e->type(), np, e->button(), e->buttons(), e->modifiers());

    bg_window->mouseReleaseEvent(e);
    r->mouseReleaseEvent(&ne);
    QDeclarativeView::mouseReleaseEvent(e);
}

void PanelView::tabletEvent(QTabletEvent *e)
{
    r->tabletEvent(e);
}

QImage PanelView::requestImage(const QString &id, QSize *size,
        const QSize &resize)
{
    Q_UNUSED(size);
    Q_UNUSED(resize);

    int i = id.toInt();

    while(i >= NUM_P) {
        i -= NUM_P;
    }

    return *cache[i];
}

static QRectF consolidate_width(const QList<QRectF> &region)
{
    qreal l,r, t, b;
    int i;

    l = region.at(0).x();
    r = region.at(0).x() + region.at(0).width();
    t = region.at(0).y();
    b = region.at(0).y() + region.at(0).height();

    for(i = 1; i < region.count(); i++) {
        const double _l = region.at(i).x();
        const double _r = region.at(i).x() + region.at(i).width();
        const double _t = region.at(i).y();
        const double _b = region.at(i).y() + region.at(i).height();
        if(_l < l) {
            l = _l;
        }
        if(_r> r) {
            r = _r;
        }
        if(_t < t) {
            t = _t;
        }
        if(_b > b) {
            b = _b;
        }
    }

    return QRectF(l, t, r -l, b - t);
}

void PanelView::invalidate(const QList<QRectF> &region)
{
    const int height = qApp->desktop()->rect().height();
    const int p_width = fwidth /  NUM_C;
    const int p_height = height / NUM_R;

    int i, j, c_width, c_height, total=0;

    if(region.count() > 0) {
        QRectF n = consolidate_width(region);
        for(i = 0, c_height =0; i < NUM_R; i++, c_height += p_height) {
            for(j =0, c_width=0; j < NUM_C; j++, c_width += p_width) {
                QRectF d(c_width, c_height , p_width, p_height);
                if(d.intersects(n)) {
                    draw_single(total);
                }
                total++;
            }
        }
    }
}

inline void PanelView::draw_single(int i)
{
    const int height = qApp->desktop()->rect().height();
    const int p_width = fwidth /  NUM_C;
    const int p_height = height / NUM_R;

    static const QDeclarativeItem *dec = qobject_cast<QDeclarativeItem *>
        (rootObject());
    static const QList<QObject *> kids = dec->children();

    int c, _r=0,k;
    QImage *old;
    QString src;
    QPainter p;

    c = i;
    while(c >= NUM_C) {
        _r++;
        c -= NUM_C;
    }

    qobject_cast<QGLWidget *>(viewport())->makeCurrent();
    p.begin(fbo);
        glClear(GL_COLOR_BUFFER_BIT);
        r->viewport()->render(&p, QPoint(), QRegion(
            p_width * c, p_height *_r,
            p_width, p_height));
    p.end();

    old = cache[i];
    cache[i] = new QImage(fbo->toImage());
    delete old;

    src = kids.at(i+1)->property("source").toString();
    k = src.right(src.size() - ISRC_LEN).toInt();
    src.truncate(ISRC_LEN);
    k += NUM_P;
    src += QString::number(k);
    kids.at(i+1)->setProperty("source", src);
}

void PanelView::create_bg(void)
{
    const int width = qApp->desktop()->rect().width();
    const int height = qApp->desktop()->rect().height();

    bg_window = new PMonitor();
    bg_window->setSource(QUrl::fromLocalFile(
        "/usr/share/meego-ux-daemon/background.qml"));
    background = new QImage(width, height,
         QImage::Format_ARGB32_Premultiplied);

    QObject::connect(bg_window->scene(), SIGNAL(changed(const QList<QRectF>&)),
            this, SLOT(bg_changed(void)));
}

void PanelView::bg_changed(void)
{
    QPainter bg_painter(background);
        bg_window->viewport()->render(&bg_painter);
    bg_painter.end();

    QBrush br(*background);
    br.setStyle(Qt::TexturePattern);
    setBackgroundBrush(br);

    scene()->invalidate(QRectF(0,0,0,0), QGraphicsScene::BackgroundLayer);
}

<|endoftext|>


<commit_before>#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>

extern "C"
{
#include "../src/classifiers/dynamic_classifiers/flow_table/flow_table.h"
#include "../libs/memory_management/memory_management.h"
#include "../libs/thread_pool/thread_pool.h"
}

#include "gtest/gtest.h"

#define NB_NUMBERS      1000
#define NB_THREADS      1
#define HEADER_LENGTH   16
#define HEADER_BIT_L    320

struct arguments_t
{
   u_char* numbers;
   uint32_t* index;
   uint32_t size;
   hash_table** table;
};

uint32_t *get_random_numbers(uint32_t min, uint32_t max);
void* job_insert(void* args);
void* job_get(void* args);
void* job_remove(void* args);
void init(arguments_t*** args);

TEST (FlowTable, Insert)
{
   arguments_t** args;
   threadpool_t* pool = new_threadpool(NB_THREADS);
   init(&args);

   for (uint32_t i = 0; i < NB_THREADS; ++i)
      threadpool_add_work(pool, job_insert, args[i]);
   threadpool_wait(pool);
   free_threadpool(pool);

   hash_table_free(args[0]->table);
}

TEST (FlowTable, Get)
{
   arguments_t** args;
   threadpool_t* pool = new_threadpool(NB_THREADS);
   init(&args);

   for (uint32_t i = 0; i < NB_NUMBERS; ++i)
      put_flow(*(*args)->table, &(*args)->numbers[i], HEADER_BIT_L, &(*args)->numbers[i]);

   for (uint32_t i = 0; i < NB_THREADS; ++i)
      threadpool_add_work(pool, job_get, args[i]);
   threadpool_wait(pool);
   free_threadpool(pool);

   hash_table_free(args[0]->table);
}

TEST (FlowTable, Remove)
{
   arguments_t** args;
   threadpool_t* pool = new_threadpool(NB_THREADS);
   init(&args);

   for (uint32_t i = 0; i < NB_NUMBERS; ++i)
      put_flow(*(*args)->table, &(*args)->numbers[i], HEADER_BIT_L, &(*args)->numbers[i]);

   for (uint32_t i = 0; i < NB_THREADS; ++i)
      threadpool_add_work(pool, job_remove, args[i]);
   threadpool_wait(pool);
   free_threadpool(pool);

   hash_table_free(args[0]->table);
}

int main(int argc, char **argv)
{
   srand(time(NULL));
   ::testing::InitGoogleTest(&argc, argv);
   return RUN_ALL_TESTS();
}

uint32_t *get_random_numbers(uint32_t min, uint32_t max)
{
   uint32_t size = max - min;
   uint32_t *result = new uint32_t[size];
   bool is_used[max];
   for (uint32_t i = 0; i < size; i++)
   {
      is_used[i] = false;
   }
   uint32_t im = 0;
   for (uint32_t in = min; in < max && im < size; ++in)
   {
      uint32_t r = rand() % (in + 1); /* generate a random number 'r' */
      if (is_used[r])                 /* we already have 'r' */
         r = in;                      /* use 'in' instead of the generated number */

      result[im++] = r + min;
      is_used[r] = true;
   }
   return result;
}

void init(arguments_t*** args)
{
   // Init phase
   hash_table_init();

   // Get random unique flows
   uint32_t* protocols = get_random_numbers(0, 255);
   uint32_t* source_address = get_random_numbers(0, NB_NUMBERS);
   uint32_t* destination_address = get_random_numbers((NB_NUMBERS + 1), (NB_NUMBERS * 2) + 1);
   uint32_t* source_port = get_random_numbers(0, 65535);
   uint32_t* destination_port = get_random_numbers(0, 65535);

   u_char** keys = new u_char*[NB_NUMBERS];
   uint32_t j = 0;
   uint32_t* nb = new uint32_t;
   uint8_t zero = 0;
   for(uint32_t i = 0; i < NB_NUMBERS * 4; i+=4){
      key_type tmp = new_byte_stream();

      // Put the offset of port (9 bytes)
      for(uint32_t j = 0; j < 9; j++)
         append_bytes(tmp, &zero, 1);

      // Put the port
      *nb = protocols[(i % 256)];
      append_bytes(tmp, nb, 1);

      // Put the offset of the addresses (2 bytes)
      for(uint32_t j = 0; j < 2; j++)
         append_bytes(tmp, &zero, 1);

      // Put the source address
      *nb = source_address[i];
      append_bytes(tmp, nb, 4);

      // Put the destination address
      *nb = destination_address[i];
      append_bytes(tmp, nb, 4);

      // Put the offset of the source ports (16 bytes)
      for(uint32_t j = 0; j < 16; j++)
         append_bytes(tmp, &zero, 1);

      // Put the source port
      *nb = source_port[(i % 65536)];
      append_bytes(tmp, nb, 2);

      // Put the destination port
      *nb = destination_port[(i % 65536)];
      append_bytes(tmp, nb, 2);

      // Get the uint8_t array that form the header
      keys[j++] = tmp->stream;
   }

   // Preparing the structure
   *args = new arguments_t*[NB_THREADS];
   hash_table** table = new hash_table*;
   *table = new_hash_table(FNV_1);

   // We distribute the work per threads
   uint32_t divider = NB_NUMBERS / NB_THREADS;
   uint32_t remain = NB_NUMBERS % NB_THREADS;
   uint32_t* indexes = new uint32_t[NB_NUMBERS];
   for (uint32_t i = 0; i < NB_NUMBERS; i++)
      indexes[i] = i;

   for (uint32_t p = 0; p < NB_THREADS; ++p)
   {
      (*args)[p] = new arguments_t;
      (*args)[p]->numbers = keys[p * divider];
      (*args)[p]->index = &(indexes[p * divider]);

      if(p != (NB_THREADS - 1))
         (*args)[p]->size = divider;
      else
         (*args)[p]->size = divider + remain;
      (*args)[p]->table = table;
   }
}

void* job_insert(void* args)
{
   arguments_t* args_cast = (arguments_t*)args;
   for (uint32_t i = 0; i < args_cast->size; ++i){
      bool result = put_flow(*args_cast->table, &args_cast->numbers[i], HEADER_BIT_L, &args_cast->numbers[i]);
      EXPECT_TRUE(result);
   }
   return NULL;
}

void* job_get(void* args)
{
   arguments_t* args_cast = (arguments_t*)args;
   for (uint32_t i = 0; i < args_cast->size; ++i){
      if (args_cast->numbers[i])
         EXPECT_EQ(get_flow(*args_cast->table, &args_cast->numbers[i], HEADER_BIT_L), &args_cast->numbers[i]);
   }
   return NULL;
}

void* job_remove(void* args)
{
   arguments_t* args_cast = (arguments_t*)args;
   for(uint32_t i = 0; i < args_cast->size; ++i){
      bool result = remove_flow(*args_cast->table, &args_cast->numbers[i], HEADER_BIT_L);
      EXPECT_TRUE(result);
   }
   return NULL;
}
<commit_msg>[FIX] flow table: test fixed<commit_after>#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>

extern "C"
{
#include "../src/classifiers/dynamic_classifiers/flow_table/flow_table.h"
#include "../libs/memory_management/memory_management.h"
#include "../libs/thread_pool/thread_pool.h"
}

#include "gtest/gtest.h"

#define NB_NUMBERS      1000000
#define NB_THREADS      64
#define HEADER_LENGTH   16
#define HEADER_BIT_L    320

struct arguments_t
{
   u_char** numbers;
   uint32_t* index;
   uint32_t size;
   hash_table** table;
};

uint32_t *get_random_numbers(uint32_t min, uint32_t max);
void* job_insert(void* args);
void* job_get(void* args);
void* job_remove(void* args);
void init(arguments_t*** args);

TEST (FlowTable, Insert)
{
   arguments_t** args;
   threadpool_t* pool = new_threadpool(NB_THREADS);
   init(&args);

   for (uint32_t i = 0; i < NB_THREADS; ++i)
      threadpool_add_work(pool, job_insert, args[i]);
   threadpool_wait(pool);
   free_threadpool(pool);

   hash_table_free(args[0]->table);
}

TEST (FlowTable, Get)
{
   arguments_t** args;
   threadpool_t* pool = new_threadpool(NB_THREADS);
   init(&args);

   for (uint32_t i = 0; i < NB_NUMBERS; ++i)
      put_flow(*(*args)->table, (*args)->numbers[i], HEADER_BIT_L, &(*args)->numbers[i]);

   for (uint32_t i = 0; i < NB_THREADS; ++i)
      threadpool_add_work(pool, job_get, args[i]);
   threadpool_wait(pool);
   free_threadpool(pool);

   hash_table_free(args[0]->table);
}

TEST (FlowTable, Remove)
{
   arguments_t** args;
   threadpool_t* pool = new_threadpool(NB_THREADS);
   init(&args);

   for (uint32_t i = 0; i < NB_NUMBERS; ++i)
      put_flow(*(*args)->table, (*args)->numbers[i], HEADER_BIT_L, &(*args)->numbers[i]);

   for (uint32_t i = 0; i < NB_THREADS; ++i)
      threadpool_add_work(pool, job_remove, args[i]);
   threadpool_wait(pool);
   free_threadpool(pool);

   hash_table_free(args[0]->table);
}

int main(int argc, char **argv)
{
   srand(time(NULL));
   ::testing::InitGoogleTest(&argc, argv);
   return RUN_ALL_TESTS();
}

uint32_t *get_random_numbers(uint32_t min, uint32_t max)
{
   uint32_t size = max - min;
   uint32_t *result = new uint32_t[size];
   bool is_used[max];
   for (uint32_t i = 0; i < size; i++)
   {
      is_used[i] = false;
   }
   uint32_t im = 0;
   for (uint32_t in = min; in < max && im < size; ++in)
   {
      uint32_t r = rand() % (in + 1); /* generate a random number 'r' */
      if (is_used[r])                 /* we already have 'r' */
         r = in;                      /* use 'in' instead of the generated number */

      result[im++] = r + min;
      is_used[r] = true;
   }
   return result;
}

void init(arguments_t*** args)
{
   // Init phase
   hash_table_init();

   // Get random unique flows
   uint32_t* protocols = get_random_numbers(0, 255);
   uint32_t* source_address = get_random_numbers(0, NB_NUMBERS);
   uint32_t* destination_address = get_random_numbers(NB_NUMBERS, (NB_NUMBERS * 2));
   uint32_t* source_port = get_random_numbers(0, 65535);
   uint32_t* destination_port = get_random_numbers(0, 65535);

   u_char** keys = new u_char*[NB_NUMBERS];
   uint32_t j = 0;
   uint32_t* nb = new uint32_t;
   uint8_t zero = 0;
   for(uint32_t i = 0; i < NB_NUMBERS; i++){
      key_type tmp = new_byte_stream();

      // Put the offset of port (9 bytes)
      for(uint32_t j = 0; j < 9; j++)
         append_bytes(tmp, &zero, 1);

      // Put the port
      *nb = protocols[(i % 256)];
      append_bytes(tmp, nb, 1);

      // Put the offset of the addresses (2 bytes)
      for(uint32_t j = 0; j < 2; j++)
         append_bytes(tmp, &zero, 1);

      // Put the source address
      *nb = source_address[i];
      append_bytes(tmp, nb, 4);

      // Put the destination address
      *nb = destination_address[i];
      append_bytes(tmp, nb, 4);

      // Put the offset of the source ports (16 bytes)
      for(uint32_t j = 0; j < 16; j++)
         append_bytes(tmp, &zero, 1);

      // Put the source port
      *nb = source_port[(i % 65536)];
      append_bytes(tmp, nb, 2);

      // Put the destination port
      *nb = destination_port[(i % 65536)];
      append_bytes(tmp, nb, 2);

      // Get the uint8_t array that form the header
      keys[j++] = tmp->stream;
   }

   // Preparing the structure
   *args = new arguments_t*[NB_THREADS];
   hash_table** table = new hash_table*;
   *table = new_hash_table(FNV_1);

   // We distribute the work per threads
   uint32_t divider = NB_NUMBERS / NB_THREADS;
   uint32_t remain = NB_NUMBERS % NB_THREADS;
   uint32_t* indexes = new uint32_t[NB_NUMBERS];
   for (uint32_t i = 0; i < NB_NUMBERS; i++)
      indexes[i] = i;

   for (uint32_t p = 0; p < NB_THREADS; ++p)
   {
      (*args)[p] = new arguments_t;
      (*args)[p]->numbers = &keys[p * divider];
      (*args)[p]->index = &(indexes[p * divider]);

      if(p != (NB_THREADS - 1))
         (*args)[p]->size = divider;
      else
         (*args)[p]->size = divider + remain;
      (*args)[p]->table = table;
   }
}

void* job_insert(void* args)
{
   arguments_t* args_cast = (arguments_t*)args;
   for (uint32_t i = 0; i < args_cast->size; ++i){
      bool result = put_flow(*args_cast->table, args_cast->numbers[i], HEADER_BIT_L, &args_cast->numbers[i]);
      EXPECT_TRUE(result);
   }
   return NULL;
}

void* job_get(void* args)
{
   arguments_t* args_cast = (arguments_t*)args;
   for (uint32_t i = 0; i < args_cast->size; ++i){
      if (args_cast->numbers[i])
         EXPECT_EQ(get_flow(*args_cast->table, args_cast->numbers[i], HEADER_BIT_L), &args_cast->numbers[i]);
   }
   return NULL;
}

void* job_remove(void* args)
{
   arguments_t* args_cast = (arguments_t*)args;
   for(uint32_t i = 0; i < args_cast->size; ++i){
      bool result = remove_flow(*args_cast->table, args_cast->numbers[i], HEADER_BIT_L);
      EXPECT_TRUE(result);
   }
   return NULL;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012, 2013 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#include <fstream>

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/thread/mutex.hpp>

#include <qi/os.hpp>
#include <qi/log.hpp>
#include <qi/types.hpp>
#include <qi/error.hpp>
#include <qi/path.hpp>

qiLogCategory("qi.os");

namespace qi {
  namespace os {
    /* Have the static variable we need inside the function so that we
     * give correct results at initialization time, but also force
     * initialization so that timestamp 0 corresponds to pogram start time.
     */
    static int64_t _unused_base = ustime();

    int64_t ustime()
    {
      static bool initialized = false;
      static int64_t base;
      timeval tv;
      gettimeofday(&tv);
      if (!initialized)
      {
        base = tv.tv_sec*1000000LL + tv.tv_usec;
        initialized = true;
      }
      return tv.tv_sec*1000000LL + tv.tv_usec - base;
    }

    static inline void update_tv(qi::os::timeval *t)
    {
      const long usecPerSec = 1000 * 1000;
      while (t->tv_usec >= usecPerSec)
      {
        t->tv_sec++;
        t->tv_usec -= usecPerSec;
      }
      while (t->tv_usec < 0)
      {
        t->tv_sec--;
        t->tv_usec += usecPerSec;
      }
    }

    qi::os::timeval operator+(const qi::os::timeval &lhs,
                              const qi::os::timeval &rhs)
    {
      qi::os::timeval res;
      res.tv_sec = lhs.tv_sec + rhs.tv_sec;
      res.tv_usec = lhs.tv_usec + rhs.tv_usec;
      update_tv(&res);

      return res;
    }

    qi::os::timeval operator+(const qi::os::timeval &lhs,
                              long                   us)
    {
      const long usecPerSec = 1000 * 1000;

      qi::os::timeval res;
      res.tv_sec = lhs.tv_sec + (us / usecPerSec);
      res.tv_usec = lhs.tv_usec + (us % usecPerSec);
      update_tv(&res);

      return res;
    }

    qi::os::timeval operator-(const qi::os::timeval &lhs,
                              const qi::os::timeval &rhs)
    {
      qi::os::timeval res;
      res.tv_sec = lhs.tv_sec - rhs.tv_sec;
      res.tv_usec = lhs.tv_usec - rhs.tv_usec;
      update_tv(&res);

      return res;
    }

    qi::os::timeval operator-(const qi::os::timeval &lhs,
                              long                   us)
    {
      const long usecPerSec = 1000 * 1000;

      qi::os::timeval res;
      res.tv_sec = lhs.tv_sec - (us / usecPerSec);
      res.tv_usec = lhs.tv_usec - (us % usecPerSec);
      update_tv(&res);

      return res;
    }

    /* getMachineId will return an uuid as a string.
     * If the uuid is not created yet, it will generate it and store it
     * in machine_id file.
     * Otherwise it will read the file to retrieve the uuid and cache it
     * for further uses.
     * If the file is removed, a new file with a different uuid will be
     * created.
     */
    std::string getMachineId()
    {
      static bool initialized = false;
      static std::string idString;

      if (initialized)
        return idString;

      static boost::mutex mutex;
      boost::mutex::scoped_lock lock(mutex);
      if (initialized)
        return idString;
      std::string idFilePath(qi::path::userWritableConfPath("qimessaging", "machine_id"));
      std::ifstream idFile(idFilePath.c_str());

      if (idFile)
      {
        idFile >> idString;
        idFile.close();
        initialized = true;
        return idString;
      }

      std::ofstream newIdFile(idFilePath.c_str());

      idString = generateUuid();
      if (newIdFile)
      {
        newIdFile << idString;
        newIdFile.close();
        initialized = true;
      }
      else
      {
        qiLogError() << "Unable to create file: " << idFilePath;
      }

      return idString;
    }

    std::string generateUuid()
    {
      boost::uuids::uuid u = boost::uuids::random_generator()();
      return to_string(u);
    }
  }
}
<commit_msg>android: Fix getMachineId<commit_after>/*
 * Copyright (c) 2012, 2013 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#include <fstream>

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/thread/mutex.hpp>

#include <qi/os.hpp>
#include <qi/log.hpp>
#include <qi/types.hpp>
#include <qi/error.hpp>
#include <qi/path.hpp>

qiLogCategory("qi.os");

namespace qi {
  namespace os {
    /* Have the static variable we need inside the function so that we
     * give correct results at initialization time, but also force
     * initialization so that timestamp 0 corresponds to pogram start time.
     */
    static int64_t _unused_base = ustime();

    int64_t ustime()
    {
      static bool initialized = false;
      static int64_t base;
      timeval tv;
      gettimeofday(&tv);
      if (!initialized)
      {
        base = tv.tv_sec*1000000LL + tv.tv_usec;
        initialized = true;
      }
      return tv.tv_sec*1000000LL + tv.tv_usec - base;
    }

    static inline void update_tv(qi::os::timeval *t)
    {
      const long usecPerSec = 1000 * 1000;
      while (t->tv_usec >= usecPerSec)
      {
        t->tv_sec++;
        t->tv_usec -= usecPerSec;
      }
      while (t->tv_usec < 0)
      {
        t->tv_sec--;
        t->tv_usec += usecPerSec;
      }
    }

    qi::os::timeval operator+(const qi::os::timeval &lhs,
                              const qi::os::timeval &rhs)
    {
      qi::os::timeval res;
      res.tv_sec = lhs.tv_sec + rhs.tv_sec;
      res.tv_usec = lhs.tv_usec + rhs.tv_usec;
      update_tv(&res);

      return res;
    }

    qi::os::timeval operator+(const qi::os::timeval &lhs,
                              long                   us)
    {
      const long usecPerSec = 1000 * 1000;

      qi::os::timeval res;
      res.tv_sec = lhs.tv_sec + (us / usecPerSec);
      res.tv_usec = lhs.tv_usec + (us % usecPerSec);
      update_tv(&res);

      return res;
    }

    qi::os::timeval operator-(const qi::os::timeval &lhs,
                              const qi::os::timeval &rhs)
    {
      qi::os::timeval res;
      res.tv_sec = lhs.tv_sec - rhs.tv_sec;
      res.tv_usec = lhs.tv_usec - rhs.tv_usec;
      update_tv(&res);

      return res;
    }

    qi::os::timeval operator-(const qi::os::timeval &lhs,
                              long                   us)
    {
      const long usecPerSec = 1000 * 1000;

      qi::os::timeval res;
      res.tv_sec = lhs.tv_sec - (us / usecPerSec);
      res.tv_usec = lhs.tv_usec - (us % usecPerSec);
      update_tv(&res);

      return res;
    }

    /* getMachineId will return an uuid as a string.
     * If the uuid is not created yet, it will generate it and store it
     * in machine_id file.
     * Otherwise it will read the file to retrieve the uuid and cache it
     * for further uses.
     * If the file is removed, a new file with a different uuid will be
     * created.
     */
    std::string getMachineId()
    {
      static bool initialized = false;
      static std::string idString;

      if (initialized)
        return idString;

      static boost::mutex mutex;
      boost::mutex::scoped_lock lock(mutex);
      if (initialized)
        return idString;
      std::string idFilePath(qi::path::userWritableConfPath("qimessaging", "machine_id"));
      std::ifstream idFile(idFilePath.c_str());

      if (idFile)
      {
        idFile >> idString;
        idFile.close();
        initialized = true;
        return idString;
      }

      std::ofstream newIdFile(idFilePath.c_str());

      idString = generateUuid();
      if (newIdFile)
      {
        newIdFile << idString;
        newIdFile.close();
        initialized = true;
      }
      else
      {
        qiLogError() << "Unable to create file: '" << idFilePath << "'";
      }

      return idString;
    }

    std::string generateUuid()
    {
      boost::uuids::uuid u = boost::uuids::random_generator()();
      return to_string(u);
    }
  }
}
<|endoftext|>


<commit_before>// Copyright Paul Dardeau, SwampBits LLC 2014
// BSD License

#include <stdio.h>
#include <string.h>

#include "HttpRequestHandler.h"
#include "Socket.h"
#include "SocketRequest.h"
#include "HttpServer.h"
#include "HTTP.h"
#include "HttpRequest.h"
#include "HttpResponse.h"
#include "Thread.h"
#include "BasicException.h"
#include "Logger.h"
#include "StrUtils.h"

static const std::string HTTP_ACCEPT_ENCODING = "accept-encoding";
static const std::string HTTP_CONNECTION      = "Connection:";
static const std::string HTTP_CONTENT_LENGTH  = "content-length:";
static const std::string HTTP_CONTENT_TYPE    = "content-type:";
static const std::string HTTP_DATE            = "date:";
static const std::string HTTP_SERVER          = "server:";
static const std::string HTTP_USER_AGENT      = "User-Agent";

static const std::string CONNECTION_CLOSE     = "close";

static const std::string ZERO                 = "0";
static const std::string FAVICON_ICO          = "/favicon.ico";

static const std::string CONTENT_TYPE_HTML    = "text/html";

static const std::string COUNT_PATH           = "path";
static const std::string COUNT_USER_AGENT     = "user_agent";

static const std::string QUESTION_MARK        = "?";

static const std::string GZIP                 = "gzip";

using namespace misere;
using namespace chaudiere;

//******************************************************************************

HttpRequestHandler::HttpRequestHandler(HttpServer& server,
                                       SocketRequest* socketRequest) :
   RequestHandler(socketRequest),
   m_server(server) {
   Logger::logInstanceCreate("HttpRequestHandler");
}

//******************************************************************************

HttpRequestHandler::HttpRequestHandler(HttpServer& server,
                                       Socket* socket) :
   RequestHandler(socket),
   m_server(server) {
   Logger::logInstanceCreate("HttpRequestHandler");
}

//******************************************************************************

HttpRequestHandler::~HttpRequestHandler() {
   Logger::logInstanceDestroy("HttpRequestHandler");
}

//******************************************************************************

void HttpRequestHandler::run() {
   Socket* socket = getSocket();

   if (!socket) {
      Logger::error("no socket or socket request present in RequestHandler");
      return;
   }

   socket->setTcpNoDelay(true);
   socket->setSendBufferSize(m_server.getSocketSendBufferSize());
   socket->setReceiveBufferSize(m_server.getSocketReceiveBufferSize());

   const bool isLoggingDebug = Logger::isLogging(Debug);
   if (isLoggingDebug) {
      Logger::debug("starting parse of HttpRequest");
   }

   HttpRequest request(*socket);

   if (request.isInitialized()) {
      if (isLoggingDebug) {
         Logger::debug("ending parse of HttpRequest");
      }

      const std::string& method = request.getMethod();
      const std::string& protocol = request.getProtocol();
      const std::string& path = request.getPath();

      std::string routingPath = path;

      std::string clientIPAddress;
      socket->getPeerIPAddress(clientIPAddress);

      if (StrUtils::containsString(path, QUESTION_MARK)) {
         // strip arguments from path
         const std::string::size_type posQuestionMark =
            path.find(QUESTION_MARK);
         if (posQuestionMark != std::string::npos) {
            routingPath = path.substr(0, posQuestionMark);
         }
      }

      Logger::countOccurrence(COUNT_PATH, routingPath);

      if (request.hasHeaderValue(HTTP_USER_AGENT)) {
         Logger::countOccurrence(COUNT_USER_AGENT,
                                 request.getHeaderValue(HTTP_USER_AGENT));
      }

      HttpHandler* pHandler = m_server.getPathHandler(routingPath);
      bool handlerAvailable = false;

      if (pHandler == NULL) {
         Logger::info("no handler for request: " + routingPath);
      }

      // assume the worst
      std::string responseCode = HTTP::HTTP_RESP_SERV_ERR_INTERNAL_ERROR;
      const std::string systemDate = m_server.getSystemDateGMT();
      KeyValuePairs headers;
      headers.addPair(HTTP_CONNECTION, CONNECTION_CLOSE);
      const std::string& serverString = m_server.getServerId();

      if (!serverString.empty()) {
         headers.addPair(HTTP_SERVER, serverString);
      }

      headers.addPair(HTTP_DATE, systemDate);
      //headers.addPair(HTTP_CONTENT_TYPE, CONTENT_TYPE_HTML);

      if ((HTTP::HTTP_PROTOCOL1_0 != protocol) &&
          (HTTP::HTTP_PROTOCOL1_1 != protocol)) {
         responseCode = HTTP::HTTP_RESP_SERV_ERR_HTTP_VERSION_UNSUPPORTED;
         Logger::warning("unsupported protocol: " + protocol);
      } else if (NULL == pHandler) { // path recognized?
         responseCode = HTTP::HTTP_RESP_CLIENT_ERR_NOT_FOUND;
         //Logger::warning("bad request: " + path);
      } else if (!pHandler->isAvailable()) { // is our handler available?
         responseCode = HTTP::HTTP_RESP_SERV_ERR_SERVICE_UNAVAILABLE;
         Logger::warning("handler not available: " + routingPath);
      } else {
         handlerAvailable = true;
      }

      const std::string httpHeader = request.getRawHeader();
      const std::string httpBody = request.getBody();

      if (isLoggingDebug) {
         Logger::debug("HttpServer method: " + method);
         Logger::debug("HttpServer path: " + routingPath);
         Logger::debug("HttpServer protocol: " + protocol);

         Logger::debug("HttpServer header:");
         Logger::debug(httpHeader);

         Logger::debug("HttpServer body:");
         Logger::debug(httpBody);
      }

      int contentLength = 0;
      HttpResponse response;

      if ((NULL != pHandler) && handlerAvailable) {
         try {
            pHandler->serviceRequest(request, response);
            responseCode = StrUtils::toString(response.getStatusCode());
            const std::string& responseBody = response.getBody();
            contentLength = responseBody.size();

            if ((contentLength > 0) && !response.hasContentEncoding()) {
               if (request.hasAcceptEncoding()) {
                  const std::string& acceptEncoding =
                     request.getAcceptEncoding();

                  if (StrUtils::containsString(acceptEncoding, GZIP) &&
                      m_server.compressionEnabled() &&
                      m_server.compressResponse(response.getContentType()) &&
                      contentLength >= m_server.minimumCompressionSize()) {

                     try {
                        const std::string compressedResponseBody =
                           StrUtils::gzipCompress(responseBody);
                        contentLength = compressedResponseBody.size();
                        response.setBody(compressedResponseBody);
                        response.setContentEncoding(GZIP);
                     } catch (const std::exception& e) {
                        Logger::error("unable to compress response");
                     }
                  }
               }
            }

            response.populateWithHeaders(headers);
         } catch (const BasicException& be) {
            responseCode = HTTP::HTTP_RESP_SERV_ERR_INTERNAL_ERROR;
            Logger::error("exception handling request: " + be.whatString());
         } catch (const std::exception& e) {
            responseCode = HTTP::HTTP_RESP_SERV_ERR_INTERNAL_ERROR;
            Logger::error("exception handling request: " + std::string(e.what()));
         } catch (...) {
            responseCode = HTTP::HTTP_RESP_SERV_ERR_INTERNAL_ERROR;
            Logger::error("unknown exception handling request");
         }
      }

      if (contentLength > 0) {
         headers.addPair(HTTP_CONTENT_LENGTH,
                         StrUtils::toString(contentLength));
      } else {
         headers.addPair(HTTP_CONTENT_LENGTH, ZERO);
      }

      // log the request
      if (isThreadPooling()) {
         const std::string& runByWorkerThreadId = getRunByThreadWorkerId();

         if (!runByWorkerThreadId.empty()) {
            m_server.logRequest(clientIPAddress,
                                request.getRequestLine(),
                                responseCode,
                                runByWorkerThreadId);
         } else {
            m_server.logRequest(clientIPAddress,
                                request.getRequestLine(),
                                responseCode);
         }
      } else {
         m_server.logRequest(clientIPAddress,
                             request.getRequestLine(),
                             responseCode);
      }

      std::string responseAsString =
         m_server.buildHeader(responseCode, headers);

      if (contentLength > 0) {
         responseAsString += response.getBody();
      }

      socket->write(responseAsString);

      /*
       if (isLoggingDebug) {
         Logger::debug("response written, calling read so that client can close first");
       }

       // invoke a read to give the client the chance to close the socket
       // first. this also lets us easily detect the close on the client
       // end of the connection.  we won't actually read any data here,
       // this is just a wait to allow the client to close first
       char readBuffer[5];
       socket->read(readBuffer, 4);

      //if (m_socketRequest != NULL) {
      //   m_socketRequest->requestComplete();
      //}
       */
   } else {
      ::printf("error: unable to initialize HttpRequest\n");
   }
}

//******************************************************************************

<commit_msg>remove gzip functionality<commit_after>// Copyright Paul Dardeau, SwampBits LLC 2014
// BSD License

#include <stdio.h>
#include <string.h>

#include "HttpRequestHandler.h"
#include "Socket.h"
#include "SocketRequest.h"
#include "HttpServer.h"
#include "HTTP.h"
#include "HttpRequest.h"
#include "HttpResponse.h"
#include "Thread.h"
#include "BasicException.h"
#include "Logger.h"
#include "StrUtils.h"

static const std::string HTTP_ACCEPT_ENCODING = "accept-encoding";
static const std::string HTTP_CONNECTION      = "Connection:";
static const std::string HTTP_CONTENT_LENGTH  = "content-length:";
static const std::string HTTP_CONTENT_TYPE    = "content-type:";
static const std::string HTTP_DATE            = "date:";
static const std::string HTTP_SERVER          = "server:";
static const std::string HTTP_USER_AGENT      = "User-Agent";

static const std::string CONNECTION_CLOSE     = "close";

static const std::string ZERO                 = "0";
static const std::string FAVICON_ICO          = "/favicon.ico";

static const std::string CONTENT_TYPE_HTML    = "text/html";

static const std::string COUNT_PATH           = "path";
static const std::string COUNT_USER_AGENT     = "user_agent";

static const std::string QUESTION_MARK        = "?";

static const std::string GZIP                 = "gzip";

using namespace misere;
using namespace chaudiere;

//******************************************************************************

HttpRequestHandler::HttpRequestHandler(HttpServer& server,
                                       SocketRequest* socketRequest) :
   RequestHandler(socketRequest),
   m_server(server) {
   Logger::logInstanceCreate("HttpRequestHandler");
}

//******************************************************************************

HttpRequestHandler::HttpRequestHandler(HttpServer& server,
                                       Socket* socket) :
   RequestHandler(socket),
   m_server(server) {
   Logger::logInstanceCreate("HttpRequestHandler");
}

//******************************************************************************

HttpRequestHandler::~HttpRequestHandler() {
   Logger::logInstanceDestroy("HttpRequestHandler");
}

//******************************************************************************

void HttpRequestHandler::run() {
   Socket* socket = getSocket();

   if (!socket) {
      Logger::error("no socket or socket request present in RequestHandler");
      return;
   }

   socket->setTcpNoDelay(true);
   socket->setSendBufferSize(m_server.getSocketSendBufferSize());
   socket->setReceiveBufferSize(m_server.getSocketReceiveBufferSize());

   const bool isLoggingDebug = Logger::isLogging(Debug);
   if (isLoggingDebug) {
      Logger::debug("starting parse of HttpRequest");
   }

   HttpRequest request(*socket);

   if (request.isInitialized()) {
      if (isLoggingDebug) {
         Logger::debug("ending parse of HttpRequest");
      }

      const std::string& method = request.getMethod();
      const std::string& protocol = request.getProtocol();
      const std::string& path = request.getPath();

      std::string routingPath = path;

      std::string clientIPAddress;
      socket->getPeerIPAddress(clientIPAddress);

      if (StrUtils::containsString(path, QUESTION_MARK)) {
         // strip arguments from path
         const std::string::size_type posQuestionMark =
            path.find(QUESTION_MARK);
         if (posQuestionMark != std::string::npos) {
            routingPath = path.substr(0, posQuestionMark);
         }
      }

      Logger::countOccurrence(COUNT_PATH, routingPath);

      if (request.hasHeaderValue(HTTP_USER_AGENT)) {
         Logger::countOccurrence(COUNT_USER_AGENT,
                                 request.getHeaderValue(HTTP_USER_AGENT));
      }

      HttpHandler* pHandler = m_server.getPathHandler(routingPath);
      bool handlerAvailable = false;

      if (pHandler == NULL) {
         Logger::info("no handler for request: " + routingPath);
      }

      // assume the worst
      std::string responseCode = HTTP::HTTP_RESP_SERV_ERR_INTERNAL_ERROR;
      const std::string systemDate = m_server.getSystemDateGMT();
      KeyValuePairs headers;
      headers.addPair(HTTP_CONNECTION, CONNECTION_CLOSE);
      const std::string& serverString = m_server.getServerId();

      if (!serverString.empty()) {
         headers.addPair(HTTP_SERVER, serverString);
      }

      headers.addPair(HTTP_DATE, systemDate);
      //headers.addPair(HTTP_CONTENT_TYPE, CONTENT_TYPE_HTML);

      if ((HTTP::HTTP_PROTOCOL1_0 != protocol) &&
          (HTTP::HTTP_PROTOCOL1_1 != protocol)) {
         responseCode = HTTP::HTTP_RESP_SERV_ERR_HTTP_VERSION_UNSUPPORTED;
         Logger::warning("unsupported protocol: " + protocol);
      } else if (NULL == pHandler) { // path recognized?
         responseCode = HTTP::HTTP_RESP_CLIENT_ERR_NOT_FOUND;
         //Logger::warning("bad request: " + path);
      } else if (!pHandler->isAvailable()) { // is our handler available?
         responseCode = HTTP::HTTP_RESP_SERV_ERR_SERVICE_UNAVAILABLE;
         Logger::warning("handler not available: " + routingPath);
      } else {
         handlerAvailable = true;
      }

      const std::string httpHeader = request.getRawHeader();
      const std::string httpBody = request.getBody();

      if (isLoggingDebug) {
         Logger::debug("HttpServer method: " + method);
         Logger::debug("HttpServer path: " + routingPath);
         Logger::debug("HttpServer protocol: " + protocol);

         Logger::debug("HttpServer header:");
         Logger::debug(httpHeader);

         Logger::debug("HttpServer body:");
         Logger::debug(httpBody);
      }

      int contentLength = 0;
      HttpResponse response;

      if ((NULL != pHandler) && handlerAvailable) {
         try {
            pHandler->serviceRequest(request, response);
            responseCode = StrUtils::toString(response.getStatusCode());
            const std::string& responseBody = response.getBody();
            contentLength = responseBody.size();

            if ((contentLength > 0) && !response.hasContentEncoding()) {
               if (request.hasAcceptEncoding()) {
                  const std::string& acceptEncoding =
                     request.getAcceptEncoding();

                  /*
                  if (StrUtils::containsString(acceptEncoding, GZIP) &&
                      m_server.compressionEnabled() &&
                      m_server.compressResponse(response.getContentType()) &&
                      contentLength >= m_server.minimumCompressionSize()) {

                     try {
                        const std::string compressedResponseBody =
                           StrUtils::gzipCompress(responseBody);
                        contentLength = compressedResponseBody.size();
                        response.setBody(compressedResponseBody);
                        response.setContentEncoding(GZIP);
                     } catch (const std::exception& e) {
                        Logger::error("unable to compress response");
                     }
                  }
                  */
               }
            }

            response.populateWithHeaders(headers);
         } catch (const BasicException& be) {
            responseCode = HTTP::HTTP_RESP_SERV_ERR_INTERNAL_ERROR;
            Logger::error("exception handling request: " + be.whatString());
         } catch (const std::exception& e) {
            responseCode = HTTP::HTTP_RESP_SERV_ERR_INTERNAL_ERROR;
            Logger::error("exception handling request: " + std::string(e.what()));
         } catch (...) {
            responseCode = HTTP::HTTP_RESP_SERV_ERR_INTERNAL_ERROR;
            Logger::error("unknown exception handling request");
         }
      }

      if (contentLength > 0) {
         headers.addPair(HTTP_CONTENT_LENGTH,
                         StrUtils::toString(contentLength));
      } else {
         headers.addPair(HTTP_CONTENT_LENGTH, ZERO);
      }

      // log the request
      if (isThreadPooling()) {
         const std::string& runByWorkerThreadId = getRunByThreadWorkerId();

         if (!runByWorkerThreadId.empty()) {
            m_server.logRequest(clientIPAddress,
                                request.getRequestLine(),
                                responseCode,
                                runByWorkerThreadId);
         } else {
            m_server.logRequest(clientIPAddress,
                                request.getRequestLine(),
                                responseCode);
         }
      } else {
         m_server.logRequest(clientIPAddress,
                             request.getRequestLine(),
                             responseCode);
      }

      std::string responseAsString =
         m_server.buildHeader(responseCode, headers);

      if (contentLength > 0) {
         responseAsString += response.getBody();
      }

      socket->write(responseAsString);

      /*
       if (isLoggingDebug) {
         Logger::debug("response written, calling read so that client can close first");
       }

       // invoke a read to give the client the chance to close the socket
       // first. this also lets us easily detect the close on the client
       // end of the connection.  we won't actually read any data here,
       // this is just a wait to allow the client to close first
       char readBuffer[5];
       socket->read(readBuffer, 4);

      //if (m_socketRequest != NULL) {
      //   m_socketRequest->requestComplete();
      //}
       */
   } else {
      ::printf("error: unable to initialize HttpRequest\n");
   }
}

//******************************************************************************

<|endoftext|>


<commit_before>#include "signal.hpp"

namespace dafs
{
    Signal::Signal()
    {
        flag = false;
    }

    void
    Signal::Set()
    {
        flag = true;
        condition.notify_one();
    }

    void
    Signal::Wait()
    {
        std::unique_lock<std::mutex> lock(mutex);
        condition.wait(lock, [&] { return flag; });
    }
}
<commit_msg>Fix signal wait<commit_after>#include "signal.hpp"

namespace dafs
{
    Signal::Signal()
    {
        flag = false;
    }

    void
    Signal::Set()
    {
        flag = true;
        condition.notify_one();
    }

    void
    Signal::Wait()
    {
        std::unique_lock<std::mutex> lock(mutex);
        condition.wait(lock, [&] { return flag; });
        flag = false;
    }
}
<|endoftext|>


<commit_before>//== BodyFarm.cpp  - Factory for conjuring up fake bodies ----------*- C++ -*-//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// BodyFarm is a factory for creating faux implementations for functions/methods
// for analysis purposes.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/StringSwitch.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
#include "BodyFarm.h"

using namespace clang;

//===----------------------------------------------------------------------===//
// Helper creation functions for constructing faux ASTs.
//===----------------------------------------------------------------------===//

static bool isDispatchBlock(QualType Ty) {
  // Is it a block pointer?
  const BlockPointerType *BPT = Ty->getAs<BlockPointerType>();
  if (!BPT)
    return false;

  // Check if the block pointer type takes no arguments and
  // returns void.
  const FunctionProtoType *FT =
  BPT->getPointeeType()->getAs<FunctionProtoType>();
  if (!FT || !FT->getResultType()->isVoidType()  ||
      FT->getNumArgs() != 0)
    return false;

  return true;
}

namespace {
class ASTMaker {
public:
  ASTMaker(ASTContext &C) : C(C) {}

  /// Create a new DeclRefExpr for the referenced variable.
  DeclRefExpr *makeDeclRefExpr(const VarDecl *D);

  /// Create a new UnaryOperator representing a dereference.
  UnaryOperator *makeDereference(const Expr *Arg, QualType Ty);

  /// Create an implicit cast for an integer conversion.
  ImplicitCastExpr *makeIntegralCast(const Expr *Arg, QualType Ty);

  // Create an implicit cast for lvalue-to-rvaluate conversions.
  ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty);

private:
  ASTContext &C;
};
}

DeclRefExpr *ASTMaker::makeDeclRefExpr(const VarDecl *D) {
  DeclRefExpr *DR =
    DeclRefExpr::Create(/* Ctx = */ C,
                        /* QualifierLoc = */ NestedNameSpecifierLoc(),
                        /* TemplateKWLoc = */ SourceLocation(),
                        /* D = */ const_cast<VarDecl*>(D),
                        /* isEnclosingLocal = */ false,
                        /* NameLoc = */ SourceLocation(),
                        /* T = */ D->getType(),
                        /* VK = */ VK_LValue);
  return DR;
}

UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) {
  return new (C) UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty,
                               VK_LValue, OK_Ordinary, SourceLocation());
}

ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
  return ImplicitCastExpr::Create(C, Ty, CK_LValueToRValue,
                                  const_cast<Expr*>(Arg), 0, VK_RValue);
}

ImplicitCastExpr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) {
  return ImplicitCastExpr::Create(C, Ty, CK_IntegralCast,
                                  const_cast<Expr*>(Arg), 0, VK_RValue);
}

//===----------------------------------------------------------------------===//
// Creation functions for faux ASTs.
//===----------------------------------------------------------------------===//

typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D);

/// Create a fake body for dispatch_once.
static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
  // Check if we have at least two parameters.
  if (D->param_size() != 2)
    return 0;

  // Check if the first parameter is a pointer to integer type.
  const ParmVarDecl *Predicate = D->getParamDecl(0);
  QualType PredicateQPtrTy = Predicate->getType();
  const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>();
  if (!PredicatePtrTy)
    return 0;
  QualType PredicateTy = PredicatePtrTy->getPointeeType();
  if (!PredicateTy->isIntegerType())
    return 0;

  // Check if the second parameter is the proper block type.
  const ParmVarDecl *Block = D->getParamDecl(1);
  QualType Ty = Block->getType();
  if (!isDispatchBlock(Ty))
    return 0;

  // Everything checks out.  Create a fakse body that checks the predicate,
  // sets it, and calls the block.  Basically, an AST dump of:
  //
  // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) {
  //  if (!*predicate) {
  //    *predicate = 1;
  //    block();
  //  }
  // }

  ASTMaker M(C);

  // (1) Create the call.
  DeclRefExpr *DR = M.makeDeclRefExpr(Block);
  ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
  CallExpr *CE = new (C) CallExpr(C, ICE, ArrayRef<Expr*>(), C.VoidTy,
                                  VK_RValue, SourceLocation());

  // (2) Create the assignment to the predicate.
  IntegerLiteral *IL =
    IntegerLiteral::Create(C, llvm::APInt(C.getTypeSize(C.IntTy), (uint64_t) 1),
                           C.IntTy, SourceLocation());
  ICE = M.makeIntegralCast(IL, PredicateTy);
  DR = M.makeDeclRefExpr(Predicate);
  ImplicitCastExpr *LValToRval = M.makeLvalueToRvalue(DR, PredicateQPtrTy);
  UnaryOperator *UO = M.makeDereference(LValToRval, PredicateTy);
  BinaryOperator *B = new (C) BinaryOperator(UO, ICE, BO_Assign,
                                             PredicateTy, VK_RValue,
                                             OK_Ordinary,
                                             SourceLocation());
  // (3) Create the compound statement.
  Stmt *Stmts[2];
  Stmts[0] = B;
  Stmts[1] = CE;
  CompoundStmt *CS = new (C) CompoundStmt(C, Stmts, 2, SourceLocation(),
                                          SourceLocation());

  // (4) Create the 'if' condition.
  DR = M.makeDeclRefExpr(Predicate);
  LValToRval = M.makeLvalueToRvalue(DR, PredicateQPtrTy);
  UO = M.makeDereference(LValToRval, PredicateTy);
  LValToRval = M.makeLvalueToRvalue(UO, PredicateTy);
  UO = new (C) UnaryOperator(LValToRval, UO_LNot, C.IntTy,
                             VK_RValue, OK_Ordinary, SourceLocation());

  // (5) Create the 'if' statement.
  IfStmt *If = new (C) IfStmt(C, SourceLocation(), 0, UO, CS);
  return If;
}

/// Create a fake body for dispatch_sync.
static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
  // Check if we have at least two parameters.
  if (D->param_size() != 2)
    return 0;

  // Check if the second parameter is a block.
  const ParmVarDecl *PV = D->getParamDecl(1);
  QualType Ty = PV->getType();
  if (!isDispatchBlock(Ty))
    return 0;

  // Everything checks out.  Create a fake body that just calls the block.
  // This is basically just an AST dump of:
  //
  // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) {
  //   block();
  // }
  //
  ASTMaker M(C);
  DeclRefExpr *DR = M.makeDeclRefExpr(PV);
  ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
  CallExpr *CE = new (C) CallExpr(C, ICE, ArrayRef<Expr*>(), C.VoidTy,
                                  VK_RValue, SourceLocation());
  return CE;
}

Stmt *BodyFarm::getBody(const FunctionDecl *D) {
  D = D->getCanonicalDecl();

  llvm::Optional<Stmt *> &Val = Bodies[D];
  if (Val.hasValue())
    return Val.getValue();

  Val = 0;

  if (D->getIdentifier() == 0)
    return 0;

  StringRef Name = D->getName();
  if (Name.empty())
    return 0;

  FunctionFarmer FF =
    llvm::StringSwitch<FunctionFarmer>(Name)
      .Case("dispatch_sync", create_dispatch_sync)
      .Case("dispatch_once", create_dispatch_once)
      .Default(NULL);

  if (FF) {
    Val = FF(C, D);
  }

  return Val.getValue();
}

<commit_msg>Create helper method in BodyFarm for creating simple assignments.<commit_after>//== BodyFarm.cpp  - Factory for conjuring up fake bodies ----------*- C++ -*-//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// BodyFarm is a factory for creating faux implementations for functions/methods
// for analysis purposes.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/StringSwitch.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
#include "BodyFarm.h"

using namespace clang;

//===----------------------------------------------------------------------===//
// Helper creation functions for constructing faux ASTs.
//===----------------------------------------------------------------------===//

static bool isDispatchBlock(QualType Ty) {
  // Is it a block pointer?
  const BlockPointerType *BPT = Ty->getAs<BlockPointerType>();
  if (!BPT)
    return false;

  // Check if the block pointer type takes no arguments and
  // returns void.
  const FunctionProtoType *FT =
  BPT->getPointeeType()->getAs<FunctionProtoType>();
  if (!FT || !FT->getResultType()->isVoidType()  ||
      FT->getNumArgs() != 0)
    return false;

  return true;
}

namespace {
class ASTMaker {
public:
  ASTMaker(ASTContext &C) : C(C) {}

  /// Create a new BinaryOperator representing a simple assignment.
  BinaryOperator *makeAssignment(const Expr *LHS, const Expr *RHS, QualType Ty);

  /// Create a new DeclRefExpr for the referenced variable.
  DeclRefExpr *makeDeclRefExpr(const VarDecl *D);

  /// Create a new UnaryOperator representing a dereference.
  UnaryOperator *makeDereference(const Expr *Arg, QualType Ty);

  /// Create an implicit cast for an integer conversion.
  ImplicitCastExpr *makeIntegralCast(const Expr *Arg, QualType Ty);

  // Create an implicit cast for lvalue-to-rvaluate conversions.
  ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty);

private:
  ASTContext &C;
};
}

BinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS,
                                         QualType Ty) {
 return new (C) BinaryOperator(const_cast<Expr*>(LHS), const_cast<Expr*>(RHS),
                               BO_Assign, Ty, VK_RValue,
                               OK_Ordinary, SourceLocation());
}

DeclRefExpr *ASTMaker::makeDeclRefExpr(const VarDecl *D) {
  DeclRefExpr *DR =
    DeclRefExpr::Create(/* Ctx = */ C,
                        /* QualifierLoc = */ NestedNameSpecifierLoc(),
                        /* TemplateKWLoc = */ SourceLocation(),
                        /* D = */ const_cast<VarDecl*>(D),
                        /* isEnclosingLocal = */ false,
                        /* NameLoc = */ SourceLocation(),
                        /* T = */ D->getType(),
                        /* VK = */ VK_LValue);
  return DR;
}

UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) {
  return new (C) UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty,
                               VK_LValue, OK_Ordinary, SourceLocation());
}

ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
  return ImplicitCastExpr::Create(C, Ty, CK_LValueToRValue,
                                  const_cast<Expr*>(Arg), 0, VK_RValue);
}

ImplicitCastExpr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) {
  return ImplicitCastExpr::Create(C, Ty, CK_IntegralCast,
                                  const_cast<Expr*>(Arg), 0, VK_RValue);
}

//===----------------------------------------------------------------------===//
// Creation functions for faux ASTs.
//===----------------------------------------------------------------------===//

typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D);

/// Create a fake body for dispatch_once.
static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
  // Check if we have at least two parameters.
  if (D->param_size() != 2)
    return 0;

  // Check if the first parameter is a pointer to integer type.
  const ParmVarDecl *Predicate = D->getParamDecl(0);
  QualType PredicateQPtrTy = Predicate->getType();
  const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>();
  if (!PredicatePtrTy)
    return 0;
  QualType PredicateTy = PredicatePtrTy->getPointeeType();
  if (!PredicateTy->isIntegerType())
    return 0;

  // Check if the second parameter is the proper block type.
  const ParmVarDecl *Block = D->getParamDecl(1);
  QualType Ty = Block->getType();
  if (!isDispatchBlock(Ty))
    return 0;

  // Everything checks out.  Create a fakse body that checks the predicate,
  // sets it, and calls the block.  Basically, an AST dump of:
  //
  // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) {
  //  if (!*predicate) {
  //    *predicate = 1;
  //    block();
  //  }
  // }

  ASTMaker M(C);

  // (1) Create the call.
  DeclRefExpr *DR = M.makeDeclRefExpr(Block);
  ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
  CallExpr *CE = new (C) CallExpr(C, ICE, ArrayRef<Expr*>(), C.VoidTy,
                                  VK_RValue, SourceLocation());

  // (2) Create the assignment to the predicate.
  IntegerLiteral *IL =
    IntegerLiteral::Create(C, llvm::APInt(C.getTypeSize(C.IntTy), (uint64_t) 1),
                           C.IntTy, SourceLocation());
  ICE = M.makeIntegralCast(IL, PredicateTy);
  DR = M.makeDeclRefExpr(Predicate);
  ImplicitCastExpr *LValToRval = M.makeLvalueToRvalue(DR, PredicateQPtrTy);
  UnaryOperator *UO = M.makeDereference(LValToRval, PredicateTy);
  BinaryOperator * B = M.makeAssignment(UO, ICE, PredicateTy);

  // (3) Create the compound statement.
  Stmt *Stmts[2];
  Stmts[0] = B;
  Stmts[1] = CE;
  CompoundStmt *CS = new (C) CompoundStmt(C, Stmts, 2, SourceLocation(),
                                          SourceLocation());

  // (4) Create the 'if' condition.
  DR = M.makeDeclRefExpr(Predicate);
  LValToRval = M.makeLvalueToRvalue(DR, PredicateQPtrTy);
  UO = M.makeDereference(LValToRval, PredicateTy);
  LValToRval = M.makeLvalueToRvalue(UO, PredicateTy);
  UO = new (C) UnaryOperator(LValToRval, UO_LNot, C.IntTy,
                             VK_RValue, OK_Ordinary, SourceLocation());

  // (5) Create the 'if' statement.
  IfStmt *If = new (C) IfStmt(C, SourceLocation(), 0, UO, CS);
  return If;
}

/// Create a fake body for dispatch_sync.
static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
  // Check if we have at least two parameters.
  if (D->param_size() != 2)
    return 0;

  // Check if the second parameter is a block.
  const ParmVarDecl *PV = D->getParamDecl(1);
  QualType Ty = PV->getType();
  if (!isDispatchBlock(Ty))
    return 0;

  // Everything checks out.  Create a fake body that just calls the block.
  // This is basically just an AST dump of:
  //
  // void dispatch_sync(dispatch_queue_t queue, void (^block)(void)) {
  //   block();
  // }
  //
  ASTMaker M(C);
  DeclRefExpr *DR = M.makeDeclRefExpr(PV);
  ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
  CallExpr *CE = new (C) CallExpr(C, ICE, ArrayRef<Expr*>(), C.VoidTy,
                                  VK_RValue, SourceLocation());
  return CE;
}

Stmt *BodyFarm::getBody(const FunctionDecl *D) {
  D = D->getCanonicalDecl();

  llvm::Optional<Stmt *> &Val = Bodies[D];
  if (Val.hasValue())
    return Val.getValue();

  Val = 0;

  if (D->getIdentifier() == 0)
    return 0;

  StringRef Name = D->getName();
  if (Name.empty())
    return 0;

  FunctionFarmer FF =
    llvm::StringSwitch<FunctionFarmer>(Name)
      .Case("dispatch_sync", create_dispatch_sync)
      .Case("dispatch_once", create_dispatch_once)
      .Default(NULL);

  if (FF) {
    Val = FF(C, D);
  }

  return Val.getValue();
}

<|endoftext|>


<commit_before>/**
 * @file snyder.cpp
 * @brief implementation of the MetricsRegistry
 * @author Daniel Schauenberg <d@unwiredcouch.com>
 */

#include "snyder/metrics_registry.h"

using namespace Snyder;

MetricsRegistry::MetricsRegistry() : counterMutex(), gaugesMutex() {
}
MetricsRegistry::~MetricsRegistry() {
}

size_t MetricsRegistry::Increment(const std::string& name) {
  this->Increment(name, 1);
  return 0;
}
size_t MetricsRegistry::Increment(const std::string& name, uint64_t count) {
  std::lock_guard<std::mutex> lock(counterMutex);
  counterRegistry[name] += count;
  return 0;
}

size_t MetricsRegistry::Gauge(const std::string& name, uint64_t value) {
  std::lock_guard<std::mutex> lock(gaugesMutex);
  gaugesRegistry[name] = value;
  return 0;
}

MetricsStore MetricsRegistry::GetCounters() {
  std::lock_guard<std::mutex> lock(counterMutex);
  return counterRegistry;
}

MetricsStore MetricsRegistry::GetGauges() {
  std::lock_guard<std::mutex> lock(gaugesMutex);
  return gaugesRegistry;
}
<commit_msg>add method documentation<commit_after>/**
 * @file snyder.cpp
 * @brief implementation of the MetricsRegistry
 * @author Daniel Schauenberg <d@unwiredcouch.com>
 */

#include "snyder/metrics_registry.h"

using namespace Snyder;

MetricsRegistry::MetricsRegistry() : counterMutex(), gaugesMutex() {
}
MetricsRegistry::~MetricsRegistry() {
}

/**
 * @brief method to increment a metric by 1
 *
 * @param name the name of the counter to increment
 *
 * @return size_t 0
 */
size_t MetricsRegistry::Increment(const std::string& name) {
  this->Increment(name, 1);
  return 0;
}

/**
 * @brief method to increment a metric by a given count
 *
 * @param name the name of the counter to increment
 * @param count integer to increment the counter by
 *
 * @return size_t 0
 */
size_t MetricsRegistry::Increment(const std::string& name, uint64_t count) {
  std::lock_guard<std::mutex> lock(counterMutex);
  counterRegistry[name] += count;
  return 0;
}

/**
 * @brief method to record a gauge value
 *
 * @param name the name of the gauge to record
 * @param name the value of the gauge to record
 *
 * @return size_t 0
 */
size_t MetricsRegistry::Gauge(const std::string& name, uint64_t value) {
  std::lock_guard<std::mutex> lock(gaugesMutex);
  gaugesRegistry[name] = value;
  return 0;
}

/**
* @brief method to get the MetricsStore backing counters. This will
* return by value thus locking the mutex for the duration it takes to
* copy the data structure.
*
* @return MetricsStore
*/
MetricsStore MetricsRegistry::GetCounters() {
  std::lock_guard<std::mutex> lock(counterMutex);
  return counterRegistry;
}

/**
* @brief method to get the MetricsStore backing gauges. This will return
* by value thus locking the mutex for the duration it takes to copy the
* data structure.
*
* @return MetricsStore
*/
MetricsStore MetricsRegistry::GetGauges() {
  std::lock_guard<std::mutex> lock(gaugesMutex);
  return gaugesRegistry;
}
<|endoftext|>