<commit_before>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
/*
COPYING CONDITIONS NOTICE:

  This program is free software; you can redistribute it and/or modify
  it under the terms of version 2 of the GNU General Public License as
  published by the Free Software Foundation, and provided that the
  following conditions are met:

      * Redistributions of source code must retain this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below).

      * Redistributions in binary form must reproduce this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below) in the documentation and/or other materials
        provided with the distribution.

  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., 51 Franklin Street, Fifth Floor, Boston, MA
  02110-1301, USA.

COPYRIGHT NOTICE:

  TokuDB, Tokutek Fractal Tree Indexing Library.
  Copyright (C) 2007-2013 Tokutek, Inc.

DISCLAIMER:

  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.

UNIVERSITY PATENT NOTICE:

  The technology is licensed by the Massachusetts Institute of
  Technology, Rutgers State University of New Jersey, and the Research
  Foundation of State University of New York at Stony Brook under
  United States of America Serial No. 11/760379 and to the patents
  and/or patent applications resulting from it.

PATENT MARKING NOTICE:

  This software is covered by US Patent No. 8,185,551.
  This software is covered by US Patent No. 8,489,638.

PATENT RIGHTS GRANT:

  "THIS IMPLEMENTATION" means the copyrightable works distributed by
  Tokutek as part of the Fractal Tree project.

  "PATENT CLAIMS" means the claims of patents that are owned or
  licensable by Tokutek, both currently or in the future; and that in
  the absence of this license would be infringed by THIS
  IMPLEMENTATION or by using or running THIS IMPLEMENTATION.

  "PATENT CHALLENGE" shall mean a challenge to the validity,
  patentability, enforceability and/or non-infringement of any of the
  PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.

  Tokutek hereby grants to you, for the term and geographical scope of
  the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
  irrevocable (except as stated in this section) patent license to
  make, have made, use, offer to sell, sell, import, transfer, and
  otherwise run, modify, and propagate the contents of THIS
  IMPLEMENTATION, where such license applies only to the PATENT
  CLAIMS.  This grant does not include claims that would be infringed
  only as a consequence of further modifications of THIS
  IMPLEMENTATION.  If you or your agent or licensee institute or order
  or agree to the institution of patent litigation against any entity
  (including a cross-claim or counterclaim in a lawsuit) alleging that
  THIS IMPLEMENTATION constitutes direct or contributory patent
  infringement, or inducement of patent infringement, then any rights
  granted to you under this License shall terminate as of the date
  such litigation is filed.  If you or your agent or exclusive
  licensee institute or order or agree to the institution of a PATENT
  CHALLENGE, then Tokutek may terminate any rights granted to you
  under this License.
*/

#ident "Copyright (c) 2007-2013 Tokutek Inc.  All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."

#include "ft-cachetable-wrappers.h"
#include "ft-flusher.h"
#include "ft-internal.h"
#include "ft.h"
#include "node.h"
#include "fttypes.h"
#include "ule.h"

// dummymsn needed to simulate msn because messages are injected at a lower level than toku_ft_root_put_msg()
#define MIN_DUMMYMSN ((MSN) {(uint64_t)1 << 62})
static MSN dummymsn;
static int testsetup_initialized = 0;

// Must be called before any other test_setup_xxx() functions are called.
void
toku_testsetup_initialize(void) {
    if (testsetup_initialized == 0) {
        testsetup_initialized = 1;
        dummymsn = MIN_DUMMYMSN;
    }
}

static MSN
next_dummymsn(void) {
    ++(dummymsn.msn);
    return dummymsn;
}

bool ignore_if_was_already_open;
int toku_testsetup_leaf(FT_HANDLE ft_handle, BLOCKNUM *blocknum, int n_children, char **keys, int *keylens) {
    FTNODE node;
    assert(testsetup_initialized);
    toku_create_new_ftnode(ft_handle, &node, 0, n_children);
    for (int i = 0; i < n_children; i++) {
        BP_STATE(node, i) = PT_AVAIL;
    }

    DBT *XMALLOC_N(n_children - 1, pivotkeys);
    for (int i = 0; i + 1 < n_children; i++) {
        toku_memdup_dbt(&pivotkeys[i], keys[i], keylens[i]);
    }
    node->pivotkeys.create_from_dbts(pivotkeys, n_children - 1);

    *blocknum = node->blocknum;
    toku_unpin_ftnode(ft_handle->ft, node);
    return 0;
}

// Don't bother to clean up carefully if something goes wrong.  (E.g., it's OK to have malloced stuff that hasn't been freed.)
int toku_testsetup_nonleaf (FT_HANDLE ft_handle, int height, BLOCKNUM *blocknum, int n_children, BLOCKNUM *children, char **keys, int *keylens) {
    FTNODE node;
    assert(testsetup_initialized);
    toku_create_new_ftnode(ft_handle, &node, height, n_children);
    for (int i = 0; i < n_children; i++) {
        BP_BLOCKNUM(node, i) = children[i];
        BP_STATE(node,i) = PT_AVAIL;
    }
    DBT *XMALLOC_N(n_children - 1, pivotkeys);
    for (int i = 0; i + 1 < n_children; i++) {
        toku_memdup_dbt(&pivotkeys[i], keys[i], keylens[i]);
    }
    node->pivotkeys.create_from_dbts(pivotkeys, n_children - 1);
    *blocknum = node->blocknum;
    toku_unpin_ftnode(ft_handle->ft, node);
    return 0;
}

int toku_testsetup_root(FT_HANDLE ft_handle, BLOCKNUM blocknum) {
    assert(testsetup_initialized);
    ft_handle->ft->h->root_blocknum = blocknum;
    return 0;
}

int toku_testsetup_get_sersize(FT_HANDLE ft_handle, BLOCKNUM diskoff) // Return the size on disk
{
    assert(testsetup_initialized);
    void *node_v;
    struct ftnode_fetch_extra bfe;
    fill_bfe_for_full_read(&bfe, ft_handle->ft);
    int r  = toku_cachetable_get_and_pin(
        ft_handle->ft->cf, diskoff,
        toku_cachetable_hash(ft_handle->ft->cf, diskoff),
        &node_v,
        NULL,
        get_write_callbacks_for_node(ft_handle->ft),
        toku_ftnode_fetch_callback,
        toku_ftnode_pf_req_callback,
        toku_ftnode_pf_callback,
        true,
        &bfe
        );
    assert(r==0);
    FTNODE CAST_FROM_VOIDP(node, node_v);
    int size = toku_serialize_ftnode_size(node);
    toku_unpin_ftnode(ft_handle->ft, node);
    return size;
}

int toku_testsetup_insert_to_leaf (FT_HANDLE ft_handle, BLOCKNUM blocknum, const char *key, int keylen, const char *val, int vallen) {
    void *node_v;
    int r;

    assert(testsetup_initialized);

    struct ftnode_fetch_extra bfe;
    fill_bfe_for_full_read(&bfe, ft_handle->ft);
    r = toku_cachetable_get_and_pin(
        ft_handle->ft->cf,
        blocknum,
        toku_cachetable_hash(ft_handle->ft->cf, blocknum),
        &node_v,
        NULL,
        get_write_callbacks_for_node(ft_handle->ft),
	toku_ftnode_fetch_callback,
        toku_ftnode_pf_req_callback,
        toku_ftnode_pf_callback,
        true,
	&bfe
	);
    if (r!=0) return r;
    FTNODE CAST_FROM_VOIDP(node, node_v);
    toku_verify_or_set_counts(node);
    assert(node->height==0);

    DBT keydbt,valdbt;
    MSN msn = next_dummymsn();
    FT_MSG_S msg = { FT_INSERT, msn, xids_get_root_xids(),
                     .u = { .id = { toku_fill_dbt(&keydbt, key, keylen),
                                    toku_fill_dbt(&valdbt, val, vallen) } } };

    static size_t zero_flow_deltas[] = { 0, 0 };
    txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, true);
    toku_ftnode_put_msg(
        ft_handle->ft->compare_fun,
        ft_handle->ft->update_fun,
        &ft_handle->ft->cmp_descriptor,
        node,
        -1,
        &msg,
        true,
        &gc_info,
        zero_flow_deltas,
        NULL
        );

    toku_verify_or_set_counts(node);

    toku_unpin_ftnode(ft_handle->ft, node);
    return 0;
}

static int
testhelper_string_key_cmp(DB *UU(e), const DBT *a, const DBT *b)
{
    char *CAST_FROM_VOIDP(s, a->data), *CAST_FROM_VOIDP(t, b->data);
    return strcmp(s, t);
}

void
toku_pin_node_with_min_bfe(FTNODE* node, BLOCKNUM b, FT_HANDLE t)
{
    struct ftnode_fetch_extra bfe;
    fill_bfe_for_min_read(&bfe, t->ft);
    toku_pin_ftnode(
        t->ft,
        b,
        toku_cachetable_hash(t->ft->cf, b),
        &bfe,
        PL_WRITE_EXPENSIVE,
        node,
        true
        );
}

int toku_testsetup_insert_to_nonleaf (FT_HANDLE ft_handle, BLOCKNUM blocknum, enum ft_msg_type msgtype, const char *key, int keylen, const char *val, int vallen) {
    void *node_v;
    int r;

    assert(testsetup_initialized);

    struct ftnode_fetch_extra bfe;
    fill_bfe_for_full_read(&bfe, ft_handle->ft);
    r = toku_cachetable_get_and_pin(
        ft_handle->ft->cf,
        blocknum,
        toku_cachetable_hash(ft_handle->ft->cf, blocknum),
        &node_v,
        NULL,
        get_write_callbacks_for_node(ft_handle->ft),
	toku_ftnode_fetch_callback,
        toku_ftnode_pf_req_callback,
        toku_ftnode_pf_callback,
        true,
	&bfe
        );
    if (r!=0) return r;
    FTNODE CAST_FROM_VOIDP(node, node_v);
    assert(node->height>0);

    DBT k;
    int childnum = toku_ftnode_which_child(node,
                                            toku_fill_dbt(&k, key, keylen),
                                            &ft_handle->ft->cmp_descriptor, ft_handle->ft->compare_fun);

    XIDS xids_0 = xids_get_root_xids();
    MSN msn = next_dummymsn();
    toku_bnc_insert_msg(BNC(node, childnum), key, keylen, val, vallen, msgtype, msn, xids_0, true, NULL, testhelper_string_key_cmp);
    // Hack to get the test working. The problem is that this test
    // is directly queueing something in a FIFO instead of
    // using ft APIs.
    node->max_msn_applied_to_node_on_disk = msn;
    node->dirty = 1;
    // Also hack max_msn_in_ft
    ft_handle->ft->h->max_msn_in_ft = msn;

    toku_unpin_ftnode(ft_handle->ft, node);
    return 0;
}
<commit_msg>fix leak in ft-test-helpers.cc<commit_after>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
/*
COPYING CONDITIONS NOTICE:

  This program is free software; you can redistribute it and/or modify
  it under the terms of version 2 of the GNU General Public License as
  published by the Free Software Foundation, and provided that the
  following conditions are met:

      * Redistributions of source code must retain this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below).

      * Redistributions in binary form must reproduce this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below) in the documentation and/or other materials
        provided with the distribution.

  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., 51 Franklin Street, Fifth Floor, Boston, MA
  02110-1301, USA.

COPYRIGHT NOTICE:

  TokuDB, Tokutek Fractal Tree Indexing Library.
  Copyright (C) 2007-2013 Tokutek, Inc.

DISCLAIMER:

  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.

UNIVERSITY PATENT NOTICE:

  The technology is licensed by the Massachusetts Institute of
  Technology, Rutgers State University of New Jersey, and the Research
  Foundation of State University of New York at Stony Brook under
  United States of America Serial No. 11/760379 and to the patents
  and/or patent applications resulting from it.

PATENT MARKING NOTICE:

  This software is covered by US Patent No. 8,185,551.
  This software is covered by US Patent No. 8,489,638.

PATENT RIGHTS GRANT:

  "THIS IMPLEMENTATION" means the copyrightable works distributed by
  Tokutek as part of the Fractal Tree project.

  "PATENT CLAIMS" means the claims of patents that are owned or
  licensable by Tokutek, both currently or in the future; and that in
  the absence of this license would be infringed by THIS
  IMPLEMENTATION or by using or running THIS IMPLEMENTATION.

  "PATENT CHALLENGE" shall mean a challenge to the validity,
  patentability, enforceability and/or non-infringement of any of the
  PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.

  Tokutek hereby grants to you, for the term and geographical scope of
  the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
  irrevocable (except as stated in this section) patent license to
  make, have made, use, offer to sell, sell, import, transfer, and
  otherwise run, modify, and propagate the contents of THIS
  IMPLEMENTATION, where such license applies only to the PATENT
  CLAIMS.  This grant does not include claims that would be infringed
  only as a consequence of further modifications of THIS
  IMPLEMENTATION.  If you or your agent or licensee institute or order
  or agree to the institution of patent litigation against any entity
  (including a cross-claim or counterclaim in a lawsuit) alleging that
  THIS IMPLEMENTATION constitutes direct or contributory patent
  infringement, or inducement of patent infringement, then any rights
  granted to you under this License shall terminate as of the date
  such litigation is filed.  If you or your agent or exclusive
  licensee institute or order or agree to the institution of a PATENT
  CHALLENGE, then Tokutek may terminate any rights granted to you
  under this License.
*/

#ident "Copyright (c) 2007-2013 Tokutek Inc.  All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."

#include "ft-cachetable-wrappers.h"
#include "ft-flusher.h"
#include "ft-internal.h"
#include "ft.h"
#include "node.h"
#include "fttypes.h"
#include "ule.h"

// dummymsn needed to simulate msn because messages are injected at a lower level than toku_ft_root_put_msg()
#define MIN_DUMMYMSN ((MSN) {(uint64_t)1 << 62})
static MSN dummymsn;
static int testsetup_initialized = 0;

// Must be called before any other test_setup_xxx() functions are called.
void
toku_testsetup_initialize(void) {
    if (testsetup_initialized == 0) {
        testsetup_initialized = 1;
        dummymsn = MIN_DUMMYMSN;
    }
}

static MSN
next_dummymsn(void) {
    ++(dummymsn.msn);
    return dummymsn;
}

bool ignore_if_was_already_open;
int toku_testsetup_leaf(FT_HANDLE ft_handle, BLOCKNUM *blocknum, int n_children, char **keys, int *keylens) {
    FTNODE node;
    assert(testsetup_initialized);
    toku_create_new_ftnode(ft_handle, &node, 0, n_children);
    for (int i = 0; i < n_children; i++) {
        BP_STATE(node, i) = PT_AVAIL;
    }

    DBT *XMALLOC_N(n_children - 1, pivotkeys);
    for (int i = 0; i + 1 < n_children; i++) {
        toku_memdup_dbt(&pivotkeys[i], keys[i], keylens[i]);
    }
    node->pivotkeys.create_from_dbts(pivotkeys, n_children - 1);
    toku_free(pivotkeys);

    *blocknum = node->blocknum;
    toku_unpin_ftnode(ft_handle->ft, node);
    return 0;
}

// Don't bother to clean up carefully if something goes wrong.  (E.g., it's OK to have malloced stuff that hasn't been freed.)
int toku_testsetup_nonleaf (FT_HANDLE ft_handle, int height, BLOCKNUM *blocknum, int n_children, BLOCKNUM *children, char **keys, int *keylens) {
    FTNODE node;
    assert(testsetup_initialized);
    toku_create_new_ftnode(ft_handle, &node, height, n_children);
    for (int i = 0; i < n_children; i++) {
        BP_BLOCKNUM(node, i) = children[i];
        BP_STATE(node,i) = PT_AVAIL;
    }
    DBT *XMALLOC_N(n_children - 1, pivotkeys);
    for (int i = 0; i + 1 < n_children; i++) {
        toku_memdup_dbt(&pivotkeys[i], keys[i], keylens[i]);
    }
    node->pivotkeys.create_from_dbts(pivotkeys, n_children - 1);
    *blocknum = node->blocknum;
    toku_unpin_ftnode(ft_handle->ft, node);
    return 0;
}

int toku_testsetup_root(FT_HANDLE ft_handle, BLOCKNUM blocknum) {
    assert(testsetup_initialized);
    ft_handle->ft->h->root_blocknum = blocknum;
    return 0;
}

int toku_testsetup_get_sersize(FT_HANDLE ft_handle, BLOCKNUM diskoff) // Return the size on disk
{
    assert(testsetup_initialized);
    void *node_v;
    struct ftnode_fetch_extra bfe;
    fill_bfe_for_full_read(&bfe, ft_handle->ft);
    int r  = toku_cachetable_get_and_pin(
        ft_handle->ft->cf, diskoff,
        toku_cachetable_hash(ft_handle->ft->cf, diskoff),
        &node_v,
        NULL,
        get_write_callbacks_for_node(ft_handle->ft),
        toku_ftnode_fetch_callback,
        toku_ftnode_pf_req_callback,
        toku_ftnode_pf_callback,
        true,
        &bfe
        );
    assert(r==0);
    FTNODE CAST_FROM_VOIDP(node, node_v);
    int size = toku_serialize_ftnode_size(node);
    toku_unpin_ftnode(ft_handle->ft, node);
    return size;
}

int toku_testsetup_insert_to_leaf (FT_HANDLE ft_handle, BLOCKNUM blocknum, const char *key, int keylen, const char *val, int vallen) {
    void *node_v;
    int r;

    assert(testsetup_initialized);

    struct ftnode_fetch_extra bfe;
    fill_bfe_for_full_read(&bfe, ft_handle->ft);
    r = toku_cachetable_get_and_pin(
        ft_handle->ft->cf,
        blocknum,
        toku_cachetable_hash(ft_handle->ft->cf, blocknum),
        &node_v,
        NULL,
        get_write_callbacks_for_node(ft_handle->ft),
	toku_ftnode_fetch_callback,
        toku_ftnode_pf_req_callback,
        toku_ftnode_pf_callback,
        true,
	&bfe
	);
    if (r!=0) return r;
    FTNODE CAST_FROM_VOIDP(node, node_v);
    toku_verify_or_set_counts(node);
    assert(node->height==0);

    DBT keydbt,valdbt;
    MSN msn = next_dummymsn();
    FT_MSG_S msg = { FT_INSERT, msn, xids_get_root_xids(),
                     .u = { .id = { toku_fill_dbt(&keydbt, key, keylen),
                                    toku_fill_dbt(&valdbt, val, vallen) } } };

    static size_t zero_flow_deltas[] = { 0, 0 };
    txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, true);
    toku_ftnode_put_msg(
        ft_handle->ft->compare_fun,
        ft_handle->ft->update_fun,
        &ft_handle->ft->cmp_descriptor,
        node,
        -1,
        &msg,
        true,
        &gc_info,
        zero_flow_deltas,
        NULL
        );

    toku_verify_or_set_counts(node);

    toku_unpin_ftnode(ft_handle->ft, node);
    return 0;
}

static int
testhelper_string_key_cmp(DB *UU(e), const DBT *a, const DBT *b)
{
    char *CAST_FROM_VOIDP(s, a->data), *CAST_FROM_VOIDP(t, b->data);
    return strcmp(s, t);
}

void
toku_pin_node_with_min_bfe(FTNODE* node, BLOCKNUM b, FT_HANDLE t)
{
    struct ftnode_fetch_extra bfe;
    fill_bfe_for_min_read(&bfe, t->ft);
    toku_pin_ftnode(
        t->ft,
        b,
        toku_cachetable_hash(t->ft->cf, b),
        &bfe,
        PL_WRITE_EXPENSIVE,
        node,
        true
        );
}

int toku_testsetup_insert_to_nonleaf (FT_HANDLE ft_handle, BLOCKNUM blocknum, enum ft_msg_type msgtype, const char *key, int keylen, const char *val, int vallen) {
    void *node_v;
    int r;

    assert(testsetup_initialized);

    struct ftnode_fetch_extra bfe;
    fill_bfe_for_full_read(&bfe, ft_handle->ft);
    r = toku_cachetable_get_and_pin(
        ft_handle->ft->cf,
        blocknum,
        toku_cachetable_hash(ft_handle->ft->cf, blocknum),
        &node_v,
        NULL,
        get_write_callbacks_for_node(ft_handle->ft),
	toku_ftnode_fetch_callback,
        toku_ftnode_pf_req_callback,
        toku_ftnode_pf_callback,
        true,
	&bfe
        );
    if (r!=0) return r;
    FTNODE CAST_FROM_VOIDP(node, node_v);
    assert(node->height>0);

    DBT k;
    int childnum = toku_ftnode_which_child(node,
                                            toku_fill_dbt(&k, key, keylen),
                                            &ft_handle->ft->cmp_descriptor, ft_handle->ft->compare_fun);

    XIDS xids_0 = xids_get_root_xids();
    MSN msn = next_dummymsn();
    toku_bnc_insert_msg(BNC(node, childnum), key, keylen, val, vallen, msgtype, msn, xids_0, true, NULL, testhelper_string_key_cmp);
    // Hack to get the test working. The problem is that this test
    // is directly queueing something in a FIFO instead of
    // using ft APIs.
    node->max_msn_applied_to_node_on_disk = msn;
    node->dirty = 1;
    // Also hack max_msn_in_ft
    ft_handle->ft->h->max_msn_in_ft = msn;

    toku_unpin_ftnode(ft_handle->ft, node);
    return 0;
}
<|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
/*======
This file is part of PerconaFT.

Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.

    PerconaFT is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License, version 2,
    as published by the Free Software Foundation.

    PerconaFT 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 PerconaFT.  If not, see <http://www.gnu.org/licenses/>.

----------------------------------------

    PerconaFT is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License, version 3,
    as published by the Free Software Foundation.

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

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

#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."

#include "test.h"

// create and close, making sure that everything is deallocated properly.

int
test_main (int argc __attribute__((__unused__)),
	  const char *argv[] __attribute__((__unused__))) {
    int r;
    char logname[TOKU_PATH_MAX+1];
    toku_os_recursive_delete(TOKU_TEST_FILENAME);
    r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU);                               assert(r==0);
    TOKULOGGER logger;
    r = toku_logger_create(&logger);                                 assert(r == 0);
    r = toku_logger_open(TOKU_TEST_FILENAME, logger);                             assert(r == 0);

    {
	ml_lock(&logger->input_lock);
	toku_logger_make_space_in_inbuf(logger, 5);
	snprintf(logger->inbuf.buf+logger->inbuf.n_in_buf, 5, "a1234");
	logger->inbuf.n_in_buf+=5;
	logger->lsn.lsn++;
	logger->inbuf.max_lsn_in_buf = logger->lsn;
	ml_unlock(&logger->input_lock);
    }

    r = toku_logger_close(&logger);                                  assert(r == 0);
    {
        toku_struct_stat statbuf;
        sprintf(logname,
                "%s/log000000000000.tokulog%d",
                TOKU_TEST_FILENAME,
                TOKU_LOG_VERSION);
        r = toku_stat(logname, &statbuf, toku_uninstrumented);
        assert(r == 0);
        assert(statbuf.st_size == 12 + 5);
    }
    toku_os_recursive_delete(TOKU_TEST_FILENAME);
    return 0;
}
<commit_msg>avoid gcc7 warning about truncated snprintf format strings<commit_after>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
/*======
This file is part of PerconaFT.

Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.

    PerconaFT is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License, version 2,
    as published by the Free Software Foundation.

    PerconaFT 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 PerconaFT.  If not, see <http://www.gnu.org/licenses/>.

----------------------------------------

    PerconaFT is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License, version 3,
    as published by the Free Software Foundation.

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

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

#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."

#include "test.h"

// create and close, making sure that everything is deallocated properly.

int
test_main (int argc __attribute__((__unused__)),
	  const char *argv[] __attribute__((__unused__))) {
    int r;
    char logname[TOKU_PATH_MAX+1];
    toku_os_recursive_delete(TOKU_TEST_FILENAME);
    r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU);                               assert(r==0);
    TOKULOGGER logger;
    r = toku_logger_create(&logger);                                 assert(r == 0);
    r = toku_logger_open(TOKU_TEST_FILENAME, logger);                             assert(r == 0);

    {
	ml_lock(&logger->input_lock);
	toku_logger_make_space_in_inbuf(logger, 5);
	memcpy(logger->inbuf.buf+logger->inbuf.n_in_buf, "a1234", 5);
	logger->inbuf.n_in_buf+=5;
	logger->lsn.lsn++;
	logger->inbuf.max_lsn_in_buf = logger->lsn;
	ml_unlock(&logger->input_lock);
    }

    r = toku_logger_close(&logger);                                  assert(r == 0);
    {
        toku_struct_stat statbuf;
        sprintf(logname,
                "%s/log000000000000.tokulog%d",
                TOKU_TEST_FILENAME,
                TOKU_LOG_VERSION);
        r = toku_stat(logname, &statbuf, toku_uninstrumented);
        assert(r == 0);
        assert(statbuf.st_size == 12 + 5);
    }
    toku_os_recursive_delete(TOKU_TEST_FILENAME);
    return 0;
}
<|endoftext|>


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

/// \author Bence Magyar

#include <algorithm>
#include <cmath>

#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>

#include <gtest/gtest.h>

#include <ros/ros.h>

#include <geometry_msgs/Twist.h>
#include <nav_msgs/Odometry.h>
#include <tf/tf.h>

// Floating-point value comparison threshold
const double EPS = 0.01;

class DiffDriveControllerTest : public ::testing::Test
{
public:

  DiffDriveControllerTest()
    : cmd_pub(nh.advertise<geometry_msgs::Twist>("/cmd_vel", 10)),
      odom_sub(nh.subscribe("/odom", 10, &DiffDriveControllerTest::odomCallback, this))
  {
  }

  ~DiffDriveControllerTest()
  {
    odom_sub.shutdown();
  }

  nav_msgs::Odometry getLastOdom(){ return last_odom; }
  void publish(geometry_msgs::Twist cmd_vel){ cmd_pub.publish(cmd_vel); }

private:
  ros::NodeHandle nh;
  ros::Publisher cmd_pub;
  ros::Subscriber odom_sub;
  nav_msgs::Odometry last_odom;

  void odomCallback(const nav_msgs::Odometry& odom)
  {
    std::cerr << "Callback reveived: pos.x: " << odom.pose.pose.position.x <<
              ", orient.z: " << odom.pose.pose.orientation.z << std::endl;
    last_odom = odom;
  }

};

// TEST CASES

btQuaternion btQuatFromGeomQuat(const geometry_msgs::Quaternion& quat)
{
  return btQuaternion(quat.x, quat.y, quat.z, quat.w);
}

TEST_F(DiffDriveControllerTest, testForward)
{
  ros::Duration(0.5).sleep();
  // get initial odom
  nav_msgs::Odometry old_odom = getLastOdom();
  // send a velocity command of 0.1 m/s
  geometry_msgs::Twist cmd_vel;
  cmd_vel.linear.x = 0.1;
  publish(cmd_vel);
  // wait for 10s
  ros::Duration(10.0).sleep();

  nav_msgs::Odometry new_odom = getLastOdom();

  // check if the robot travelled 1 meter in x, changes in the other fields should be ~~0
  EXPECT_LT(fabs(new_odom.pose.pose.position.x - old_odom.pose.pose.position.x), 1.0 + EPS);
  EXPECT_GT(fabs(new_odom.pose.pose.position.x - old_odom.pose.pose.position.x), 1.0 - EPS);
  EXPECT_LT(fabs(new_odom.pose.pose.position.y - old_odom.pose.pose.position.y), EPS);
  EXPECT_LT(fabs(new_odom.pose.pose.position.z - old_odom.pose.pose.position.z), EPS);

  // convert to rpy and test that way
  double roll_old, pitch_old, yaw_old;
  double roll_new, pitch_new, yaw_new;
  tf::Matrix3x3(btQuatFromGeomQuat(old_odom.pose.pose.orientation)).getRPY(roll_old, pitch_old, yaw_old);
  tf::Matrix3x3(btQuatFromGeomQuat(new_odom.pose.pose.orientation)).getRPY(roll_new, pitch_new, yaw_new);
  EXPECT_LT(fabs(roll_new - roll_old), EPS);
  EXPECT_LT(fabs(pitch_new - pitch_old), EPS);
  EXPECT_LT(fabs(yaw_new - yaw_old), EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.linear.x - old_odom.twist.twist.linear.x), 0.1 + EPS);
  EXPECT_GT(fabs(new_odom.twist.twist.linear.x - old_odom.twist.twist.linear.x), 0.1 - EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.linear.y - old_odom.twist.twist.linear.y), EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.linear.z - old_odom.twist.twist.linear.z), EPS);

  EXPECT_LT(fabs(new_odom.twist.twist.angular.x - old_odom.twist.twist.angular.x), EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.angular.y - old_odom.twist.twist.angular.y), EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.angular.z - old_odom.twist.twist.angular.z), EPS);
}

TEST_F(DiffDriveControllerTest, testTurn)
{
  ros::Duration(0.5).sleep();
  // get initial odom
  nav_msgs::Odometry old_odom = getLastOdom();
  // send a velocity command
  geometry_msgs::Twist cmd_vel;
  cmd_vel.angular.z = M_PI/10.0;
  publish(cmd_vel);
  // wait for 10s
  ros::Duration(10.0).sleep();

  nav_msgs::Odometry new_odom = getLastOdom();

  // check if the robot rotated PI around z, changes in the other fields should be ~~0
  EXPECT_LT(fabs(new_odom.pose.pose.position.x - old_odom.pose.pose.position.x), EPS);
  EXPECT_LT(fabs(new_odom.pose.pose.position.y - old_odom.pose.pose.position.y), EPS);
  EXPECT_LT(fabs(new_odom.pose.pose.position.z - old_odom.pose.pose.position.z), EPS);

  // convert to rpy and test that way
  double roll_old, pitch_old, yaw_old;
  double roll_new, pitch_new, yaw_new;
  tf::Matrix3x3(btQuatFromGeomQuat(old_odom.pose.pose.orientation)).getRPY(roll_old, pitch_old, yaw_old);
  tf::Matrix3x3(btQuatFromGeomQuat(new_odom.pose.pose.orientation)).getRPY(roll_new, pitch_new, yaw_new);
  EXPECT_LT(fabs(roll_new - roll_old), EPS);
  EXPECT_LT(fabs(pitch_new - pitch_old), EPS);
  EXPECT_LT(fabs(yaw_new - yaw_old), M_PI + EPS);
  EXPECT_GT(fabs(yaw_new - yaw_old), M_PI - EPS);

  EXPECT_LT(fabs(new_odom.twist.twist.linear.x - old_odom.twist.twist.linear.x), EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.linear.y - old_odom.twist.twist.linear.y), EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.linear.z - old_odom.twist.twist.linear.z), EPS);

  EXPECT_LT(fabs(new_odom.twist.twist.angular.x - old_odom.twist.twist.angular.x), EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.angular.y - old_odom.twist.twist.angular.y), EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.angular.z - old_odom.twist.twist.angular.z), M_PI/10.0 + EPS);
  EXPECT_GT(fabs(new_odom.twist.twist.angular.z - old_odom.twist.twist.angular.z), M_PI/10.0 - EPS);
}

int main(int argc, char** argv)
{
  testing::InitGoogleTest(&argc, argv);
  ros::init(argc, argv, "diff_drive_test");

  ros::AsyncSpinner spinner(1);
  spinner.start();
  //ros::Duration(0.5).sleep();
  int ret = RUN_ALL_TESTS();
  spinner.stop();
  ros::shutdown();
  return ret;
}
<commit_msg>Changed checks on twist fields. Not interested in the difference but the final value of those fields. Checking for those.<commit_after>///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2013, PAL Robotics S.L.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//   * Neither the name of hiDOF, Inc. nor the names of its
//     contributors may be used to endorse or promote products derived from
//     this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//////////////////////////////////////////////////////////////////////////////

/// \author Bence Magyar

#include <algorithm>
#include <cmath>

#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>

#include <gtest/gtest.h>

#include <ros/ros.h>

#include <geometry_msgs/Twist.h>
#include <nav_msgs/Odometry.h>
#include <tf/tf.h>

// Floating-point value comparison threshold
const double EPS = 0.02;

class DiffDriveControllerTest : public ::testing::Test
{
public:

  DiffDriveControllerTest()
    : cmd_pub(nh.advertise<geometry_msgs::Twist>("/cmd_vel", 1000)),
      odom_sub(nh.subscribe("/odom", 1000, &DiffDriveControllerTest::odomCallback, this))
  {
  }

  ~DiffDriveControllerTest()
  {
    odom_sub.shutdown();
  }

  nav_msgs::Odometry getLastOdom(){ return last_odom; }
  void publish(geometry_msgs::Twist cmd_vel){ cmd_pub.publish(cmd_vel); }
  bool isControllerAlive(){ return (odom_sub.getNumPublishers() > 0) && (cmd_pub.getNumSubscribers() > 0); }

private:
  ros::NodeHandle nh;
  ros::Publisher cmd_pub;
  ros::Subscriber odom_sub;
  nav_msgs::Odometry last_odom;

  void odomCallback(const nav_msgs::Odometry& odom)
  {
    std::cerr << "Callback reveived: pos.x: " << odom.pose.pose.position.x
              << ", orient.z: " << odom.pose.pose.orientation.z
              << ", lin_est: " << odom.twist.twist.linear.x
              << ", ang_est: " << odom.twist.twist.angular.z << std::endl;
    last_odom = odom;
  }
};

btQuaternion btQuatFromGeomQuat(const geometry_msgs::Quaternion& quat)
{
  return btQuaternion(quat.x, quat.y, quat.z, quat.w);
}

// TEST CASES
TEST_F(DiffDriveControllerTest, testForward)
{
  // wait for ROS
  while(!isControllerAlive())
  {
    std::cerr << ".";
    ros::Duration(0.1).sleep();
  }
  std::cerr << std::endl << "Odom published, diff_drive controller is alive" << std::endl;
  // zero everything before test
  geometry_msgs::Twist cmd_vel;
  cmd_vel.linear.x = 0.0;
  cmd_vel.angular.z = 0.0;
  publish(cmd_vel);
  ros::Duration(0.1).sleep();
  // get initial odom
  nav_msgs::Odometry old_odom = getLastOdom();
  // send a velocity command of 0.1 m/s
  cmd_vel.linear.x = 0.1;
  publish(cmd_vel);
  // wait for 10s
  ros::Duration(10.0).sleep();

  nav_msgs::Odometry new_odom = getLastOdom();

  // check if the robot travelled 1 meter in x, changes in the other fields should be ~~0
  EXPECT_NEAR(fabs(new_odom.pose.pose.position.x - old_odom.pose.pose.position.x), 1.0, EPS);
  EXPECT_LT(fabs(new_odom.pose.pose.position.y - old_odom.pose.pose.position.y), EPS);
  EXPECT_LT(fabs(new_odom.pose.pose.position.z - old_odom.pose.pose.position.z), EPS);

  // convert to rpy and test that way
  double roll_old, pitch_old, yaw_old;
  double roll_new, pitch_new, yaw_new;
  tf::Matrix3x3(btQuatFromGeomQuat(old_odom.pose.pose.orientation)).getRPY(roll_old, pitch_old, yaw_old);
  tf::Matrix3x3(btQuatFromGeomQuat(new_odom.pose.pose.orientation)).getRPY(roll_new, pitch_new, yaw_new);
  EXPECT_LT(fabs(roll_new - roll_old), EPS);
  EXPECT_LT(fabs(pitch_new - pitch_old), EPS);
  EXPECT_LT(fabs(yaw_new - yaw_old), EPS);
  EXPECT_NEAR(fabs(new_odom.twist.twist.linear.x), 0.1, EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.linear.y), EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.linear.z), EPS);

  EXPECT_LT(fabs(new_odom.twist.twist.angular.x), EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.angular.y), EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.angular.z), EPS);

  std::cerr << "testForward ended" << std::endl;
}

TEST_F(DiffDriveControllerTest, testTurn)
{
  // wait for ROS
  while(!isControllerAlive())
  {
    std::cerr << ".";
    ros::Duration(0.1).sleep();
  }
  std::cerr << std::endl << "Odom published, diff_drive controller is alive" << std::endl;
  // zero everything before test
  geometry_msgs::Twist cmd_vel;
  cmd_vel.linear.x = 0.0;
  cmd_vel.angular.z = 0.0;
  publish(cmd_vel);
  ros::Duration(0.1).sleep();
  // get initial odom
  nav_msgs::Odometry old_odom = getLastOdom();
  // send a velocity command
  cmd_vel.angular.z = M_PI/10.0;
  publish(cmd_vel);
  // wait for 10s
  ros::Duration(10.0).sleep();

  nav_msgs::Odometry new_odom = getLastOdom();

  // check if the robot rotated PI around z, changes in the other fields should be ~~0
  EXPECT_LT(fabs(new_odom.pose.pose.position.x - old_odom.pose.pose.position.x), EPS);
  EXPECT_LT(fabs(new_odom.pose.pose.position.y - old_odom.pose.pose.position.y), EPS);
  EXPECT_LT(fabs(new_odom.pose.pose.position.z - old_odom.pose.pose.position.z), EPS);

  // convert to rpy and test that way
  double roll_old, pitch_old, yaw_old;
  double roll_new, pitch_new, yaw_new;
  tf::Matrix3x3(btQuatFromGeomQuat(old_odom.pose.pose.orientation)).getRPY(roll_old, pitch_old, yaw_old);
  tf::Matrix3x3(btQuatFromGeomQuat(new_odom.pose.pose.orientation)).getRPY(roll_new, pitch_new, yaw_new);
  EXPECT_LT(fabs(roll_new - roll_old), EPS);
  EXPECT_LT(fabs(pitch_new - pitch_old), EPS);
  EXPECT_NEAR(fabs(yaw_new - yaw_old), M_PI, EPS);

  EXPECT_LT(fabs(new_odom.twist.twist.linear.x), EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.linear.y), EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.linear.z), EPS);

  EXPECT_LT(fabs(new_odom.twist.twist.angular.x), EPS);
  EXPECT_LT(fabs(new_odom.twist.twist.angular.y), EPS);
  EXPECT_NEAR(fabs(new_odom.twist.twist.angular.z), M_PI/10.0, EPS);
}

int main(int argc, char** argv)
{
  testing::InitGoogleTest(&argc, argv);
  ros::init(argc, argv, "diff_drive_test");

  ros::AsyncSpinner spinner(1);
  spinner.start();
  //ros::Duration(0.5).sleep();
  int ret = RUN_ALL_TESTS();
  spinner.stop();
  ros::shutdown();
  return ret;
}
<|endoftext|>


<commit_before>#include <cmath>
#include <stdexcept>
#include <iostream>

#include "Galois.hpp"

using namespace aff3ct::tools;

Galois
::Galois(const int& K, const int& N, const int& m, const int& t)
 : K(K), N(N), m(m), t(t), d(2 * t + 1), alpha_to(N + 1), index_of(N + 1), p(m + 1, 0), g(N - K + 1)
{
	if (N >= 1048576) // 2^20
		throw std::invalid_argument("aff3ct::tools::Galois: \"N\" has to be smaller than 1048576.");

	if (m != (int)std::ceil(std::log2(N +1)))
		throw std::invalid_argument("aff3ct::tools::Galois: \"m\" has to be equal to \"log2(N +1)\".");

	if (N != ((1 << m) -1))
		throw std::invalid_argument("aff3ct::tools::Galois: \"N\" has to be a power of 2 minus 1.");

	Select_Polynomial();
	Generate_GF();
	Compute_BCH_Generator_Polynomial();
}

Galois
::~Galois()
{
}

void Galois
::Select_Polynomial()
{
	p[0] = p[m] = 1;
	if      (m ==  2) p[1] = 1;
	else if (m ==  3) p[1] = 1;
	else if (m ==  4) p[1] = 1;
	else if (m ==  5) p[2] = 1;
	else if (m ==  6) p[1] = 1;
	else if (m ==  7) p[1] = 1;
	else if (m ==  8) p[4] = p[5] = p[6] = 1;
	else if (m ==  9) p[4] = 1;
	else if (m == 10) p[3] = 1;
	else if (m == 11) p[2] = 1;
	else if (m == 12) p[3] = p[4] = p[7] = 1;
	else if (m == 13) p[1] = p[3] = p[4] = 1;
	else if (m == 14) p[1] = p[11] = p[12] = 1;
	else if (m == 15) p[1] = 1;
	else if (m == 16) p[2] = p[3] = p[5] = 1;
	else if (m == 17) p[3] = 1;
	else if (m == 18) p[7] = 1;
	else if (m == 19) p[1] = p[5] = p[6] = 1;
	else if (m == 20) p[3] = 1;
}

void Galois
::Generate_GF()
{
	register int i, mask;

	mask = 1;
	alpha_to[m] = 0;
	for (i = 0; i < m; i++)
	{
		alpha_to[i] = mask;
		index_of[alpha_to[i]] = i;
		if (p[i] != 0)
			alpha_to[m] ^= mask;
		mask <<= 1;
	}
	index_of[alpha_to[m]] = m;
	mask >>= 1;
	for (i = m + 1; i < N; i++)
	{
		if (alpha_to[i - 1] >= mask)
			alpha_to[i] = alpha_to[m] ^ ((alpha_to[i - 1] ^ mask) << 1);
		else
			alpha_to[i] = alpha_to[i - 1] << 1;
		const auto idx = alpha_to[i];
		index_of[idx] = i;
	}
	index_of[0] = -1;
}

void Galois
::Compute_BCH_Generator_Polynomial()
{
	register int ii, jj, ll, kaux;
	register int test, aux, nocycles, root, noterms, rdncy;
	int cycle[1024][21], size[1024], min[1024], zeros[1024];

	/* Generate cycle sets modulo n, n = 2**m - 1 */
	cycle[0][0] = 0;
	size[0] = 1;
	cycle[1][0] = 1;
	size[1] = 1;
	jj = 1; /* cycle set index */
	do
	{
		/* Generate the jj-th cycle set */
		ii = 0;
		do
		{
			ii++;
			cycle[jj][ii] = (cycle[jj][ii - 1] * 2) % N;
			size[jj]++;
			aux = (cycle[jj][ii] * 2) % N;
		}
		while (aux != cycle[jj][0]);
		/* Next cycle set representative */
		ll = 0;
		do
		{
			ll++;
			test = 0;
			for (ii = 1; ((ii <= jj) && (!test)); ii++)
				/* Examine previous cycle sets */
				for (kaux = 0; ((kaux < size[ii]) && (!test)); kaux++)
					if (ll == cycle[ii][kaux])
						test = 1;
		}
		while ((test) && (ll < (N - 1)));
		if (!(test))
		{
			jj++; /* next cycle set index */
			cycle[jj][0] = ll;
			size[jj] = 1;
		}
	}
	while (ll < (N - 1));
	nocycles = jj; /* number of cycle sets modulo n */

	//d = 2 * t + 1;

	/* Search for roots 1, 2, ..., d-1 in cycle sets */
	kaux = 0;
	rdncy = 0;
	for (ii = 1; ii <= nocycles; ii++)
	{
		min[kaux] = 0;
		test = 0;
		for (jj = 0; ((jj < size[ii]) && (!test)); jj++)
			for (root = 1; ((root < d) && (!test)); root++)
				if (root == cycle[ii][jj])
				{
					test = 1;
					min[kaux] = ii;
				}
		if (min[kaux])
		{
			rdncy += size[min[kaux]];
			kaux++;
		}
	}
	noterms = kaux;
	kaux = 1;
	for (ii = 0; ii < noterms; ii++)
		for (jj = 0; jj < size[min[ii]]; jj++)
		{
			zeros[kaux] = cycle[min[ii]][jj];
			kaux++;
		}

	if (K > N - rdncy)
		throw std::runtime_error("aff3ct::tools::Galois: \"K\" seems to be too big for this correction power \"t\".");

	/* Compute the generator polynomial */
	g[0] = alpha_to[zeros[1]];
	g[1] = 1; /* g(x) = (X + zeros[1]) initially */
	for (ii = 2; ii <= rdncy; ii++)
	{
		g[ii] = 1;
		for (jj = ii - 1; jj > 0; jj--)
			if (g[jj] != 0)
				g[jj] = g[jj - 1] ^ alpha_to[(index_of[g[jj]] + zeros[ii]) % N];
			else
				g[jj] = g[jj - 1];
		g[0] = alpha_to[(index_of[g[0]] + zeros[ii]) % N];
	}
}
<commit_msg>Remove the register keyword.<commit_after>#include <cmath>
#include <stdexcept>
#include <iostream>

#include "Galois.hpp"

using namespace aff3ct::tools;

Galois
::Galois(const int& K, const int& N, const int& m, const int& t)
 : K(K), N(N), m(m), t(t), d(2 * t + 1), alpha_to(N + 1), index_of(N + 1), p(m + 1, 0), g(N - K + 1)
{
	if (N >= 1048576) // 2^20
		throw std::invalid_argument("aff3ct::tools::Galois: \"N\" has to be smaller than 1048576.");

	if (m != (int)std::ceil(std::log2(N +1)))
		throw std::invalid_argument("aff3ct::tools::Galois: \"m\" has to be equal to \"log2(N +1)\".");

	if (N != ((1 << m) -1))
		throw std::invalid_argument("aff3ct::tools::Galois: \"N\" has to be a power of 2 minus 1.");

	Select_Polynomial();
	Generate_GF();
	Compute_BCH_Generator_Polynomial();
}

Galois
::~Galois()
{
}

void Galois
::Select_Polynomial()
{
	p[0] = p[m] = 1;
	if      (m ==  2) p[1] = 1;
	else if (m ==  3) p[1] = 1;
	else if (m ==  4) p[1] = 1;
	else if (m ==  5) p[2] = 1;
	else if (m ==  6) p[1] = 1;
	else if (m ==  7) p[1] = 1;
	else if (m ==  8) p[4] = p[5] = p[6] = 1;
	else if (m ==  9) p[4] = 1;
	else if (m == 10) p[3] = 1;
	else if (m == 11) p[2] = 1;
	else if (m == 12) p[3] = p[4] = p[7] = 1;
	else if (m == 13) p[1] = p[3] = p[4] = 1;
	else if (m == 14) p[1] = p[11] = p[12] = 1;
	else if (m == 15) p[1] = 1;
	else if (m == 16) p[2] = p[3] = p[5] = 1;
	else if (m == 17) p[3] = 1;
	else if (m == 18) p[7] = 1;
	else if (m == 19) p[1] = p[5] = p[6] = 1;
	else if (m == 20) p[3] = 1;
}

void Galois
::Generate_GF()
{
	int i, mask;

	mask = 1;
	alpha_to[m] = 0;
	for (i = 0; i < m; i++)
	{
		alpha_to[i] = mask;
		index_of[alpha_to[i]] = i;
		if (p[i] != 0)
			alpha_to[m] ^= mask;
		mask <<= 1;
	}
	index_of[alpha_to[m]] = m;
	mask >>= 1;
	for (i = m + 1; i < N; i++)
	{
		if (alpha_to[i - 1] >= mask)
			alpha_to[i] = alpha_to[m] ^ ((alpha_to[i - 1] ^ mask) << 1);
		else
			alpha_to[i] = alpha_to[i - 1] << 1;
		const auto idx = alpha_to[i];
		index_of[idx] = i;
	}
	index_of[0] = -1;
}

void Galois
::Compute_BCH_Generator_Polynomial()
{
	int ii, jj, ll, kaux;
	int test, aux, nocycles, root, noterms, rdncy;
	int cycle[1024][21], size[1024], min[1024], zeros[1024];

	/* Generate cycle sets modulo n, n = 2**m - 1 */
	cycle[0][0] = 0;
	size[0] = 1;
	cycle[1][0] = 1;
	size[1] = 1;
	jj = 1; /* cycle set index */
	do
	{
		/* Generate the jj-th cycle set */
		ii = 0;
		do
		{
			ii++;
			cycle[jj][ii] = (cycle[jj][ii - 1] * 2) % N;
			size[jj]++;
			aux = (cycle[jj][ii] * 2) % N;
		}
		while (aux != cycle[jj][0]);
		/* Next cycle set representative */
		ll = 0;
		do
		{
			ll++;
			test = 0;
			for (ii = 1; ((ii <= jj) && (!test)); ii++)
				/* Examine previous cycle sets */
				for (kaux = 0; ((kaux < size[ii]) && (!test)); kaux++)
					if (ll == cycle[ii][kaux])
						test = 1;
		}
		while ((test) && (ll < (N - 1)));
		if (!(test))
		{
			jj++; /* next cycle set index */
			cycle[jj][0] = ll;
			size[jj] = 1;
		}
	}
	while (ll < (N - 1));
	nocycles = jj; /* number of cycle sets modulo n */

	//d = 2 * t + 1;

	/* Search for roots 1, 2, ..., d-1 in cycle sets */
	kaux = 0;
	rdncy = 0;
	for (ii = 1; ii <= nocycles; ii++)
	{
		min[kaux] = 0;
		test = 0;
		for (jj = 0; ((jj < size[ii]) && (!test)); jj++)
			for (root = 1; ((root < d) && (!test)); root++)
				if (root == cycle[ii][jj])
				{
					test = 1;
					min[kaux] = ii;
				}
		if (min[kaux])
		{
			rdncy += size[min[kaux]];
			kaux++;
		}
	}
	noterms = kaux;
	kaux = 1;
	for (ii = 0; ii < noterms; ii++)
		for (jj = 0; jj < size[min[ii]]; jj++)
		{
			zeros[kaux] = cycle[min[ii]][jj];
			kaux++;
		}

	if (K > N - rdncy)
		throw std::runtime_error("aff3ct::tools::Galois: \"K\" seems to be too big for this correction power \"t\".");

	/* Compute the generator polynomial */
	g[0] = alpha_to[zeros[1]];
	g[1] = 1; /* g(x) = (X + zeros[1]) initially */
	for (ii = 2; ii <= rdncy; ii++)
	{
		g[ii] = 1;
		for (jj = ii - 1; jj > 0; jj--)
			if (g[jj] != 0)
				g[jj] = g[jj - 1] ^ alpha_to[(index_of[g[jj]] + zeros[ii]) % N];
			else
				g[jj] = g[jj - 1];
		g[0] = alpha_to[(index_of[g[0]] + zeros[ii]) % N];
	}
}
<|endoftext|>


<commit_before>#include "framework/logger.h"
#include "game/city/vehicle.h"
#include "game/city/weapon.h"
#include "game/tileview/projectile.h"
#include "game/organisation.h"
#include <cfloat>
#include <random>
#include <limits>

std::default_random_engine rng;

namespace OpenApoc {

class VehicleRandomWalk : public VehicleMission
{
public:
	std::uniform_int_distribution<int> distribution;
	VehicleRandomWalk(Vehicle &vehicle)
		: VehicleMission(vehicle), distribution(-1,1)
			{};
	virtual Vec3<float> getNextDestination()
	{
		TileMap &map = this->vehicle.tileObject->getOwningTile()->map;
		Vec3<int> nextPosition;
		int tries = 0;
		do {
			nextPosition = {vehicle.position.x, vehicle.position.y, vehicle.position.z};
			Vec3<int> diff {distribution(rng), distribution(rng), distribution(rng)};
			nextPosition += diff;
			//FIXME HACK - abort after some attempts (e.g. if we're completely trapped)
			//and just phase through whatever obstruction is there
			tries++;
			//Keep looping until we find an empty tile within the map
		} while (nextPosition.x >= map.size.x || nextPosition.x < 0 ||
			nextPosition.y >= map.size.y || nextPosition.y < 0 ||
			nextPosition.z >= map.size.z || nextPosition.z < 0
			//FIXME: Proper routing/obstruction handling
			//(This below could cause an infinite loop if a vehicle gets 'trapped'
			|| (tries < 50 && !map.getTile(nextPosition)->ownedObjects.empty()));
		return Vec3<float>{nextPosition.x, nextPosition.y, nextPosition.z};
	}
};

class VehicleRandomDestination : public VehicleMission
{
public:
	std::uniform_int_distribution<int> xydistribution;
	std::uniform_int_distribution<int> zdistribution;
	VehicleRandomDestination(Vehicle &v)
		: VehicleMission(v), xydistribution(0,99), zdistribution(0,9)
			{};
	std::list<Tile*> path;
	virtual Vec3<float> getNextDestination()
	{
		while (path.empty())
		{
			Vec3<int> newTarget = {xydistribution(rng), xydistribution(rng), zdistribution(rng)};
			while (!vehicle.tileObject->getOwningTile()->map.getTile(newTarget)->ownedObjects.empty())
				newTarget = {xydistribution(rng), xydistribution(rng), zdistribution(rng)};
			path = vehicle.tileObject->getOwningTile()->map.findShortestPath(vehicle.tileObject->getOwningTile()->position, newTarget);
			if (path.empty())
			{
				LogInfo("Failed to path - retrying");
				continue;
			}
			//Skip first in the path (as that's current tile)
			path.pop_front();
		}
		if (!path.front()->ownedObjects.empty())
		{
			Vec3<int> target = path.back()->position;
			path = vehicle.tileObject->getOwningTile()->map.findShortestPath(vehicle.tileObject->getOwningTile()->position, target);
			if (path.empty())
			{
				LogInfo("Failed to path after obstruction");
				path.clear();
				return this->getNextDestination();
			}
			//Skip first in the path (as that's current tile)
			path.pop_front();
		}
		Tile *nextTile = path.front();
		path.pop_front();
		return Vec3<float>{nextTile->position.x, nextTile->position.y, nextTile->position.z}
			//Add {0.5,0.5,0.5} to make it route to the center of the tile
			+ Vec3<float>{0.5,0.5,0.5};
	}

};

class FlyingVehicleMover : public VehicleMover
{
public:
	Vec3<float> goalPosition;
	float speed;
	FlyingVehicleMover(Vehicle &v, Vec3<float> initialGoal)
		: VehicleMover(v), goalPosition(initialGoal)
	{
		std::uniform_real_distribution<float> distribution(-0.02, 0.02);
		//Tweak the speed slightly, makes everything a little less synchronised
		speed = 0.05 + distribution(rng);
	}
	virtual void update(unsigned int ticks)
	{
		float distanceLeft = speed * ticks;
		while (distanceLeft > 0)
		{
			Vec3<float> vectorToGoal = goalPosition -
				vehicle.position;
			float distanceToGoal = glm::length(vectorToGoal);
			if (distanceToGoal <= distanceLeft)
			{
				distanceLeft -= distanceToGoal;
				vehicle.position = goalPosition;
				goalPosition = vehicle.mission->getNextDestination();
			}
			else
			{
				vehicle.direction = vectorToGoal;
				vehicle.position += distanceLeft * glm::normalize(vectorToGoal);
				distanceLeft = -1;
			}
		}
		for (auto &weapon : vehicle.weapons)
		{
			weapon->update(ticks);
			if (weapon->canFire())
			{
				//Find something to shoot at!
				//FIXME: Only run on 'aggressive'? And not already a manually-selected target?
				float range = weapon->getWeaponDef().range;
				//Find the closest enemy within the firing arc
				float closestEnemyRange = std::numeric_limits<float>::max();
				std::shared_ptr<VehicleTileObject> closestEnemy;
				for (auto obj : vehicle.tileObject->getOwningTile()->map.activeObjects)
				{
					auto vehicleObj = std::dynamic_pointer_cast<VehicleTileObject>(obj);
					if (!vehicleObj)
					{
						/* Not a vehicle, skip */
						continue;
					}
					auto &otherVehicle = vehicleObj->getVehicle();
					if (!vehicle.owner.isHostileTo(otherVehicle.owner))
					{
						/* Not hostile, skip */
						continue;
					}
					//FIXME: Check weapon arc against otherVehicle
					auto offset = vehicle.position - otherVehicle.position;
					float distance = offset.length();

					if (distance < closestEnemyRange)
					{
						closestEnemyRange = distance;
						closestEnemy = vehicleObj;
					}
				}

				if (closestEnemyRange <= range)
				{
					//Only fire if we're in range
					auto projectile = weapon->fire(closestEnemy->getPosition());
					if (projectile)
					{
						vehicle.tileObject->getOwningTile()->map.addObject(projectile);
					}
					else
					{
						LogWarning("Fire() produced no object");
					}
				}
			}
		}
	}
};

VehicleMission::VehicleMission(Vehicle &v)
	: vehicle(v)
{

}

VehicleMission::~VehicleMission()
{

}

VehicleMover::VehicleMover(Vehicle &v)
: vehicle(v)
{

}

VehicleMover::~VehicleMover()
{

}

Vehicle::Vehicle(const VehicleDefinition &def, Organisation &owner)
	: def(def), owner(owner)
{

}

Vehicle::~Vehicle()
{

}

void
Vehicle::launch(TileMap &map, Vec3<float> initialPosition)
{
	if (this->tileObject)
	{
		LogError("Trying to launch already-launched vehicle");
		return;
	}
	this->position = initialPosition;
	this->mover.reset(new FlyingVehicleMover(*this, initialPosition));
	this->mission.reset(new VehicleRandomDestination(*this));
	this->tileObject = std::make_shared<VehicleTileObject>(*this, map, initialPosition);
	map.addObject(this->tileObject);
}

VehicleTileObject::VehicleTileObject(Vehicle &vehicle, TileMap &map, Vec3<float> position)
	: TileObject(map, position),
	TileObjectDirectionalSprite(map, position, vehicle.def.directionalSprites),
	TileObjectCollidable(map, position, Vec3<int>{32,32,16}, vehicle.def.voxelMap),
	vehicle(vehicle)
{
	this->active = true;
}

VehicleTileObject::~VehicleTileObject()
{
}

void
VehicleTileObject::update(unsigned int ticks)
{
	if (this->vehicle.mover)
		this->vehicle.mover->update(ticks);
	//FIXME: Better way instead of mirroring pos/direction?
	this->setPosition(this->vehicle.position);
	this->setDirection(this->vehicle.direction);
}

Vec3<float> VehicleTileObject::getDrawPosition() const
{
	return this->getPosition() - Vec3<float>{2,1,1};
}

}; //namespace OpenApoc
<commit_msg>Fix 'closest enemy' calculation<commit_after>#include "framework/logger.h"
#include "game/city/vehicle.h"
#include "game/city/weapon.h"
#include "game/tileview/projectile.h"
#include "game/organisation.h"
#include <cfloat>
#include <random>
#include <limits>

std::default_random_engine rng;

namespace OpenApoc {

class VehicleRandomWalk : public VehicleMission
{
public:
	std::uniform_int_distribution<int> distribution;
	VehicleRandomWalk(Vehicle &vehicle)
		: VehicleMission(vehicle), distribution(-1,1)
			{};
	virtual Vec3<float> getNextDestination()
	{
		TileMap &map = this->vehicle.tileObject->getOwningTile()->map;
		Vec3<int> nextPosition;
		int tries = 0;
		do {
			nextPosition = {vehicle.position.x, vehicle.position.y, vehicle.position.z};
			Vec3<int> diff {distribution(rng), distribution(rng), distribution(rng)};
			nextPosition += diff;
			//FIXME HACK - abort after some attempts (e.g. if we're completely trapped)
			//and just phase through whatever obstruction is there
			tries++;
			//Keep looping until we find an empty tile within the map
		} while (nextPosition.x >= map.size.x || nextPosition.x < 0 ||
			nextPosition.y >= map.size.y || nextPosition.y < 0 ||
			nextPosition.z >= map.size.z || nextPosition.z < 0
			//FIXME: Proper routing/obstruction handling
			//(This below could cause an infinite loop if a vehicle gets 'trapped'
			|| (tries < 50 && !map.getTile(nextPosition)->ownedObjects.empty()));
		return Vec3<float>{nextPosition.x, nextPosition.y, nextPosition.z};
	}
};

class VehicleRandomDestination : public VehicleMission
{
public:
	std::uniform_int_distribution<int> xydistribution;
	std::uniform_int_distribution<int> zdistribution;
	VehicleRandomDestination(Vehicle &v)
		: VehicleMission(v), xydistribution(0,99), zdistribution(0,9)
			{};
	std::list<Tile*> path;
	virtual Vec3<float> getNextDestination()
	{
		while (path.empty())
		{
			Vec3<int> newTarget = {xydistribution(rng), xydistribution(rng), zdistribution(rng)};
			while (!vehicle.tileObject->getOwningTile()->map.getTile(newTarget)->ownedObjects.empty())
				newTarget = {xydistribution(rng), xydistribution(rng), zdistribution(rng)};
			path = vehicle.tileObject->getOwningTile()->map.findShortestPath(vehicle.tileObject->getOwningTile()->position, newTarget);
			if (path.empty())
			{
				LogInfo("Failed to path - retrying");
				continue;
			}
			//Skip first in the path (as that's current tile)
			path.pop_front();
		}
		if (!path.front()->ownedObjects.empty())
		{
			Vec3<int> target = path.back()->position;
			path = vehicle.tileObject->getOwningTile()->map.findShortestPath(vehicle.tileObject->getOwningTile()->position, target);
			if (path.empty())
			{
				LogInfo("Failed to path after obstruction");
				path.clear();
				return this->getNextDestination();
			}
			//Skip first in the path (as that's current tile)
			path.pop_front();
		}
		Tile *nextTile = path.front();
		path.pop_front();
		return Vec3<float>{nextTile->position.x, nextTile->position.y, nextTile->position.z}
			//Add {0.5,0.5,0.5} to make it route to the center of the tile
			+ Vec3<float>{0.5,0.5,0.5};
	}

};

class FlyingVehicleMover : public VehicleMover
{
public:
	Vec3<float> goalPosition;
	float speed;
	FlyingVehicleMover(Vehicle &v, Vec3<float> initialGoal)
		: VehicleMover(v), goalPosition(initialGoal)
	{
		std::uniform_real_distribution<float> distribution(-0.02, 0.02);
		//Tweak the speed slightly, makes everything a little less synchronised
		speed = 0.05 + distribution(rng);
	}
	virtual void update(unsigned int ticks)
	{
		float distanceLeft = speed * ticks;
		while (distanceLeft > 0)
		{
			Vec3<float> vectorToGoal = goalPosition -
				vehicle.position;
			float distanceToGoal = glm::length(vectorToGoal);
			if (distanceToGoal <= distanceLeft)
			{
				distanceLeft -= distanceToGoal;
				vehicle.position = goalPosition;
				goalPosition = vehicle.mission->getNextDestination();
			}
			else
			{
				vehicle.direction = vectorToGoal;
				vehicle.position += distanceLeft * glm::normalize(vectorToGoal);
				distanceLeft = -1;
			}
		}
		for (auto &weapon : vehicle.weapons)
		{
			weapon->update(ticks);
			if (weapon->canFire())
			{
				//Find something to shoot at!
				//FIXME: Only run on 'aggressive'? And not already a manually-selected target?
				float range = weapon->getWeaponDef().range;
				//Find the closest enemy within the firing arc
				float closestEnemyRange = std::numeric_limits<float>::max();
				std::shared_ptr<VehicleTileObject> closestEnemy;
				for (auto obj : vehicle.tileObject->getOwningTile()->map.activeObjects)
				{
					auto vehicleObj = std::dynamic_pointer_cast<VehicleTileObject>(obj);
					if (!vehicleObj)
					{
						/* Not a vehicle, skip */
						continue;
					}
					auto &otherVehicle = vehicleObj->getVehicle();
					if (!vehicle.owner.isHostileTo(otherVehicle.owner))
					{
						/* Not hostile, skip */
						continue;
					}
					auto myPosition = vehicle.tileObject->getPosition();
					auto enemyPosition = otherVehicle.tileObject->getPosition();
					//FIXME: Check weapon arc against otherVehicle
					auto offset = enemyPosition - myPosition;
					float distance = glm::length(offset);

					if (distance < closestEnemyRange)
					{
						closestEnemyRange = distance;
						closestEnemy = vehicleObj;
					}
				}

				if (closestEnemyRange <= range)
				{
					//Only fire if we're in range
					auto projectile = weapon->fire(closestEnemy->getPosition());
					if (projectile)
					{
						vehicle.tileObject->getOwningTile()->map.addObject(projectile);
					}
					else
					{
						LogWarning("Fire() produced no object");
					}
				}
			}
		}
	}
};

VehicleMission::VehicleMission(Vehicle &v)
	: vehicle(v)
{

}

VehicleMission::~VehicleMission()
{

}

VehicleMover::VehicleMover(Vehicle &v)
: vehicle(v)
{

}

VehicleMover::~VehicleMover()
{

}

Vehicle::Vehicle(const VehicleDefinition &def, Organisation &owner)
	: def(def), owner(owner)
{

}

Vehicle::~Vehicle()
{

}

void
Vehicle::launch(TileMap &map, Vec3<float> initialPosition)
{
	if (this->tileObject)
	{
		LogError("Trying to launch already-launched vehicle");
		return;
	}
	this->position = initialPosition;
	this->mover.reset(new FlyingVehicleMover(*this, initialPosition));
	this->mission.reset(new VehicleRandomDestination(*this));
	this->tileObject = std::make_shared<VehicleTileObject>(*this, map, initialPosition);
	map.addObject(this->tileObject);
}

VehicleTileObject::VehicleTileObject(Vehicle &vehicle, TileMap &map, Vec3<float> position)
	: TileObject(map, position),
	TileObjectDirectionalSprite(map, position, vehicle.def.directionalSprites),
	TileObjectCollidable(map, position, Vec3<int>{32,32,16}, vehicle.def.voxelMap),
	vehicle(vehicle)
{
	this->active = true;
}

VehicleTileObject::~VehicleTileObject()
{
}

void
VehicleTileObject::update(unsigned int ticks)
{
	if (this->vehicle.mover)
		this->vehicle.mover->update(ticks);
	//FIXME: Better way instead of mirroring pos/direction?
	this->setPosition(this->vehicle.position);
	this->setDirection(this->vehicle.direction);
}

Vec3<float> VehicleTileObject::getDrawPosition() const
{
	return this->getPosition() - Vec3<float>{2,1,1};
}

}; //namespace OpenApoc
<|endoftext|>


<commit_before>#include "rethinkmud.h"

#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/core/null_deleter.hpp>

namespace bl = boost::log;

namespace rethinkmud
{
    namespace log
    {
        void init()
        {
            bl::add_common_attributes();

            using text_sink_type = bl::sinks::synchronous_sink<bl::sinks::text_ostream_backend>;
            auto sink = boost::make_shared<text_sink_type>();

            sink->locked_backend()->add_stream(boost::shared_ptr< std::ostream >(&std::clog, boost::null_deleter()));

            sink->set_formatter(
                bl::expressions::stream
                    << bl::expressions::format_date_time<boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d %H:%M:%S.%f") << " :: "
                    << '[' << bl::trivial::severity << " - " << bl::expressions::attr<std::string>("Channel") << "] "
                    << bl::expressions::smessage
            );

            bl::core::get()->add_sink(sink);

            info() << "Hello world";
        }

        void clean()
        {

        }

        logger_type get_logger([[maybe_unused]] std::string const& name /* = "general" */)
        {
            return logger_type{
                bl::keywords::channel = name
            };
        }
    }
}
<commit_msg>Remove testing output<commit_after>#include "rethinkmud.h"

#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/core/null_deleter.hpp>

namespace bl = boost::log;

namespace rethinkmud
{
    namespace log
    {
        void init()
        {
            bl::add_common_attributes();

            using text_sink_type = bl::sinks::synchronous_sink<bl::sinks::text_ostream_backend>;
            auto sink = boost::make_shared<text_sink_type>();

            sink->locked_backend()->add_stream(boost::shared_ptr< std::ostream >(&std::clog, boost::null_deleter()));

            sink->set_formatter(
                bl::expressions::stream
                    << bl::expressions::format_date_time<boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d %H:%M:%S.%f") << " :: "
                    << '[' << bl::trivial::severity << " - " << bl::expressions::attr<std::string>("Channel") << "] "
                    << bl::expressions::smessage
            );

            bl::core::get()->add_sink(sink);
        }

        void clean()
        {

        }

        logger_type get_logger([[maybe_unused]] std::string const& name /* = "general" */)
        {
            return logger_type{
                bl::keywords::channel = name
            };
        }
    }
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include "libtorrent/lsd.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/http_tracker_connection.hpp"

#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <asio/ip/host_name.hpp>
#include <asio/ip/multicast.hpp>
#include <boost/thread/mutex.hpp>
#include <cstdlib>
#include <boost/config.hpp>

using boost::bind;
using namespace libtorrent;

namespace libtorrent
{
	// defined in broadcast_socket.cpp
	address guess_local_address(asio::io_service&);
}

lsd::lsd(io_service& ios, address const& listen_interface
	, peer_callback_t const& cb)
	: m_callback(cb)
	, m_retry_count(0)
	, m_socket(ios, udp::endpoint(address_v4::from_string("239.192.152.143"), 6771)
		, bind(&lsd::on_announce, self(), _1, _2, _3))
	, m_broadcast_timer(ios)
	, m_disabled(false)
{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log.open("lsd.log", std::ios::in | std::ios::out | std::ios::trunc);
#endif
}

lsd::~lsd() {}

void lsd::announce(sha1_hash const& ih, int listen_port)
{
	if (m_disabled) return;

	std::stringstream btsearch;
	btsearch << "BT-SEARCH * HTTP/1.1\r\n"
		"Host: 239.192.152.143:6771\r\n"
		"Port: " << listen_port << "\r\n"
		"Infohash: " << ih << "\r\n"
		"\r\n\r\n";
	std::string const& msg = btsearch.str();

	m_retry_count = 0;
	asio::error_code ec;
	m_socket.send(msg.c_str(), int(msg.size()), ec);
	if (ec)
	{
		m_disabled = true;
		return;
	}

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " ==> announce: ih: " << ih << " port: " << listen_port << std::endl;
#endif

	m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count));
	m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
}

void lsd::resend_announce(asio::error_code const& e, std::string msg) try
{
	if (e) return;

	asio::error_code ec;
	m_socket.send(msg.c_str(), int(msg.size()), ec);

	++m_retry_count;
	if (m_retry_count >= 5)
		return;

	m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count));
	m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
}
catch (std::exception&)
{}

void lsd::on_announce(udp::endpoint const& from, char* buffer
	, std::size_t bytes_transferred)
{
	using namespace libtorrent::detail;

	http_parser p;

	p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred));

	if (!p.header_finished())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: incomplete HTTP message\n";
#endif
		return;
	}

	if (p.method() != "bt-search")
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid HTTP method: " << p.method() << std::endl;
#endif
		return;
	}

	std::string const& port_str = p.header("port");
	if (port_str.empty())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid BT-SEARCH, missing port" << std::endl;
#endif
		return;
	}

	std::string const& ih_str = p.header("infohash");
	if (ih_str.empty())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid BT-SEARCH, missing infohash" << std::endl;
#endif
		return;
	}

	sha1_hash ih(0);
	std::istringstream ih_sstr(ih_str);
	ih_sstr >> ih;
	int port = atoi(port_str.c_str());

	if (!ih.is_all_zeros() && port != 0)
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		m_log << time_now_string()
			<< " *** incoming local announce " << from.address()
			<< ":" << port << " ih: " << ih << std::endl;
#endif
		// we got an announce, pass it on through the callback
		try { m_callback(tcp::endpoint(from.address(), port), ih); }
		catch (std::exception&) {}
	}
}

void lsd::close()
{
	m_socket.close();
}

<commit_msg>lsd close fix<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include "libtorrent/lsd.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/http_tracker_connection.hpp"

#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <asio/ip/host_name.hpp>
#include <asio/ip/multicast.hpp>
#include <boost/thread/mutex.hpp>
#include <cstdlib>
#include <boost/config.hpp>

using boost::bind;
using namespace libtorrent;

namespace libtorrent
{
	// defined in broadcast_socket.cpp
	address guess_local_address(asio::io_service&);
}

lsd::lsd(io_service& ios, address const& listen_interface
	, peer_callback_t const& cb)
	: m_callback(cb)
	, m_retry_count(0)
	, m_socket(ios, udp::endpoint(address_v4::from_string("239.192.152.143"), 6771)
		, bind(&lsd::on_announce, self(), _1, _2, _3))
	, m_broadcast_timer(ios)
	, m_disabled(false)
{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log.open("lsd.log", std::ios::in | std::ios::out | std::ios::trunc);
#endif
}

lsd::~lsd() {}

void lsd::announce(sha1_hash const& ih, int listen_port)
{
	if (m_disabled) return;

	std::stringstream btsearch;
	btsearch << "BT-SEARCH * HTTP/1.1\r\n"
		"Host: 239.192.152.143:6771\r\n"
		"Port: " << listen_port << "\r\n"
		"Infohash: " << ih << "\r\n"
		"\r\n\r\n";
	std::string const& msg = btsearch.str();

	m_retry_count = 0;
	asio::error_code ec;
	m_socket.send(msg.c_str(), int(msg.size()), ec);
	if (ec)
	{
		m_disabled = true;
		return;
	}

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " ==> announce: ih: " << ih << " port: " << listen_port << std::endl;
#endif

	m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count));
	m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
}

void lsd::resend_announce(asio::error_code const& e, std::string msg) try
{
	if (e) return;

	asio::error_code ec;
	m_socket.send(msg.c_str(), int(msg.size()), ec);

	++m_retry_count;
	if (m_retry_count >= 5)
		return;

	m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count));
	m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
}
catch (std::exception&)
{}

void lsd::on_announce(udp::endpoint const& from, char* buffer
	, std::size_t bytes_transferred)
{
	using namespace libtorrent::detail;

	http_parser p;

	p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred));

	if (!p.header_finished())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: incomplete HTTP message\n";
#endif
		return;
	}

	if (p.method() != "bt-search")
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid HTTP method: " << p.method() << std::endl;
#endif
		return;
	}

	std::string const& port_str = p.header("port");
	if (port_str.empty())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid BT-SEARCH, missing port" << std::endl;
#endif
		return;
	}

	std::string const& ih_str = p.header("infohash");
	if (ih_str.empty())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid BT-SEARCH, missing infohash" << std::endl;
#endif
		return;
	}

	sha1_hash ih(0);
	std::istringstream ih_sstr(ih_str);
	ih_sstr >> ih;
	int port = atoi(port_str.c_str());

	if (!ih.is_all_zeros() && port != 0)
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		m_log << time_now_string()
			<< " *** incoming local announce " << from.address()
			<< ":" << port << " ih: " << ih << std::endl;
#endif
		// we got an announce, pass it on through the callback
		try { m_callback(tcp::endpoint(from.address(), port), ih); }
		catch (std::exception&) {}
	}
}

void lsd::close()
{
	asio::error_code ec;
	m_socket.close(ec);
	m_broadcast_timer.cancel();
}

<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include "libtorrent/lsd.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/http_tracker_connection.hpp"
#include "libtorrent/buffer.hpp"
#include "libtorrent/http_parser.hpp"
#include "libtorrent/escape_string.hpp"

#include <boost/bind.hpp>
#include <boost/ref.hpp>
#if BOOST_VERSION < 103500
#include <asio/ip/host_name.hpp>
#include <asio/ip/multicast.hpp>
#else
#include <boost/asio/ip/host_name.hpp>
#include <boost/asio/ip/multicast.hpp>
#endif
#include <boost/thread/mutex.hpp>
#include <cstdlib>
#include <boost/config.hpp>

using boost::bind;
using namespace libtorrent;

namespace libtorrent
{
	// defined in broadcast_socket.cpp
	address guess_local_address(io_service&);
}

static error_code ec;

lsd::lsd(io_service& ios, address const& listen_interface
	, peer_callback_t const& cb)
	: m_callback(cb)
	, m_retry_count(1)
	, m_socket(ios, udp::endpoint(address_v4::from_string("239.192.152.143", ec), 6771)
		, bind(&lsd::on_announce, self(), _1, _2, _3))
	, m_broadcast_timer(ios)
	, m_disabled(false)
{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log.open("lsd.log", std::ios::in | std::ios::out | std::ios::trunc);
#endif
}

lsd::~lsd() {}

void lsd::announce(sha1_hash const& ih, int listen_port)
{
	if (m_disabled) return;

	char ih_hex[41];
	to_hex((char const*)&ih[0], 20, ih_hex);
	char msg[200];
	int msg_len = snprintf(msg, 200,
		"BT-SEARCH * HTTP/1.1\r\n"
		"Host: 239.192.152.143:6771\r\n"
		"Port: %d\r\n"
		"Infohash: %s\r\n"
		"\r\n\r\n", listen_port, ih_hex);

	m_retry_count = 1;
	error_code ec;
	m_socket.send(msg, msg_len, ec);
	if (ec)
	{
		m_disabled = true;
		return;
	}

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	snprintf(msg, 200, "%s ==> announce: ih: %s port: %u\n"
		, time_now_string(), ih_hex, listen_port);
	m_log << msg;
#endif

	m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count), ec);
	m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
}

void lsd::resend_announce(error_code const& e, std::string msg)
{
	if (e) return;

	error_code ec;
	m_socket.send(msg.c_str(), int(msg.size()), ec);

	++m_retry_count;
	if (m_retry_count >= 5)
		return;

	m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count), ec);
	m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
}

void lsd::on_announce(udp::endpoint const& from, char* buffer
	, std::size_t bytes_transferred)
{
	using namespace libtorrent::detail;

	http_parser p;

	bool error = false;
	p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred)
		, error);

	if (!p.header_finished() || error)
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: incomplete HTTP message\n";
#endif
		return;
	}

	if (p.method() != "bt-search")
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid HTTP method: " << p.method() << std::endl;
#endif
		return;
	}

	std::string const& port_str = p.header("port");
	if (port_str.empty())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid BT-SEARCH, missing port" << std::endl;
#endif
		return;
	}

	std::string const& ih_str = p.header("infohash");
	if (ih_str.empty())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid BT-SEARCH, missing infohash" << std::endl;
#endif
		return;
	}

	sha1_hash ih(0);
	from_hex(ih_str.c_str(), 40, (char*)&ih[0]);
	int port = std::atoi(port_str.c_str());

	if (!ih.is_all_zeros() && port != 0)
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		char msg[200];
		snprintf(msg, 200, "%s *** incoming local announce %s:%d ih: %s\n"
			, time_now_string(), print_address(from.address()).c_str()
			, port, ih_str.c_str());
#endif
		// we got an announce, pass it on through the callback
#ifndef BOOST_NO_EXCEPTIONS
		try {
#endif
			m_callback(tcp::endpoint(from.address(), port), ih);
#ifndef BOOST_NO_EXCEPTIONS
		}
		catch (std::exception&) {}
#endif
	}
}

void lsd::close()
{
	m_socket.close();
	error_code ec;
	m_broadcast_timer.cancel(ec);
	m_disabled = true;
	m_callback.clear();
}

<commit_msg>fixed lsd logging<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include "libtorrent/lsd.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/http_tracker_connection.hpp"
#include "libtorrent/buffer.hpp"
#include "libtorrent/http_parser.hpp"
#include "libtorrent/escape_string.hpp"

#include <boost/bind.hpp>
#include <boost/ref.hpp>
#if BOOST_VERSION < 103500
#include <asio/ip/host_name.hpp>
#include <asio/ip/multicast.hpp>
#else
#include <boost/asio/ip/host_name.hpp>
#include <boost/asio/ip/multicast.hpp>
#endif
#include <boost/thread/mutex.hpp>
#include <cstdlib>
#include <boost/config.hpp>

using boost::bind;
using namespace libtorrent;

namespace libtorrent
{
	// defined in broadcast_socket.cpp
	address guess_local_address(io_service&);
}

static error_code ec;

lsd::lsd(io_service& ios, address const& listen_interface
	, peer_callback_t const& cb)
	: m_callback(cb)
	, m_retry_count(1)
	, m_socket(ios, udp::endpoint(address_v4::from_string("239.192.152.143", ec), 6771)
		, bind(&lsd::on_announce, self(), _1, _2, _3))
	, m_broadcast_timer(ios)
	, m_disabled(false)
{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log.open("lsd.log", std::ios::in | std::ios::out | std::ios::trunc);
#endif
}

lsd::~lsd() {}

void lsd::announce(sha1_hash const& ih, int listen_port)
{
	if (m_disabled) return;

	char ih_hex[41];
	to_hex((char const*)&ih[0], 20, ih_hex);
	char msg[200];
	int msg_len = snprintf(msg, 200,
		"BT-SEARCH * HTTP/1.1\r\n"
		"Host: 239.192.152.143:6771\r\n"
		"Port: %d\r\n"
		"Infohash: %s\r\n"
		"\r\n\r\n", listen_port, ih_hex);

	m_retry_count = 1;
	error_code ec;
	m_socket.send(msg, msg_len, ec);
	if (ec)
	{
		m_disabled = true;
		return;
	}

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	snprintf(msg, 200, "%s ==> announce: ih: %s port: %u"
		, time_now_string(), ih_hex, listen_port);
	m_log << msg << std::endl;
#endif

	m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count), ec);
	m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
}

void lsd::resend_announce(error_code const& e, std::string msg)
{
	if (e) return;

	error_code ec;
	m_socket.send(msg.c_str(), int(msg.size()), ec);

	++m_retry_count;
	if (m_retry_count >= 5)
		return;

	m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count), ec);
	m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
}

void lsd::on_announce(udp::endpoint const& from, char* buffer
	, std::size_t bytes_transferred)
{
	using namespace libtorrent::detail;

	http_parser p;

	bool error = false;
	p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred)
		, error);

	if (!p.header_finished() || error)
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: incomplete HTTP message" << std::endl;
#endif
		return;
	}

	if (p.method() != "bt-search")
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid HTTP method: " << p.method() << std::endl;
#endif
		return;
	}

	std::string const& port_str = p.header("port");
	if (port_str.empty())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid BT-SEARCH, missing port" << std::endl;
#endif
		return;
	}

	std::string const& ih_str = p.header("infohash");
	if (ih_str.empty())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid BT-SEARCH, missing infohash" << std::endl;
#endif
		return;
	}

	sha1_hash ih(0);
	from_hex(ih_str.c_str(), 40, (char*)&ih[0]);
	int port = std::atoi(port_str.c_str());

	if (!ih.is_all_zeros() && port != 0)
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		char msg[200];
		snprintf(msg, 200, "%s *** incoming local announce %s:%d ih: %s\n"
			, time_now_string(), print_address(from.address()).c_str()
			, port, ih_str.c_str());
#endif
		// we got an announce, pass it on through the callback
#ifndef BOOST_NO_EXCEPTIONS
		try {
#endif
			m_callback(tcp::endpoint(from.address(), port), ih);
#ifndef BOOST_NO_EXCEPTIONS
		}
		catch (std::exception&) {}
#endif
	}
}

void lsd::close()
{
	m_socket.close();
	error_code ec;
	m_broadcast_timer.cancel(ec);
	m_disabled = true;
	m_callback.clear();
}

<|endoftext|>


<commit_before>
/**
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under both the Apache 2.0 license (found in the
 *  LICENSE file in the root directory of this source tree) and the GPLv2 (found
 *  in the COPYING file in the root directory of this source tree).
 *  You may select, at your option, one of the above-listed licenses.
 */

// Sanity check integration test for cpu_info
// Spec file: specs/windows/cpu_info.table

#include <osquery/tests/integration/tables/helper.h>

namespace osquery {
namespace table_tests {

class cpuInfo : public testing::Test {
 protected:
  void SetUp() override {
    setUpEnvironment();
  }
};

TEST_F(cpuInfo, test_sanity) {
  // 1. Query data
  auto const data = execute_query("select * from cpu_info");
  // 2. Check size before validation
  // ASSERT_GE(data.size(), 0ul);
  // ASSERT_EQ(data.size(), 1ul);
  // ASSERT_EQ(data.size(), 0ul);
  // 3. Build validation map
  // See helper.h for avaialbe flags
  // Or use custom DataCheck object
  // ValidatatioMap row_map = {
  //      {"device_id", NormalType}
  //      {"model", NormalType}
  //      {"manufacturer", NormalType}
  //      {"processor_type", NormalType}
  //      {"availability", NormalType}
  //      {"cpu_status", IntType}
  //      {"number_of_cores", NormalType}
  //      {"logical_processors", IntType}
  //      {"address_width", NormalType}
  //      {"current_clock_speed", IntType}
  //      {"max_clock_speed", IntType}
  //      {"socket_designation", NormalType}
  //}
  // 4. Perform validation
  // validate_rows(data, row_map);
}

} // namespace table_tests
} // namespace osquery
<commit_msg>cpu_info<commit_after>
/**
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under both the Apache 2.0 license (found in the
 *  LICENSE file in the root directory of this source tree) and the GPLv2 (found
 *  in the COPYING file in the root directory of this source tree).
 *  You may select, at your option, one of the above-listed licenses.
 */

// Sanity check integration test for cpu_info
// Spec file: specs/windows/cpu_info.table

#include <osquery/tests/integration/tables/helper.h>

namespace osquery {
namespace table_tests {

class cpuInfo : public testing::Test {
 protected:
  void SetUp() override {
    setUpEnvironment();
  }
};

TEST_F(cpuInfo, test_sanity) {
  const QueryData data = execute_query("select * from cpu_info");
  ASSERT_EQ(data.size(), 1ul);
  ValidatatioMap row_map = {{"device_id", NormalType},
                            {"model", NormalType},
                            {"manufacturer", NormalType},
                            {"processor_type", NonNegativeOrErrorInt},
                            {"availability", NonNegativeOrErrorInt},
                            {"cpu_status", NonNegativeOrErrorInt},
                            {"number_of_cores", NonNegativeOrErrorInt},
                            {"logical_processors", NonNegativeOrErrorInt},
                            {"address_width", NonNegativeOrErrorInt},
                            {"current_clock_speed", NonNegativeOrErrorInt},
                            {"max_clock_speed", NonNegativeOrErrorInt},
                            {"socket_designation", NormalType}};
  validate_rows(data, row_map);
}

} // namespace table_tests
} // namespace osquery
<|endoftext|>