<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE test_proximity_list

#include <boost/test/unit_test.hpp>
#include "proximity_list/proximity_list.h"
#include "proximity_list/proximitylist_api.h"
#include "type/data.h"
#include "georef/georef.h"

using namespace navitia::type;
using namespace navitia::proximitylist;

BOOST_AUTO_TEST_CASE(distances_grand_cercle)
{
    GeographicalCoord a(0,0);
    GeographicalCoord b(0,0);
    BOOST_CHECK_CLOSE(a.distance_to(a), 0, 1e-6);
    BOOST_CHECK_CLOSE(b.distance_to(b), 0, 1e-6);
    BOOST_CHECK_CLOSE(a.distance_to(b), 0, 1e-6);
    BOOST_CHECK_CLOSE(b.distance_to(a), 0, 1e-6);

    GeographicalCoord nantes(-1.57, 47.22);
    GeographicalCoord paris(2.36, 48.85);
    BOOST_CHECK_CLOSE(nantes.distance_to(paris), 340000, 10);
    BOOST_CHECK_CLOSE(paris.distance_to(nantes), 340000, 10);

    a.set_lon(180);
    BOOST_CHECK_CLOSE(a.distance_to(b), 6371*3.14*1000,1);
    BOOST_CHECK_CLOSE(b.distance_to(a), 6371*3.14*1000,1);
    BOOST_CHECK_CLOSE(a.distance_to(a), 0, 1e-6);
    BOOST_CHECK_CLOSE(b.distance_to(b), 0, 1e-6);

    a.set_lon(84); a.set_lat(89.999);
    BOOST_CHECK_CLOSE(a.distance_to(b), 6371*3.14*1000/2,1);
    BOOST_CHECK_CLOSE(b.distance_to(a), 6371*3.14*1000/2,1);
    BOOST_CHECK_CLOSE(a.distance_to(a), 0, 1e-6);
    BOOST_CHECK_CLOSE(b.distance_to(b), 0, 1e-6);

    a.set_lon(34); a.set_lat(-89.999);
    BOOST_CHECK_CLOSE(a.distance_to(b), 6371*3.14*1000/2,1);
    BOOST_CHECK_CLOSE(b.distance_to(a), 6371*3.14*1000/2,1);
    BOOST_CHECK_CLOSE(a.distance_to(a), 0, 1e-6);
    BOOST_CHECK_CLOSE(b.distance_to(b), 0, 1e-6);

    a.set_lon(0); a.set_lat(45);
    BOOST_CHECK_CLOSE(a.distance_to(b), 6371*3.14*1000/4,1);
    BOOST_CHECK_CLOSE(b.distance_to(a), 6371*3.14*1000/4,1);
    BOOST_CHECK_CLOSE(a.distance_to(a), 0, 1e-6);
    BOOST_CHECK_CLOSE(b.distance_to(b), 0, 1e-6);
}

BOOST_AUTO_TEST_CASE(approx_distance){
    GeographicalCoord canaltp(2.3921, 48.8296);
    GeographicalCoord tour_eiffel(2.29447,48.85834);
    double coslat = ::cos(canaltp.lat() * 0.0174532925199432958);
    BOOST_CHECK_CLOSE(canaltp.distance_to(tour_eiffel), ::sqrt(canaltp.approx_sqr_distance(tour_eiffel, coslat)), 1);
    BOOST_CHECK_CLOSE(tour_eiffel.distance_to(canaltp), ::sqrt(tour_eiffel.approx_sqr_distance(canaltp, coslat)), 1);
    BOOST_CHECK_CLOSE(canaltp.distance_to(tour_eiffel), ::sqrt(tour_eiffel.approx_sqr_distance(canaltp, coslat)), 1);
    BOOST_CHECK_CLOSE(tour_eiffel.distance_to(canaltp), ::sqrt(canaltp.approx_sqr_distance(tour_eiffel, coslat)), 1);
}

BOOST_AUTO_TEST_CASE(find_nearest){
    constexpr double M_TO_DEG = 1.0/111320.0;
    typedef std::pair<unsigned int, GeographicalCoord> p;
    ProximityList<unsigned int> pl;

    GeographicalCoord c;
    std::vector<GeographicalCoord> coords;

    // Exemple d'illustration issu de wikipedia
    c.set_lon(M_TO_DEG *2); c.set_lat(M_TO_DEG *3); pl.add(c, 1); coords.push_back(c);
    c.set_lon(M_TO_DEG *5); c.set_lat(M_TO_DEG *4); pl.add(c, 2); coords.push_back(c);
    c.set_lon(M_TO_DEG *9); c.set_lat(M_TO_DEG *6); pl.add(c, 3); coords.push_back(c);
    c.set_lon(M_TO_DEG *4); c.set_lat(M_TO_DEG *7); pl.add(c, 4); coords.push_back(c);
    c.set_lon(M_TO_DEG *8); c.set_lat(M_TO_DEG *1); pl.add(c, 5); coords.push_back(c);
    c.set_lon(M_TO_DEG *7); c.set_lat(M_TO_DEG *2); pl.add(c, 6); coords.push_back(c);

    pl.build();

    std::vector<unsigned int> expected {1,4,2,6,5,3};
    for(size_t i=0; i < expected.size(); ++i)
        BOOST_CHECK_EQUAL(pl.items[i].element, expected[i]);

    c.set_lon(M_TO_DEG *2); c.set_lat(M_TO_DEG *3);
    BOOST_CHECK_EQUAL(pl.find_nearest(c), 1);

    c.set_lon(M_TO_DEG *7.1); c.set_lat(M_TO_DEG *1.9);
    BOOST_CHECK_EQUAL(pl.find_nearest(c), 6);

    c.set_lon(M_TO_DEG *100); c.set_lat(M_TO_DEG *6);
    BOOST_CHECK_EQUAL(pl.find_nearest(c), 3);

    c.set_lon(M_TO_DEG *2); c.set_lat(M_TO_DEG *4);

    expected = {1};
    auto tmp1 = pl.find_within(c, 1.1);
    std::vector<unsigned int> tmp;
    for(auto p : tmp1) tmp.push_back(p.first);
    BOOST_CHECK_EQUAL(tmp1[0].second, coords[0]);
    BOOST_CHECK_EQUAL_COLLECTIONS(tmp.begin(), tmp.end(), expected.begin(), expected.end());

    expected={1,2};
    tmp1 = pl.find_within(c, 3.1);
    tmp.clear();
    for(auto p : tmp1) tmp.push_back(p.first);
    std::sort(tmp.begin(), tmp.end());
    BOOST_CHECK_EQUAL_COLLECTIONS(tmp.begin(), tmp.end(), expected.begin(), expected.end());

    expected={1,2,4};
    tmp.clear();
    tmp1 = pl.find_within(c, 3.7);
    for(auto p : tmp1) tmp.push_back(p.first);
    std::sort(tmp.begin(), tmp.end());
    BOOST_CHECK_EQUAL_COLLECTIONS(tmp.begin(), tmp.end(), expected.begin(), expected.end());

    expected={1,2,4,6};
    tmp.clear();
    tmp1 = pl.find_within(c, 5.4);
    for(auto p : tmp1) tmp.push_back(p.first);
    std::sort(tmp.begin(), tmp.end());
    BOOST_CHECK_EQUAL_COLLECTIONS(tmp.begin(), tmp.end(), expected.begin(), expected.end());

    expected={1,2,4,5,6};
    tmp.clear();
    tmp1 = pl.find_within(c, 6.8);
    for(auto p : tmp1) tmp.push_back(p.first);
    std::sort(tmp.begin(), tmp.end());
    BOOST_CHECK_EQUAL_COLLECTIONS(tmp.begin(), tmp.end(), expected.begin(), expected.end());

    expected={1,2,3,4,5,6};
    tmp.clear();
    tmp1 = pl.find_within(c, 7.3);
    for(auto p : tmp1) tmp.push_back(p.first);
    std::sort(tmp.begin(), tmp.end());
    BOOST_CHECK_EQUAL_COLLECTIONS(tmp.begin(), tmp.end(), expected.begin(), expected.end());
}
<commit_msg>Kraken : Add idx to stop_areas in proximity_list tests<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE test_proximity_list

#include <boost/test/unit_test.hpp>
#include "proximity_list/proximity_list.h"
#include "proximity_list/proximitylist_api.h"
#include "type/data.h"
#include "georef/georef.h"

using namespace navitia::type;
using namespace navitia::proximitylist;

BOOST_AUTO_TEST_CASE(distances_grand_cercle)
{
    GeographicalCoord a(0,0);
    GeographicalCoord b(0,0);
    BOOST_CHECK_CLOSE(a.distance_to(a), 0, 1e-6);
    BOOST_CHECK_CLOSE(b.distance_to(b), 0, 1e-6);
    BOOST_CHECK_CLOSE(a.distance_to(b), 0, 1e-6);
    BOOST_CHECK_CLOSE(b.distance_to(a), 0, 1e-6);

    GeographicalCoord nantes(-1.57, 47.22);
    GeographicalCoord paris(2.36, 48.85);
    BOOST_CHECK_CLOSE(nantes.distance_to(paris), 340000, 10);
    BOOST_CHECK_CLOSE(paris.distance_to(nantes), 340000, 10);

    a.set_lon(180);
    BOOST_CHECK_CLOSE(a.distance_to(b), 6371*3.14*1000,1);
    BOOST_CHECK_CLOSE(b.distance_to(a), 6371*3.14*1000,1);
    BOOST_CHECK_CLOSE(a.distance_to(a), 0, 1e-6);
    BOOST_CHECK_CLOSE(b.distance_to(b), 0, 1e-6);

    a.set_lon(84); a.set_lat(89.999);
    BOOST_CHECK_CLOSE(a.distance_to(b), 6371*3.14*1000/2,1);
    BOOST_CHECK_CLOSE(b.distance_to(a), 6371*3.14*1000/2,1);
    BOOST_CHECK_CLOSE(a.distance_to(a), 0, 1e-6);
    BOOST_CHECK_CLOSE(b.distance_to(b), 0, 1e-6);

    a.set_lon(34); a.set_lat(-89.999);
    BOOST_CHECK_CLOSE(a.distance_to(b), 6371*3.14*1000/2,1);
    BOOST_CHECK_CLOSE(b.distance_to(a), 6371*3.14*1000/2,1);
    BOOST_CHECK_CLOSE(a.distance_to(a), 0, 1e-6);
    BOOST_CHECK_CLOSE(b.distance_to(b), 0, 1e-6);

    a.set_lon(0); a.set_lat(45);
    BOOST_CHECK_CLOSE(a.distance_to(b), 6371*3.14*1000/4,1);
    BOOST_CHECK_CLOSE(b.distance_to(a), 6371*3.14*1000/4,1);
    BOOST_CHECK_CLOSE(a.distance_to(a), 0, 1e-6);
    BOOST_CHECK_CLOSE(b.distance_to(b), 0, 1e-6);
}

BOOST_AUTO_TEST_CASE(approx_distance){
    GeographicalCoord canaltp(2.3921, 48.8296);
    GeographicalCoord tour_eiffel(2.29447,48.85834);
    double coslat = ::cos(canaltp.lat() * 0.0174532925199432958);
    BOOST_CHECK_CLOSE(canaltp.distance_to(tour_eiffel), ::sqrt(canaltp.approx_sqr_distance(tour_eiffel, coslat)), 1);
    BOOST_CHECK_CLOSE(tour_eiffel.distance_to(canaltp), ::sqrt(tour_eiffel.approx_sqr_distance(canaltp, coslat)), 1);
    BOOST_CHECK_CLOSE(canaltp.distance_to(tour_eiffel), ::sqrt(tour_eiffel.approx_sqr_distance(canaltp, coslat)), 1);
    BOOST_CHECK_CLOSE(tour_eiffel.distance_to(canaltp), ::sqrt(canaltp.approx_sqr_distance(tour_eiffel, coslat)), 1);
}

BOOST_AUTO_TEST_CASE(find_nearest){
    constexpr double M_TO_DEG = 1.0/111320.0;
    typedef std::pair<unsigned int, GeographicalCoord> p;
    ProximityList<unsigned int> pl;

    GeographicalCoord c;
    std::vector<GeographicalCoord> coords;

    // Exemple d'illustration issu de wikipedia
    c.set_lon(M_TO_DEG *2); c.set_lat(M_TO_DEG *3); pl.add(c, 1); coords.push_back(c);
    c.set_lon(M_TO_DEG *5); c.set_lat(M_TO_DEG *4); pl.add(c, 2); coords.push_back(c);
    c.set_lon(M_TO_DEG *9); c.set_lat(M_TO_DEG *6); pl.add(c, 3); coords.push_back(c);
    c.set_lon(M_TO_DEG *4); c.set_lat(M_TO_DEG *7); pl.add(c, 4); coords.push_back(c);
    c.set_lon(M_TO_DEG *8); c.set_lat(M_TO_DEG *1); pl.add(c, 5); coords.push_back(c);
    c.set_lon(M_TO_DEG *7); c.set_lat(M_TO_DEG *2); pl.add(c, 6); coords.push_back(c);

    pl.build();

    std::vector<unsigned int> expected {1,4,2,6,5,3};
    for(size_t i=0; i < expected.size(); ++i)
        BOOST_CHECK_EQUAL(pl.items[i].element, expected[i]);

    c.set_lon(M_TO_DEG *2); c.set_lat(M_TO_DEG *3);
    BOOST_CHECK_EQUAL(pl.find_nearest(c), 1);

    c.set_lon(M_TO_DEG *7.1); c.set_lat(M_TO_DEG *1.9);
    BOOST_CHECK_EQUAL(pl.find_nearest(c), 6);

    c.set_lon(M_TO_DEG *100); c.set_lat(M_TO_DEG *6);
    BOOST_CHECK_EQUAL(pl.find_nearest(c), 3);

    c.set_lon(M_TO_DEG *2); c.set_lat(M_TO_DEG *4);

    expected = {1};
    auto tmp1 = pl.find_within(c, 1.1);
    std::vector<unsigned int> tmp;
    for(auto p : tmp1) tmp.push_back(p.first);
    BOOST_CHECK_EQUAL(tmp1[0].second, coords[0]);
    BOOST_CHECK_EQUAL_COLLECTIONS(tmp.begin(), tmp.end(), expected.begin(), expected.end());

    expected={1,2};
    tmp1 = pl.find_within(c, 3.1);
    tmp.clear();
    for(auto p : tmp1) tmp.push_back(p.first);
    std::sort(tmp.begin(), tmp.end());
    BOOST_CHECK_EQUAL_COLLECTIONS(tmp.begin(), tmp.end(), expected.begin(), expected.end());

    expected={1,2,4};
    tmp.clear();
    tmp1 = pl.find_within(c, 3.7);
    for(auto p : tmp1) tmp.push_back(p.first);
    std::sort(tmp.begin(), tmp.end());
    BOOST_CHECK_EQUAL_COLLECTIONS(tmp.begin(), tmp.end(), expected.begin(), expected.end());

    expected={1,2,4,6};
    tmp.clear();
    tmp1 = pl.find_within(c, 5.4);
    for(auto p : tmp1) tmp.push_back(p.first);
    std::sort(tmp.begin(), tmp.end());
    BOOST_CHECK_EQUAL_COLLECTIONS(tmp.begin(), tmp.end(), expected.begin(), expected.end());

    expected={1,2,4,5,6};
    tmp.clear();
    tmp1 = pl.find_within(c, 6.8);
    for(auto p : tmp1) tmp.push_back(p.first);
    std::sort(tmp.begin(), tmp.end());
    BOOST_CHECK_EQUAL_COLLECTIONS(tmp.begin(), tmp.end(), expected.begin(), expected.end());

    expected={1,2,3,4,5,6};
    tmp.clear();
    tmp1 = pl.find_within(c, 7.3);
    for(auto p : tmp1) tmp.push_back(p.first);
    std::sort(tmp.begin(), tmp.end());
    BOOST_CHECK_EQUAL_COLLECTIONS(tmp.begin(), tmp.end(), expected.begin(), expected.end());
}

BOOST_AUTO_TEST_CASE(test_api) {
    navitia::type::Data data;
    //Everything in the range
    auto sa = new navitia::type::StopArea();
    sa->coord.set_lon(-1.554514);
    sa->coord.set_lat(47.218515);
    sa->idx = 0;
    data.pt_data.stop_areas.push_back(sa);
    sa = new navitia::type::StopArea();
    sa->coord.set_lon(-1.552044);
    sa->coord.set_lat(47.212516);
    sa->idx = 1;
    data.pt_data.stop_areas.push_back(sa);
    data.build_proximity_list();
    navitia::type::GeographicalCoord c;
    c.set_lon(-1.554514);
    c.set_lat(47.218515);
    auto result = find(c, 700,
                    {navitia::type::Type_e::StopArea, navitia::type::Type_e::POI},
                    "", 1, 10, 0, data);
    BOOST_CHECK_EQUAL(result.places_nearby().size(), 2);
    //One object out of the range
}

BOOST_AUTO_TEST_CASE(test_api_type) {
    //Everything of the same type in the range
    //Everything of the same type and one out of the range
    //Two types and everything in the range
    //Two types and one out of the range
}

BOOST_AUTO_TEST_CASE(test_filter) {
    //We ask for a stop_area inside the range
    //We ask for a stop_area outside the range

}
<|endoftext|>


<commit_before>#include <limits.h>

#include "aio_private.h"

#define EVEN_DISTRIBUTE

const int MAX_BUF_REQS = 1024 * 3;

/*
 * each file gets the same number of outstanding requests.
 */
#ifdef EVEN_DISTRIBUTE
#define MAX_OUTSTANDING_NREQS (AIO_DEPTH / num_open_files())
#define ALLOW_DROP
#endif

class extended_io_request: public io_request
{
	char *orig_embedded_bufs[NUM_EMBEDDED_IOVECS];
	char **orig_bufs;
	slab_allocator *allocator;

	void assign_extended(extended_io_request &req) {
		this->allocator = req.allocator;
		if (req.orig_bufs == req.orig_embedded_bufs) {
			this->orig_bufs = this->orig_embedded_bufs;
			memcpy(this->orig_embedded_bufs, req.orig_embedded_bufs,
					sizeof(orig_embedded_bufs));
		}
		else {
			this->orig_bufs = req.orig_bufs;
			req.orig_bufs = NULL;
		}
	}
public:
	extended_io_request() {
		orig_bufs = NULL;
		allocator = NULL;
		memset(orig_embedded_bufs, 0, sizeof(orig_embedded_bufs));
	}

	/**
	 * The buffers in the IO request are allocated in a different NUMA node
	 * than the SSDs are connected to, and allocate buffers on the local node.
	 */
	extended_io_request(io_request &req, slab_allocator *allocator) {
		init(req, allocator);
	}

	/**
	 * The buffers are allocated in the same NUMA node as the SSDs
	 * are connected to.
	 */
	extended_io_request(io_request &req): io_request(req) {
		allocator = NULL;
		orig_bufs = NULL;
		memset(orig_embedded_bufs, 0, sizeof(orig_embedded_bufs));
	}

	extended_io_request(extended_io_request &req) {
		io_request::assign(req);
		assign_extended(req);
	}

	~extended_io_request() {
		reset();
	}

	extended_io_request &operator=(io_request &req) {
		io_request::assign(req);
		orig_bufs = NULL;
		allocator = NULL;
		memset(orig_embedded_bufs, 0, sizeof(orig_embedded_bufs));
		return *this;
	}

	extended_io_request &operator=(extended_io_request &req) {
		io_request::assign(req);
		assign_extended(req);
		return *this;
	}

	void reset();
	void init(io_request &req, slab_allocator *allocator);

	bool is_replaced() const {
		return orig_bufs != NULL;
	}

	void use_orig_bufs();
};

void extended_io_request::use_orig_bufs()
{
	for (int i = 0; i < get_num_bufs(); i++) {
		char *buf = get_buf(i);
		// This memory copy can significantly decrease the performance.
		// But it seems there isn't a better way to avoid it.
		memcpy(orig_bufs[i], buf, get_buf_size(i));
		set_buf(i, orig_bufs[i]);
		if (this->get_buf_size(i) <= PAGE_SIZE)
			allocator->free(&buf, 1);
		else
			free(buf);
	}
	// We have to reset orig_bufs because all original buffers
	// will be destroyed when the object is destructed.
	if (orig_bufs != orig_embedded_bufs)
		delete orig_bufs;
	orig_bufs = NULL;
}

void extended_io_request::init(io_request &req, slab_allocator *allocator)
{
	io_request::assign(req);
	this->allocator = allocator;
	memset(orig_embedded_bufs, 0, sizeof(orig_embedded_bufs));
	if (this->get_num_bufs() > NUM_EMBEDDED_IOVECS)
		orig_bufs = new char *[this->get_num_bufs()];
	else
		orig_bufs = orig_embedded_bufs;
	for (int i = 0; i < this->get_num_bufs(); i++) {
		char *remote_buf = this->get_buf(i);
		char *local_buf;
		if (this->get_buf_size(i) <= PAGE_SIZE) {
			int ret = allocator->alloc(&local_buf, 1);
			assert(ret == 1);
		}
		else
			local_buf = (char *) valloc(this->get_buf_size(i));
		this->set_buf(i, local_buf);
		orig_bufs[i] = remote_buf;
	}
}

void extended_io_request::reset()
{
	if (orig_bufs) {
		char *local_pages[get_num_bufs()];
		for (int i = 0; i < get_num_bufs(); i++) {
			local_pages[i] = get_buf(i);
		}
		allocator->free(local_pages, get_num_bufs());
		if (orig_bufs != orig_embedded_bufs)
			delete orig_bufs;
		orig_bufs = NULL;
	}
}

struct thread_callback_s
{
	struct io_callback_s cb;
	async_io *aio;
	extended_io_request req;
};

void aio_callback(io_context_t ctx, struct iocb* iocb[],
		void *cbs[], long res[], long res2[], int num) {
	async_io *aio = NULL;
	thread_callback_s *tcbs[num];
	for (int i = 0; i < num; i++) {
		assert(res2[i] == 0);
		tcbs[i] = (thread_callback_s *) cbs[i];
		if (aio == NULL)
			aio = tcbs[i]->aio;
		// This is true when disks are only accessed by disk access threads.
		assert(aio == tcbs[i]->aio);
	}

	aio->return_cb(tcbs, num);
}

async_io::async_io(const logical_file_partition &partition, long size,
		int aio_depth_per_file, int node_id): buffered_io(partition, size,
			node_id, O_DIRECT | O_RDWR), AIO_DEPTH(aio_depth_per_file *
				partition.get_num_files()), allocator(PAGE_SIZE,
				AIO_DEPTH * PAGE_SIZE, INT_MAX, node_id)
{
	printf("aio is used\n");
	buf_idx = 0;
	ctx = create_aio_ctx(AIO_DEPTH);
	for (int i = 0; i < AIO_DEPTH * 5; i++) {
		cbs.push_back(new thread_callback_s());
	}
	cb = NULL;
	num_iowait = 0;
}

void async_io::cleanup()
{
	int slot = max_io_slot(ctx);

	while (slot < AIO_DEPTH) {
		io_wait(ctx, NULL);
		slot = max_io_slot(ctx);
	}
	buffered_io::cleanup();
}

async_io::~async_io()
{
	cleanup();
}

struct iocb *async_io::construct_req(io_request &io_req, callback_t cb_func)
{
	if (cbs.empty()) {
		fprintf(stderr, "no callback object left\n");
		return NULL;
	}

	thread_callback_s *tcb = cbs.front();
	io_callback_s *cb = (io_callback_s *) tcb;
	cbs.pop_front();

	cb->func = cb_func;
	if (get_node_id() == io_req.get_node_id() || get_node_id() == -1)
		tcb->req = io_req;
	else
		tcb->req.init(io_req, &allocator);
	tcb->aio = this;

	assert(tcb->req.get_size() >= MIN_BLOCK_SIZE);
	assert(tcb->req.get_size() % MIN_BLOCK_SIZE == 0);
	assert(tcb->req.get_offset() % MIN_BLOCK_SIZE == 0);
	assert((long) tcb->req.get_buf() % MIN_BLOCK_SIZE == 0);
	int io_type = tcb->req.get_access_method() == READ ? A_READ : A_WRITE;
	block_identifier bid;
	get_partition().map(tcb->req.get_offset() / PAGE_SIZE, bid);
	if (tcb->req.get_num_bufs() == 1)
		return make_io_request(ctx, get_fd(tcb->req.get_offset()),
				tcb->req.get_size(), bid.off * PAGE_SIZE, tcb->req.get_buf(),
				io_type, cb);
	else {
		int num_bufs = tcb->req.get_num_bufs();
		for (int i = 0; i < num_bufs; i++) {
			assert((long) tcb->req.get_buf(i) % MIN_BLOCK_SIZE == 0);
			assert(tcb->req.get_buf_size(i) % MIN_BLOCK_SIZE == 0);
		}
		return make_io_request(ctx, get_fd(tcb->req.get_offset()),
				/*
				 * iocb only contains a pointer to the io vector.
				 * the space for the IO vector is stored
				 * in the callback structure.
				 */
				tcb->req.get_vec(), num_bufs, bid.off * PAGE_SIZE,
				io_type, cb);
	}
}

ssize_t async_io::access(io_request *requests, int num)
{
	ssize_t ret = 0;

	while (num > 0) {
		int slot = max_io_slot(ctx);
		if (slot == 0) {
			/*
			 * To achieve the best performance, we need to submit requests
			 * as long as there is a slot available.
			 */
			num_iowait++;
			io_wait(ctx, NULL, 1);
			slot = max_io_slot(ctx);
		}
		struct iocb *reqs[slot];
		int min = slot > num ? num : slot;
		for (int i = 0; i < min; i++) {
			ret += requests->get_size();
			reqs[i] = construct_req(*requests, aio_callback);
			requests++;
		}
		submit_io_request(ctx, reqs, min);
		num -= min;
	}
	return ret;
}

void async_io::return_cb(thread_callback_s *tcbs[], int num)
{
	io_request *reqs[num];
	for (int i = 0; i < num; i++) {
		thread_callback_s *tcb = tcbs[i];
		if (tcb->req.is_replaced())
			tcb->req.use_orig_bufs();
		reqs[i] = &tcb->req;
	}
	if (this->cb) {
		this->cb->invoke(reqs, num);
	}
	for (int i = 0; i < num; i++) {
		thread_callback_s *tcb = tcbs[i];
		tcb->req.reset();
		cbs.push_back(tcb);
	}
}
<commit_msg>Fix a bug in aio for writing data to a remote SSD.<commit_after>#include <limits.h>

#include "aio_private.h"

#define EVEN_DISTRIBUTE

const int MAX_BUF_REQS = 1024 * 3;

/*
 * each file gets the same number of outstanding requests.
 */
#ifdef EVEN_DISTRIBUTE
#define MAX_OUTSTANDING_NREQS (AIO_DEPTH / num_open_files())
#define ALLOW_DROP
#endif

class extended_io_request: public io_request
{
	char *orig_embedded_bufs[NUM_EMBEDDED_IOVECS];
	char **orig_bufs;
	slab_allocator *allocator;

	void assign_extended(extended_io_request &req) {
		this->allocator = req.allocator;
		if (req.orig_bufs == req.orig_embedded_bufs) {
			this->orig_bufs = this->orig_embedded_bufs;
			memcpy(this->orig_embedded_bufs, req.orig_embedded_bufs,
					sizeof(orig_embedded_bufs));
		}
		else {
			this->orig_bufs = req.orig_bufs;
			req.orig_bufs = NULL;
		}
	}
public:
	extended_io_request() {
		orig_bufs = NULL;
		allocator = NULL;
		memset(orig_embedded_bufs, 0, sizeof(orig_embedded_bufs));
	}

	/**
	 * The buffers in the IO request are allocated in a different NUMA node
	 * than the SSDs are connected to, and allocate buffers on the local node.
	 */
	extended_io_request(io_request &req, slab_allocator *allocator) {
		init(req, allocator);
	}

	/**
	 * The buffers are allocated in the same NUMA node as the SSDs
	 * are connected to.
	 */
	extended_io_request(io_request &req): io_request(req) {
		allocator = NULL;
		orig_bufs = NULL;
		memset(orig_embedded_bufs, 0, sizeof(orig_embedded_bufs));
	}

	extended_io_request(extended_io_request &req) {
		io_request::assign(req);
		assign_extended(req);
	}

	~extended_io_request() {
		reset();
	}

	extended_io_request &operator=(io_request &req) {
		io_request::assign(req);
		orig_bufs = NULL;
		allocator = NULL;
		memset(orig_embedded_bufs, 0, sizeof(orig_embedded_bufs));
		return *this;
	}

	extended_io_request &operator=(extended_io_request &req) {
		io_request::assign(req);
		assign_extended(req);
		return *this;
	}

	void reset();
	void init(io_request &req, slab_allocator *allocator);

	bool is_replaced() const {
		return orig_bufs != NULL;
	}

	void use_orig_bufs();
};

void extended_io_request::use_orig_bufs()
{
	for (int i = 0; i < get_num_bufs(); i++) {
		char *buf = get_buf(i);
		// This memory copy can significantly decrease the performance.
		// But it seems there isn't a better way to avoid it.
		if (this->get_access_method() == READ)
			memcpy(orig_bufs[i], buf, get_buf_size(i));
		set_buf(i, orig_bufs[i]);
		if (this->get_buf_size(i) <= PAGE_SIZE)
			allocator->free(&buf, 1);
		else
			free(buf);
	}
	// We have to reset orig_bufs because all original buffers
	// will be destroyed when the object is destructed.
	if (orig_bufs != orig_embedded_bufs)
		delete orig_bufs;
	orig_bufs = NULL;
}

void extended_io_request::init(io_request &req, slab_allocator *allocator)
{
	io_request::assign(req);
	this->allocator = allocator;
	memset(orig_embedded_bufs, 0, sizeof(orig_embedded_bufs));
	if (this->get_num_bufs() > NUM_EMBEDDED_IOVECS)
		orig_bufs = new char *[this->get_num_bufs()];
	else
		orig_bufs = orig_embedded_bufs;
	for (int i = 0; i < this->get_num_bufs(); i++) {
		char *remote_buf = this->get_buf(i);
		char *local_buf;
		if (this->get_buf_size(i) <= PAGE_SIZE) {
			int ret = allocator->alloc(&local_buf, 1);
			assert(ret == 1);
		}
		else
			local_buf = (char *) valloc(this->get_buf_size(i));
		if (this->get_access_method() == WRITE)
			memcpy(local_buf, remote_buf, this->get_buf_size(i));
		this->set_buf(i, local_buf);
		orig_bufs[i] = remote_buf;
	}
}

void extended_io_request::reset()
{
	if (orig_bufs) {
		char *local_pages[get_num_bufs()];
		for (int i = 0; i < get_num_bufs(); i++) {
			local_pages[i] = get_buf(i);
		}
		allocator->free(local_pages, get_num_bufs());
		if (orig_bufs != orig_embedded_bufs)
			delete orig_bufs;
		orig_bufs = NULL;
	}
}

struct thread_callback_s
{
	struct io_callback_s cb;
	async_io *aio;
	extended_io_request req;
};

void aio_callback(io_context_t ctx, struct iocb* iocb[],
		void *cbs[], long res[], long res2[], int num) {
	async_io *aio = NULL;
	thread_callback_s *tcbs[num];
	for (int i = 0; i < num; i++) {
		assert(res2[i] == 0);
		tcbs[i] = (thread_callback_s *) cbs[i];
		if (aio == NULL)
			aio = tcbs[i]->aio;
		// This is true when disks are only accessed by disk access threads.
		assert(aio == tcbs[i]->aio);
	}

	aio->return_cb(tcbs, num);
}

async_io::async_io(const logical_file_partition &partition, long size,
		int aio_depth_per_file, int node_id): buffered_io(partition, size,
			node_id, O_DIRECT | O_RDWR), AIO_DEPTH(aio_depth_per_file *
				partition.get_num_files()), allocator(PAGE_SIZE,
				AIO_DEPTH * PAGE_SIZE, INT_MAX, node_id)
{
	printf("aio is used\n");
	buf_idx = 0;
	ctx = create_aio_ctx(AIO_DEPTH);
	for (int i = 0; i < AIO_DEPTH * 5; i++) {
		cbs.push_back(new thread_callback_s());
	}
	cb = NULL;
	num_iowait = 0;
}

void async_io::cleanup()
{
	int slot = max_io_slot(ctx);

	while (slot < AIO_DEPTH) {
		io_wait(ctx, NULL);
		slot = max_io_slot(ctx);
	}
	buffered_io::cleanup();
}

async_io::~async_io()
{
	cleanup();
}

struct iocb *async_io::construct_req(io_request &io_req, callback_t cb_func)
{
	if (cbs.empty()) {
		fprintf(stderr, "no callback object left\n");
		return NULL;
	}

	thread_callback_s *tcb = cbs.front();
	io_callback_s *cb = (io_callback_s *) tcb;
	cbs.pop_front();

	cb->func = cb_func;
	if (get_node_id() == io_req.get_node_id() || get_node_id() == -1)
		tcb->req = io_req;
	else
		tcb->req.init(io_req, &allocator);
	tcb->aio = this;

	assert(tcb->req.get_size() >= MIN_BLOCK_SIZE);
	assert(tcb->req.get_size() % MIN_BLOCK_SIZE == 0);
	assert(tcb->req.get_offset() % MIN_BLOCK_SIZE == 0);
	assert((long) tcb->req.get_buf() % MIN_BLOCK_SIZE == 0);
	int io_type = tcb->req.get_access_method() == READ ? A_READ : A_WRITE;
	block_identifier bid;
	get_partition().map(tcb->req.get_offset() / PAGE_SIZE, bid);
	if (tcb->req.get_num_bufs() == 1)
		return make_io_request(ctx, get_fd(tcb->req.get_offset()),
				tcb->req.get_size(), bid.off * PAGE_SIZE, tcb->req.get_buf(),
				io_type, cb);
	else {
		int num_bufs = tcb->req.get_num_bufs();
		for (int i = 0; i < num_bufs; i++) {
			assert((long) tcb->req.get_buf(i) % MIN_BLOCK_SIZE == 0);
			assert(tcb->req.get_buf_size(i) % MIN_BLOCK_SIZE == 0);
		}
		return make_io_request(ctx, get_fd(tcb->req.get_offset()),
				/*
				 * iocb only contains a pointer to the io vector.
				 * the space for the IO vector is stored
				 * in the callback structure.
				 */
				tcb->req.get_vec(), num_bufs, bid.off * PAGE_SIZE,
				io_type, cb);
	}
}

ssize_t async_io::access(io_request *requests, int num)
{
	ssize_t ret = 0;

	while (num > 0) {
		int slot = max_io_slot(ctx);
		if (slot == 0) {
			/*
			 * To achieve the best performance, we need to submit requests
			 * as long as there is a slot available.
			 */
			num_iowait++;
			io_wait(ctx, NULL, 1);
			slot = max_io_slot(ctx);
		}
		struct iocb *reqs[slot];
		int min = slot > num ? num : slot;
		for (int i = 0; i < min; i++) {
			ret += requests->get_size();
			reqs[i] = construct_req(*requests, aio_callback);
			requests++;
		}
		submit_io_request(ctx, reqs, min);
		num -= min;
	}
	return ret;
}

void async_io::return_cb(thread_callback_s *tcbs[], int num)
{
	io_request *reqs[num];
	for (int i = 0; i < num; i++) {
		thread_callback_s *tcb = tcbs[i];
		if (tcb->req.is_replaced())
			tcb->req.use_orig_bufs();
		reqs[i] = &tcb->req;
	}
	if (this->cb) {
		this->cb->invoke(reqs, num);
	}
	for (int i = 0; i < num; i++) {
		thread_callback_s *tcb = tcbs[i];
		tcb->req.reset();
		cbs.push_back(tcb);
	}
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "S60mediarecognizer.h"
#include <MPMediaRecognizer.h>
#include <e32def.h>
#include <e32cmn.h>
#include <QUrl>
#include <QDir>

S60MediaRecognizer::S60MediaRecognizer(QObject *parent) : QObject(parent)
{
    m_recognizer = NULL;
    TRAP(m_error, m_recognizer = CMPMediaRecognizer::NewL());
}

S60MediaRecognizer::~S60MediaRecognizer()
{
    delete m_recognizer;
    m_recognizer = NULL;
}
/*
 * Checks if Url is valid or not.
 */
bool S60MediaRecognizer::checkUrl(const QUrl& url)
{
   TBool validUrl = false;
   if (m_recognizer) {
       TPtrC myDesc (static_cast<const TUint16*>(url.toString().utf16()), url.toString().length());
       validUrl = m_recognizer->ValidUrl(myDesc);
   }

   return validUrl;
}

S60MediaRecognizer::MediaType S60MediaRecognizer::IdentifyMediaType(const QUrl& url)
{
   CMPMediaRecognizer::TMPMediaType type;
   QString filePath = QDir::toNativeSeparators(url.toLocalFile());
   TPtrC16 urlPtr(reinterpret_cast<const TUint16*>(filePath.utf16()));
   MediaType mediaType = NotSupported;
   TRAP(m_error, type = m_recognizer->IdentifyMediaTypeL(urlPtr, EFalse));

   if (!m_error) {
       switch (type) {
       case CMPMediaRecognizer::ELocalAudioFile:
           mediaType = Audio;
           break;
       case CMPMediaRecognizer::ELocalVideoFile:
           mediaType = Video;
           break;
       case CMPMediaRecognizer::ELocalAudioPlaylist:
       case CMPMediaRecognizer::EUrl:
// TODO: Must be considered when streams will be implemented
       case CMPMediaRecognizer::ELocalRamFile:
       case CMPMediaRecognizer::ELocalSdpFile:
       case CMPMediaRecognizer::EProgressiveDownload:
       case CMPMediaRecognizer::EUnidentified:
       default:
           break;
       }
   }
   return mediaType;
}
<commit_msg>Exclude EProgressiveDownload from switch.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "S60mediarecognizer.h"
#include <MPMediaRecognizer.h>
#include <e32def.h>
#include <e32cmn.h>
#include <QUrl>
#include <QDir>

S60MediaRecognizer::S60MediaRecognizer(QObject *parent) : QObject(parent)
{
    m_recognizer = NULL;
    TRAP(m_error, m_recognizer = CMPMediaRecognizer::NewL());
}

S60MediaRecognizer::~S60MediaRecognizer()
{
    delete m_recognizer;
    m_recognizer = NULL;
}
/*
 * Checks if Url is valid or not.
 */
bool S60MediaRecognizer::checkUrl(const QUrl& url)
{
   TBool validUrl = false;
   if (m_recognizer) {
       TPtrC myDesc (static_cast<const TUint16*>(url.toString().utf16()), url.toString().length());
       validUrl = m_recognizer->ValidUrl(myDesc);
   }

   return validUrl;
}

S60MediaRecognizer::MediaType S60MediaRecognizer::IdentifyMediaType(const QUrl& url)
{
   CMPMediaRecognizer::TMPMediaType type;
   QString filePath = QDir::toNativeSeparators(url.toLocalFile());
   TPtrC16 urlPtr(reinterpret_cast<const TUint16*>(filePath.utf16()));
   MediaType mediaType = NotSupported;
   TRAP(m_error, type = m_recognizer->IdentifyMediaTypeL(urlPtr, EFalse));

   if (!m_error) {
       switch (type) {
       case CMPMediaRecognizer::ELocalAudioFile:
           mediaType = Audio;
           break;
       case CMPMediaRecognizer::ELocalVideoFile:
           mediaType = Video;
           break;
       case CMPMediaRecognizer::ELocalAudioPlaylist:
       case CMPMediaRecognizer::EUrl:
// TODO: Must be considered when streams will be implemented
       case CMPMediaRecognizer::ELocalRamFile:
       case CMPMediaRecognizer::ELocalSdpFile:
//     case CMPMediaRecognizer::EProgressiveDownload:
       case CMPMediaRecognizer::EUnidentified:
       default:
           break;
       }
   }
   return mediaType;
}
<|endoftext|>


<commit_before>//
//  yas_db_model.cpp
//

#include <unordered_map>
#include <vector>
#include "yas_db_model.h"
#include "yas_db_entity.h"
#include "yas_db_index.h"
#include "yas_db_attribute.h"
#include "yas_db_relation.h"

using namespace yas;

namespace yas::db {
static std::string const version_key = "version";
static std::string const entities_key = "entities";
static std::string const indices_key = "indices";
static std::string const attributes_key = "attributes";
static std::string const relations_key = "relations";

static std::unordered_map<std::string, db::string_set_map_t> make_inverse_relation_names(
    std::vector<db::entity_args> const &enitity_args_vec) {
    std::unordered_map<std::string, db::string_set_map_t> entity_inv_rel_names;

    for (db::entity_args const &entity : enitity_args_vec) {
        std::string const &entity_name = entity.name;
        for (db::relation_args const &relation : entity.relations) {
            std::string const &tgt_entity_name = relation.target;

            if (entity_inv_rel_names.count(tgt_entity_name) == 0) {
                entity_inv_rel_names.insert(std::make_pair(tgt_entity_name, db::string_set_map_t{}));
            }

            auto &inv_rel_names = entity_inv_rel_names.at(tgt_entity_name);
            if (inv_rel_names.count(entity_name) == 0) {
                inv_rel_names.insert(std::make_pair(entity_name, db::string_set_t{}));
            }

            inv_rel_names.at(entity_name).insert(relation.name);
        }
    }

    return entity_inv_rel_names;
}
}

struct db::model::impl : base::impl {
    struct args {
        yas::version const version;
        db::entity_map_t const entities;
        db::index_map_t const indices;
    };

    args _args;

    static db::model::impl::args to_args(model_args &&args) {
        auto entity_inv_rel_names = make_inverse_relation_names(args.entities);

        db::entity_map_t entities;
        entities.reserve(args.entities.size());

        for (db::entity_args &entity_args : args.entities) {
            db::string_set_map_t inv_rel_names;
            if (entity_inv_rel_names.count(entity_args.name)) {
                inv_rel_names = std::move(entity_inv_rel_names.at(entity_args.name));
            }

            std::string name = entity_args.name;
            entities.emplace(std::move(name), db::entity{{.name = std::move(entity_args.name),
                                                          .attributes = std::move(entity_args.attributes),
                                                          .relations = std::move(entity_args.relations)},
                                                         std::move(inv_rel_names)});
        }

        db::index_map_t indices;
        indices.reserve(args.indices.size());

        for (db::index_args &index_args : args.indices) {
            std::string name = index_args.name;
            indices.emplace(std::move(name), db::index{std::move(index_args)});
        }

        return {.version = std::move(args.version), .entities = std::move(entities), .indices = std::move(indices)};
    }

    impl(model_args &&args) : _args(to_args(std::move(args))) {
    }
};

db::model::model(model_args args) : base(std::make_shared<impl>(std::move(args))) {
}

db::model::model(std::nullptr_t) : base(nullptr) {
}

yas::version const &db::model::version() const {
    return impl_ptr<impl>()->_args.version;
}

db::entity_map_t const &db::model::entities() const {
    return impl_ptr<impl>()->_args.entities;
}

db::index_map_t const &db::model::indices() const {
    return impl_ptr<impl>()->_args.indices;
}

db::entity const &db::model::entity(std::string const &entity) const {
    return this->entities().at(entity);
}

db::attribute_map_t const &db::model::attributes(std::string const &entity) const {
    return this->entities().at(entity).all_attributes;
}

db::attribute_map_t const &db::model::custom_attributes(std::string const &entity) const {
    return this->entities().at(entity).custom_attributes;
}

db::relation_map_t const &db::model::relations(std::string const &entity) const {
    return this->entities().at(entity).relations;
}

db::attribute const &db::model::attribute(std::string const &entity, std::string const &attr_name) const {
    return this->entities().at(entity).all_attributes.at(attr_name);
}

db::relation const &db::model::relation(std::string const &entity, std::string const &rel_name) const {
    return this->entities().at(entity).relations.at(rel_name);
}

db::index const &db::model::index(std::string const &index_name) const {
    return this->indices().at(index_name);
}

bool db::model::entity_exists(std::string const &entity) const {
    return this->entities().count(entity) > 0;
}

bool db::model::attribute_exists(std::string const &entity, std::string const &attr_name) const {
    if (this->entity_exists(entity)) {
        if (this->entities().at(entity).all_attributes.count(attr_name) > 0) {
            return true;
        }
    }
    return false;
}

bool db::model::relation_exists(std::string const &entity, std::string const &rel_name) const {
    if (this->entity_exists(entity)) {
        if (this->entities().at(entity).relations.count(rel_name) > 0) {
            return true;
        }
    }
    return false;
}

bool db::model::index_exists(std::string const &index_name) const {
    return this->indices().count(index_name) > 0;
}
<commit_msg>remove key<commit_after>//
//  yas_db_model.cpp
//

#include <unordered_map>
#include <vector>
#include "yas_db_model.h"
#include "yas_db_entity.h"
#include "yas_db_index.h"
#include "yas_db_attribute.h"
#include "yas_db_relation.h"

using namespace yas;

namespace yas::db {
static std::unordered_map<std::string, db::string_set_map_t> make_inverse_relation_names(
    std::vector<db::entity_args> const &enitity_args_vec) {
    std::unordered_map<std::string, db::string_set_map_t> entity_inv_rel_names;

    for (db::entity_args const &entity : enitity_args_vec) {
        std::string const &entity_name = entity.name;
        for (db::relation_args const &relation : entity.relations) {
            std::string const &tgt_entity_name = relation.target;

            if (entity_inv_rel_names.count(tgt_entity_name) == 0) {
                entity_inv_rel_names.insert(std::make_pair(tgt_entity_name, db::string_set_map_t{}));
            }

            auto &inv_rel_names = entity_inv_rel_names.at(tgt_entity_name);
            if (inv_rel_names.count(entity_name) == 0) {
                inv_rel_names.insert(std::make_pair(entity_name, db::string_set_t{}));
            }

            inv_rel_names.at(entity_name).insert(relation.name);
        }
    }

    return entity_inv_rel_names;
}
}

struct db::model::impl : base::impl {
    struct args {
        yas::version const version;
        db::entity_map_t const entities;
        db::index_map_t const indices;
    };

    args _args;

    static db::model::impl::args to_args(model_args &&args) {
        auto entity_inv_rel_names = make_inverse_relation_names(args.entities);

        db::entity_map_t entities;
        entities.reserve(args.entities.size());

        for (db::entity_args &entity_args : args.entities) {
            db::string_set_map_t inv_rel_names;
            if (entity_inv_rel_names.count(entity_args.name)) {
                inv_rel_names = std::move(entity_inv_rel_names.at(entity_args.name));
            }

            std::string name = entity_args.name;
            entities.emplace(std::move(name), db::entity{{.name = std::move(entity_args.name),
                                                          .attributes = std::move(entity_args.attributes),
                                                          .relations = std::move(entity_args.relations)},
                                                         std::move(inv_rel_names)});
        }

        db::index_map_t indices;
        indices.reserve(args.indices.size());

        for (db::index_args &index_args : args.indices) {
            std::string name = index_args.name;
            indices.emplace(std::move(name), db::index{std::move(index_args)});
        }

        return {.version = std::move(args.version), .entities = std::move(entities), .indices = std::move(indices)};
    }

    impl(model_args &&args) : _args(to_args(std::move(args))) {
    }
};

db::model::model(model_args args) : base(std::make_shared<impl>(std::move(args))) {
}

db::model::model(std::nullptr_t) : base(nullptr) {
}

yas::version const &db::model::version() const {
    return impl_ptr<impl>()->_args.version;
}

db::entity_map_t const &db::model::entities() const {
    return impl_ptr<impl>()->_args.entities;
}

db::index_map_t const &db::model::indices() const {
    return impl_ptr<impl>()->_args.indices;
}

db::entity const &db::model::entity(std::string const &entity) const {
    return this->entities().at(entity);
}

db::attribute_map_t const &db::model::attributes(std::string const &entity) const {
    return this->entities().at(entity).all_attributes;
}

db::attribute_map_t const &db::model::custom_attributes(std::string const &entity) const {
    return this->entities().at(entity).custom_attributes;
}

db::relation_map_t const &db::model::relations(std::string const &entity) const {
    return this->entities().at(entity).relations;
}

db::attribute const &db::model::attribute(std::string const &entity, std::string const &attr_name) const {
    return this->entities().at(entity).all_attributes.at(attr_name);
}

db::relation const &db::model::relation(std::string const &entity, std::string const &rel_name) const {
    return this->entities().at(entity).relations.at(rel_name);
}

db::index const &db::model::index(std::string const &index_name) const {
    return this->indices().at(index_name);
}

bool db::model::entity_exists(std::string const &entity) const {
    return this->entities().count(entity) > 0;
}

bool db::model::attribute_exists(std::string const &entity, std::string const &attr_name) const {
    if (this->entity_exists(entity)) {
        if (this->entities().at(entity).all_attributes.count(attr_name) > 0) {
            return true;
        }
    }
    return false;
}

bool db::model::relation_exists(std::string const &entity, std::string const &rel_name) const {
    if (this->entity_exists(entity)) {
        if (this->entities().at(entity).relations.count(rel_name) > 0) {
            return true;
        }
    }
    return false;
}

bool db::model::index_exists(std::string const &index_name) const {
    return this->indices().count(index_name) > 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#include <uavcan/transport/frame.hpp>
#include <uavcan/transport/can_io.hpp>
#include <uavcan/debug.hpp>
#include <cassert>

namespace uavcan
{
/**
 * Frame
 */
const uint8_t Frame::MaxIndexForService;
const uint8_t Frame::MaxIndexForMessage;

uint_fast8_t Frame::getMaxIndexForTransferType(const TransferType type)
{
    if (type == TransferTypeMessageBroadcast ||
        type == TransferTypeMessageUnicast)
    {
        return MaxIndexForMessage;
    }
    else if (type == TransferTypeServiceRequest ||
             type == TransferTypeServiceResponse)
    {
        return MaxIndexForService;
    }
    else
    {
        UAVCAN_ASSERT(0);
        return 0;
    }
}

void Frame::setPriority(const TransferPriority priority)
{
    UAVCAN_ASSERT(priority < NumTransferPriorities);
    if (transfer_type_ == TransferTypeMessageBroadcast ||
        transfer_type_ == TransferTypeMessageUnicast)
    {
        if (priority != TransferPriorityService)
        {
            transfer_priority_ = priority;
        }
        else
        {
            UAVCAN_ASSERT(0);
        }
    }
    else
    {
        UAVCAN_ASSERT(0);
    }
}

int Frame::getMaxPayloadLen() const
{
    switch (getTransferType())
    {
    case TransferTypeMessageBroadcast:
    {
        return int(sizeof(payload_));
    }
    case TransferTypeServiceResponse:
    case TransferTypeServiceRequest:
    case TransferTypeMessageUnicast:
    {
        return int(sizeof(payload_)) - 1;
    }
    default:
    {
        UAVCAN_ASSERT(0);
        return -ErrLogic;
    }
    }
}

int Frame::setPayload(const uint8_t* data, unsigned len)
{
    const int maxlen = getMaxPayloadLen();
    if (maxlen < 0)
    {
        return maxlen;
    }
    len = min(unsigned(maxlen), len);
    (void)copy(data, data + len, payload_);
    payload_len_ = uint_fast8_t(len);
    return int(len);
}

template <int OFFSET, int WIDTH>
inline static uint32_t bitunpack(uint32_t val)
{
    StaticAssert<(OFFSET >= 0)>::check();
    StaticAssert<(WIDTH > 0)>::check();
    StaticAssert<((OFFSET + WIDTH) <= 29)>::check();
    return (val >> OFFSET) & ((1UL << WIDTH) - 1);
}

bool Frame::parse(const CanFrame& can_frame)
{
    if (can_frame.isErrorFrame() || can_frame.isRemoteTransmissionRequest() || !can_frame.isExtended())
    {
        return false;
    }

    if (can_frame.dlc > sizeof(can_frame.data))
    {
        UAVCAN_ASSERT(0);  // This is not a protocol error, so UAVCAN_ASSERT() is ok
        return false;
    }

    /*
     * CAN ID parsing
     */
    const uint32_t id = can_frame.id & CanFrame::MaskExtID;
    transfer_id_       = uint8_t(bitunpack<0, 3>(id));
    last_frame_        = bitunpack<3, 1>(id) != 0;
    // TT-specific fields skipped
    transfer_priority_ = TransferPriority(bitunpack<27, 2>(id));

    if (transfer_priority_ == TransferPriorityService)
    {
        frame_index_   = uint_fast8_t(bitunpack<4, 6>(id));
        src_node_id_   = uint8_t(bitunpack<10, 7>(id));
        data_type_id_  = uint16_t(bitunpack<17, 9>(id));
        // RequestNotResponse
        transfer_type_ = (bitunpack<26, 1>(id) == 1U) ? TransferTypeServiceRequest : TransferTypeServiceResponse;
    }
    else
    {
        frame_index_   = uint_fast8_t(bitunpack<4, 4>(id));
        // BroadcastNotUnicast
        transfer_type_ = (bitunpack<8, 1>(id) == 1U) ? TransferTypeMessageBroadcast : TransferTypeMessageUnicast;
        src_node_id_   = uint8_t(bitunpack<9, 7>(id));
        data_type_id_  = uint16_t(bitunpack<16, 11>(id));
    }

    /*
     * CAN payload parsing
     */
    switch (transfer_type_)
    {
    case TransferTypeMessageBroadcast:
    {
        dst_node_id_ = NodeID::Broadcast;
        payload_len_ = can_frame.dlc;
        (void)copy(can_frame.data, can_frame.data + can_frame.dlc, payload_);
        break;
    }
    case TransferTypeServiceResponse:
    case TransferTypeServiceRequest:
    case TransferTypeMessageUnicast:
    {
        if (can_frame.dlc < 1)
        {
            return false;
        }
        if (can_frame.data[0] & 0x80)     // RESERVED, must be zero
        {
            return false;
        }
        dst_node_id_ = can_frame.data[0] & 0x7F;
        payload_len_ = uint8_t(can_frame.dlc - 1);
        (void)copy(can_frame.data + 1, can_frame.data + can_frame.dlc, payload_);
        break;
    }
    default:
    {
        return false;
    }
    }

    /*
     * Special case for anonymous transfers - trailing 8 bits of CAN ID must be ignored
     *  - Transfer ID (assumed zero)
     *  - Last Frame  (assumed true)
     *  - Frame Index (assumed zero)
     */
    if (src_node_id_.isBroadcast())
    {
        transfer_id_ = TransferID(0);
        last_frame_  = true;
        frame_index_ = 0;
    }

    return isValid();
}

template <int OFFSET, int WIDTH>
inline static uint32_t bitpack(uint32_t field)
{
    StaticAssert<(OFFSET >= 0)>::check();
    StaticAssert<(WIDTH > 0)>::check();
    StaticAssert<((OFFSET + WIDTH) <= 29)>::check();
    UAVCAN_ASSERT((field & ((1UL << WIDTH) - 1)) == field);
    return uint32_t((field & ((1UL << WIDTH) - 1)) << OFFSET);
}

bool Frame::compile(CanFrame& out_can_frame) const
{
    if (!isValid())
    {
        UAVCAN_ASSERT(0);        // This is an application error, so we need to maximize it.
        return false;
    }

    /*
     * Setting CAN ID field
     */
    // Common fields for messages and services
    out_can_frame.id =
        CanFrame::FlagEFF |
        bitpack<0, 3>(transfer_id_.get()) |
        bitpack<3, 1>(last_frame_) |
        /* TT-specific fields skipped */
        bitpack<27, 2>(transfer_priority_);

    if (transfer_type_ == TransferTypeServiceRequest ||
        transfer_type_ == TransferTypeServiceResponse)
    {
        out_can_frame.id |=
            bitpack<4, 6>(frame_index_) |
            bitpack<10, 7>(src_node_id_.get()) |
            bitpack<17, 9>(data_type_id_.get()) |
            bitpack<26, 1>((transfer_type_ == TransferTypeServiceRequest) ? 1U : 0U);
    }
    else if (transfer_type_ == TransferTypeMessageBroadcast ||
             transfer_type_ == TransferTypeMessageUnicast)
    {
        out_can_frame.id |=
            bitpack<4, 4>(frame_index_) |
            bitpack<8, 1>((transfer_type_ == TransferTypeMessageBroadcast) ? 1U : 0U) |
            bitpack<9, 7>(src_node_id_.get()) |
            bitpack<16, 11>(data_type_id_.get());
    }
    else
    {
        UAVCAN_ASSERT(0);
        return false;
    }

    /*
     * Setting payload
     */
    switch (transfer_type_)
    {
    case TransferTypeMessageBroadcast:
    {
        out_can_frame.dlc = uint8_t(payload_len_);
        (void)copy(payload_, payload_ + payload_len_, out_can_frame.data);
        break;
    }
    case TransferTypeServiceResponse:
    case TransferTypeServiceRequest:
    case TransferTypeMessageUnicast:
    {
        UAVCAN_ASSERT((payload_len_ + 1U) <= sizeof(out_can_frame.data));
        out_can_frame.data[0] = dst_node_id_.get();
        out_can_frame.dlc = uint8_t(payload_len_ + 1);
        (void)copy(payload_, payload_ + payload_len_, out_can_frame.data + 1);
        break;
    }
    default:
    {
        UAVCAN_ASSERT(0);
        return false;
    }
    }

    /*
     * Setting trailing bits of CAN ID for anonymous message
     * This overrides the following fields:
     *  - Transfer ID (assumed zero)
     *  - Last Frame  (assumed true)
     *  - Frame Index (assumed zero)
     */
    if (src_node_id_.isBroadcast())
    {
        uint8_t sum = 0;
        out_can_frame.id &= ~bitpack<0, 8>(sum);        // Clearing bits
        for (uint_fast8_t i = 0; i < payload_len_; i++)
        {
            sum =  static_cast<uint8_t>(sum + payload_[i]);
        }
        out_can_frame.id |= bitpack<0, 8>(sum);        // Setting the checksum
    }

    return true;
}

bool Frame::isValid() const
{
    /*
     * Frame index
     */
    if (frame_index_ > getMaxIndex())
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    if ((frame_index_ == getMaxIndex()) && !last_frame_)
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    /*
     * Node ID
     */
    if (!src_node_id_.isValid() ||
        !dst_node_id_.isValid())
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    if (src_node_id_.isUnicast() &&
        (src_node_id_ == dst_node_id_))
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    /*
     * Transfer type
     */
    if (transfer_type_ >= NumTransferTypes)
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    if ((transfer_type_ == TransferTypeMessageBroadcast) != dst_node_id_.isBroadcast())
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    // Anonymous transfers
    if (src_node_id_.isBroadcast() &&
        (!last_frame_ || (frame_index_ > 0) || (transfer_type_ != TransferTypeMessageBroadcast)))
    {
        return false;
    }

    /*
     * Payload
     */
    if (static_cast<int>(payload_len_) > getMaxPayloadLen())
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    /*
     * Data type ID
     */
    if (!data_type_id_.isValidForDataTypeKind(getDataTypeKindForTransferType(transfer_type_)))
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    /*
     * Priority
     */
    if (transfer_priority_ >= NumTransferPriorities)
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    if (transfer_type_ == TransferTypeServiceRequest ||
        transfer_type_ == TransferTypeServiceResponse)
    {
        if (transfer_priority_ != TransferPriorityService)
        {
            UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
            return false;
        }
    }

    return true;
}

bool Frame::operator==(const Frame& rhs) const
{
    return
        (transfer_priority_ == rhs.transfer_priority_) &&
        (transfer_type_     == rhs.transfer_type_) &&
        (data_type_id_      == rhs.data_type_id_) &&
        (src_node_id_       == rhs.src_node_id_) &&
        (dst_node_id_       == rhs.dst_node_id_) &&
        (frame_index_       == rhs.frame_index_) &&
        (transfer_id_       == rhs.transfer_id_) &&
        (last_frame_        == rhs.last_frame_) &&
        (payload_len_       == rhs.payload_len_) &&
        equal(payload_, payload_ + payload_len_, rhs.payload_);
}

#if UAVCAN_TOSTRING
std::string Frame::toString() const
{
    /*
     *  - Priority
     *  - Data Type ID
     *  - Transfer Type
     *  - Source Node ID
     *  - Frame Index
     *  - Last Frame
     *  - Transfer ID
     */
    static const int BUFLEN = 100;
    char buf[BUFLEN];
    int ofs = snprintf(buf, BUFLEN, "prio=%d dtid=%d tt=%d snid=%d dnid=%d idx=%d last=%d tid=%d payload=[",
                       int(transfer_priority_), int(data_type_id_.get()), int(transfer_type_), int(src_node_id_.get()),
                       int(dst_node_id_.get()), int(frame_index_), int(last_frame_), int(transfer_id_.get()));

    for (unsigned i = 0; i < payload_len_; i++)
    {
        ofs += snprintf(buf + ofs, unsigned(BUFLEN - ofs), "%02x", payload_[i]);
        if ((i + 1) < payload_len_)
        {
            ofs += snprintf(buf + ofs, unsigned(BUFLEN - ofs), " ");
        }
    }
    (void)snprintf(buf + ofs, unsigned(BUFLEN - ofs), "]");
    return std::string(buf);
}
#endif

/**
 * RxFrame
 */
bool RxFrame::parse(const CanRxFrame& can_frame)
{
    if (!Frame::parse(can_frame))
    {
        return false;
    }
    if (can_frame.ts_mono.isZero())  // Monotonic timestamps are mandatory.
    {
        UAVCAN_ASSERT(0);                   // If it is not set, it's a driver failure.
        return false;
    }
    ts_mono_ = can_frame.ts_mono;
    ts_utc_ = can_frame.ts_utc;
    iface_index_ = can_frame.iface_index;
    return true;
}

#if UAVCAN_TOSTRING
std::string RxFrame::toString() const
{
    std::string out = Frame::toString();
    out.reserve(128);
    out += " ts_m="   + ts_mono_.toString();
    out += " ts_utc=" + ts_utc_.toString();
    out += " iface=";
    out += char('0' + iface_index_);
    return out;
}
#endif

}
<commit_msg>Coverity 1304848<commit_after>/*
 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#include <uavcan/transport/frame.hpp>
#include <uavcan/transport/can_io.hpp>
#include <uavcan/debug.hpp>
#include <cassert>

namespace uavcan
{
/**
 * Frame
 */
const uint8_t Frame::MaxIndexForService;
const uint8_t Frame::MaxIndexForMessage;

uint_fast8_t Frame::getMaxIndexForTransferType(const TransferType type)
{
    if (type == TransferTypeMessageBroadcast ||
        type == TransferTypeMessageUnicast)
    {
        return MaxIndexForMessage;
    }
    else if (type == TransferTypeServiceRequest ||
             type == TransferTypeServiceResponse)
    {
        return MaxIndexForService;
    }
    else
    {
        UAVCAN_ASSERT(0);
        return 0;
    }
}

void Frame::setPriority(const TransferPriority priority)
{
    UAVCAN_ASSERT(priority < NumTransferPriorities);
    if (transfer_type_ == TransferTypeMessageBroadcast ||
        transfer_type_ == TransferTypeMessageUnicast)
    {
        if (priority != TransferPriorityService)
        {
            transfer_priority_ = priority;
        }
        else
        {
            UAVCAN_ASSERT(0);
        }
    }
    else
    {
        UAVCAN_ASSERT(0);
    }
}

int Frame::getMaxPayloadLen() const
{
    switch (getTransferType())
    {
    case TransferTypeMessageBroadcast:
    {
        return int(sizeof(payload_));
    }
    case TransferTypeServiceResponse:
    case TransferTypeServiceRequest:
    case TransferTypeMessageUnicast:
    {
        return int(sizeof(payload_)) - 1;
    }
    default:
    {
        UAVCAN_ASSERT(0);
        return -ErrLogic;
    }
    }
}

int Frame::setPayload(const uint8_t* data, unsigned len)
{
    const int maxlen = getMaxPayloadLen();
    if (maxlen < 0)
    {
        return maxlen;
    }
    len = min(unsigned(maxlen), len);
    (void)copy(data, data + len, payload_);
    payload_len_ = uint_fast8_t(len);
    return int(len);
}

template <int OFFSET, int WIDTH>
inline static uint32_t bitunpack(uint32_t val)
{
    StaticAssert<(OFFSET >= 0)>::check();
    StaticAssert<(WIDTH > 0)>::check();
    StaticAssert<((OFFSET + WIDTH) <= 29)>::check();
    return (val >> OFFSET) & ((1UL << WIDTH) - 1);
}

bool Frame::parse(const CanFrame& can_frame)
{
    if (can_frame.isErrorFrame() || can_frame.isRemoteTransmissionRequest() || !can_frame.isExtended())
    {
        return false;
    }

    if (can_frame.dlc > sizeof(can_frame.data))
    {
        UAVCAN_ASSERT(0);  // This is not a protocol error, so UAVCAN_ASSERT() is ok
        return false;
    }

    /*
     * CAN ID parsing
     */
    const uint32_t id = can_frame.id & CanFrame::MaskExtID;
    transfer_id_       = uint8_t(bitunpack<0, 3>(id));
    last_frame_        = bitunpack<3, 1>(id) != 0;
    // TT-specific fields skipped
    transfer_priority_ = TransferPriority(bitunpack<27, 2>(id));

    if (transfer_priority_ == TransferPriorityService)
    {
        frame_index_   = uint_fast8_t(bitunpack<4, 6>(id));
        src_node_id_   = uint8_t(bitunpack<10, 7>(id));
        data_type_id_  = uint16_t(bitunpack<17, 9>(id));
        // RequestNotResponse
        transfer_type_ = (bitunpack<26, 1>(id) == 1U) ? TransferTypeServiceRequest : TransferTypeServiceResponse;
    }
    else
    {
        frame_index_   = uint_fast8_t(bitunpack<4, 4>(id));
        // BroadcastNotUnicast
        transfer_type_ = (bitunpack<8, 1>(id) == 1U) ? TransferTypeMessageBroadcast : TransferTypeMessageUnicast;
        src_node_id_   = uint8_t(bitunpack<9, 7>(id));
        data_type_id_  = uint16_t(bitunpack<16, 11>(id));
    }

    /*
     * CAN payload parsing
     */
    switch (transfer_type_)
    {
    case TransferTypeMessageBroadcast:
    {
        dst_node_id_ = NodeID::Broadcast;
        payload_len_ = can_frame.dlc;
        (void)copy(can_frame.data, can_frame.data + can_frame.dlc, payload_);
        break;
    }
    case TransferTypeServiceResponse:
    case TransferTypeServiceRequest:
    case TransferTypeMessageUnicast:
    {
        if (can_frame.dlc < 1)
        {
            return false;
        }
        if (can_frame.data[0] & 0x80)     // RESERVED, must be zero
        {
            return false;
        }
        dst_node_id_ = can_frame.data[0] & 0x7F;
        payload_len_ = uint8_t(can_frame.dlc - 1);
        (void)copy(can_frame.data + 1, can_frame.data + can_frame.dlc, payload_);
        break;
    }
    default:
    {
        return false;
    }
    }

    /*
     * Special case for anonymous transfers - trailing 8 bits of CAN ID must be ignored
     *  - Transfer ID (assumed zero)
     *  - Last Frame  (assumed true)
     *  - Frame Index (assumed zero)
     */
    if (src_node_id_.isBroadcast())
    {
        transfer_id_ = TransferID(0);
        last_frame_  = true;
        frame_index_ = 0;
    }

    return isValid();
}

template <int OFFSET, int WIDTH>
inline static uint32_t bitpack(uint32_t field)
{
    StaticAssert<(OFFSET >= 0)>::check();
    StaticAssert<(WIDTH > 0)>::check();
    StaticAssert<((OFFSET + WIDTH) <= 29)>::check();
    UAVCAN_ASSERT((field & ((1UL << WIDTH) - 1)) == field);
    return uint32_t((field & ((1UL << WIDTH) - 1)) << OFFSET);
}

bool Frame::compile(CanFrame& out_can_frame) const
{
    if (!isValid())
    {
        UAVCAN_ASSERT(0);        // This is an application error, so we need to maximize it.
        return false;
    }

    /*
     * Setting CAN ID field
     */
    // Common fields for messages and services
    out_can_frame.id =
        CanFrame::FlagEFF |
        bitpack<0, 3>(transfer_id_.get()) |
        bitpack<3, 1>(last_frame_) |
        /* TT-specific fields skipped */
        bitpack<27, 2>(transfer_priority_);

    if (transfer_type_ == TransferTypeServiceRequest ||
        transfer_type_ == TransferTypeServiceResponse)
    {
        out_can_frame.id |=
            bitpack<4, 6>(frame_index_) |
            bitpack<10, 7>(src_node_id_.get()) |
            bitpack<17, 9>(data_type_id_.get()) |
            bitpack<26, 1>((transfer_type_ == TransferTypeServiceRequest) ? 1U : 0U);
    }
    else if (transfer_type_ == TransferTypeMessageBroadcast ||
             transfer_type_ == TransferTypeMessageUnicast)
    {
        out_can_frame.id |=
            bitpack<4, 4>(frame_index_) |
            bitpack<8, 1>((transfer_type_ == TransferTypeMessageBroadcast) ? 1U : 0U) |
            bitpack<9, 7>(src_node_id_.get()) |
            bitpack<16, 11>(data_type_id_.get());
    }
    else
    {
        UAVCAN_ASSERT(0);
        return false;
    }

    /*
     * Setting payload
     */
    switch (transfer_type_)
    {
    case TransferTypeMessageBroadcast:
    {
        out_can_frame.dlc = uint8_t(payload_len_);
        (void)copy(payload_, payload_ + payload_len_, out_can_frame.data);
        break;
    }
    case TransferTypeServiceResponse:
    case TransferTypeServiceRequest:
    case TransferTypeMessageUnicast:
    {
        UAVCAN_ASSERT((payload_len_ + 1U) <= sizeof(out_can_frame.data));
        out_can_frame.data[0] = dst_node_id_.get();
        out_can_frame.dlc = uint8_t(payload_len_ + 1);
        (void)copy(payload_, payload_ + payload_len_, out_can_frame.data + 1);
        break;
    }
    default:
    {
        UAVCAN_ASSERT(0);
        return false;
    }
    }

    /*
     * Setting trailing bits of CAN ID for anonymous message
     * This overrides the following fields:
     *  - Transfer ID (assumed zero)
     *  - Last Frame  (assumed true)
     *  - Frame Index (assumed zero)
     */
    if (src_node_id_.isBroadcast())
    {
        uint8_t sum = 0;
        out_can_frame.id &= ~bitpack<0, 8>(sum);        // Clearing bits
        for (uint_fast8_t i = 0; i < payload_len_; i++)
        {
            sum =  static_cast<uint8_t>(sum + payload_[i]);
        }
        out_can_frame.id |= bitpack<0, 8>(sum);        // Setting the checksum
    }

    return true;
}

bool Frame::isValid() const
{
    /*
     * Frame index
     */
    if (frame_index_ > getMaxIndex())
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    if ((frame_index_ == getMaxIndex()) && !last_frame_)
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    /*
     * Node ID
     */
    if (!src_node_id_.isValid() ||
        !dst_node_id_.isValid())
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    if (src_node_id_.isUnicast() &&
        (src_node_id_ == dst_node_id_))
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    /*
     * Transfer type
     */
    if (transfer_type_ >= NumTransferTypes)
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    if ((transfer_type_ == TransferTypeMessageBroadcast) != dst_node_id_.isBroadcast())
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    // Anonymous transfers
    if (src_node_id_.isBroadcast() &&
        (!last_frame_ || (frame_index_ > 0) || (transfer_type_ != TransferTypeMessageBroadcast)))
    {
        return false;
    }

    /*
     * Payload
     */
    if (static_cast<int>(payload_len_) > getMaxPayloadLen())
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    /*
     * Data type ID
     */
    if (!data_type_id_.isValidForDataTypeKind(getDataTypeKindForTransferType(transfer_type_)))
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    /*
     * Priority
     */
    if (transfer_priority_ >= NumTransferPriorities)
    {
        UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
        return false;
    }

    if (transfer_type_ == TransferTypeServiceRequest ||
        transfer_type_ == TransferTypeServiceResponse)
    {
        if (transfer_priority_ != TransferPriorityService)
        {
            UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
            return false;
        }
    }

    return true;
}

bool Frame::operator==(const Frame& rhs) const
{
    return
        (transfer_priority_ == rhs.transfer_priority_) &&
        (transfer_type_     == rhs.transfer_type_) &&
        (data_type_id_      == rhs.data_type_id_) &&
        (src_node_id_       == rhs.src_node_id_) &&
        (dst_node_id_       == rhs.dst_node_id_) &&
        (frame_index_       == rhs.frame_index_) &&
        (transfer_id_       == rhs.transfer_id_) &&
        (last_frame_        == rhs.last_frame_) &&
        (payload_len_       == rhs.payload_len_) &&
        equal(payload_, payload_ + payload_len_, rhs.payload_);
}

#if UAVCAN_TOSTRING
std::string Frame::toString() const
{
    /*
     *  - Priority
     *  - Data Type ID
     *  - Transfer Type
     *  - Source Node ID
     *  - Frame Index
     *  - Last Frame
     *  - Transfer ID
     */
    static const int BUFLEN = 100;
    char buf[BUFLEN];
    int ofs = snprintf(buf, BUFLEN, "prio=%d dtid=%d tt=%d snid=%d dnid=%d idx=%d last=%d tid=%d payload=[",
                       int(transfer_priority_), int(data_type_id_.get()), int(transfer_type_), int(src_node_id_.get()),
                       int(dst_node_id_.get()), int(frame_index_), int(last_frame_), int(transfer_id_.get()));

    for (unsigned i = 0; i < payload_len_; i++)
    {
        // Coverity Scan complains about payload_ being not default initialized. This is OK.
        // coverity[read_parm_fld]
        ofs += snprintf(buf + ofs, unsigned(BUFLEN - ofs), "%02x", payload_[i]);
        if ((i + 1) < payload_len_)
        {
            ofs += snprintf(buf + ofs, unsigned(BUFLEN - ofs), " ");
        }
    }
    (void)snprintf(buf + ofs, unsigned(BUFLEN - ofs), "]");
    return std::string(buf);
}
#endif

/**
 * RxFrame
 */
bool RxFrame::parse(const CanRxFrame& can_frame)
{
    if (!Frame::parse(can_frame))
    {
        return false;
    }
    if (can_frame.ts_mono.isZero())  // Monotonic timestamps are mandatory.
    {
        UAVCAN_ASSERT(0);                   // If it is not set, it's a driver failure.
        return false;
    }
    ts_mono_ = can_frame.ts_mono;
    ts_utc_ = can_frame.ts_utc;
    iface_index_ = can_frame.iface_index;
    return true;
}

#if UAVCAN_TOSTRING
std::string RxFrame::toString() const
{
    std::string out = Frame::toString();
    out.reserve(128);
    out += " ts_m="   + ts_mono_.toString();
    out += " ts_utc=" + ts_utc_.toString();
    out += " iface=";
    out += char('0' + iface_index_);
    return out;
}
#endif

}
<|endoftext|>


<commit_before>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/system/pivot_command.hpp"

#include "vast/defaults.hpp"
#include "vast/detail/assert.hpp"
#include "vast/detail/make_io_stream.hpp"
#include "vast/error.hpp"
#include "vast/format/csv.hpp"
#include "vast/format/json.hpp"
#include "vast/format/pcap.hpp"
#include "vast/format/zeek.hpp"
#include "vast/logger.hpp"
#include "vast/scope_linked.hpp"
#include "vast/system/atoms.hpp"
#include "vast/system/read_query.hpp"
#include "vast/system/signal_monitor.hpp"
#include "vast/system/sink.hpp"
#include "vast/system/sink_command.hpp"
#include "vast/system/spawn_or_connect_to_node.hpp"
#include "vast/system/tracker.hpp"

#include <caf/event_based_actor.hpp>
#include <caf/scoped_actor.hpp>
#include <caf/settings.hpp>
#include <caf/stateful_actor.hpp>
#include <caf/typed_event_based_actor.hpp>

#include <csignal>
#include <string>
#include <string_view>

using namespace std::chrono_literals;

namespace vast::system {

namespace {

template <class Writer>
caf::expected<caf::actor>
make_writer(caf::actor_system& sys, const caf::settings& options) {
  using defaults = typename Writer::defaults;
  using ostream_ptr = std::unique_ptr<std::ostream>;
  std::string category = defaults::category;
  if constexpr (std::is_constructible_v<Writer, ostream_ptr>) {
    auto output = get_or(options, category + ".write", defaults::write);
    auto uds = get_or(options, category + ".uds", false);
    auto out = detail::make_output_stream(output, uds);
    if (!out)
      return out.error();
    Writer writer{std::move(*out)};
    return sys.spawn(sink<Writer>, std::move(writer), max_events);
  } else {
    Writer writer;
    return sys.spawn(sink<Writer>, std::move(writer), max_events);
  }
}

} // namespace

caf::message
pivot_command(const command::invocation& invocation, caf::actor_system& sys) {
  VAST_TRACE(invocation);
  // Read query from input file, STDIN or CLI arguments.
  auto query = read_query(invocation, "export.read", size_t{1});
  if (!query)
    return caf::make_message(std::move(query.error()));
  auto& options = invocation.options;
  auto& target = invocation.arguments[0];
  // using caf::get_or;
  auto limit
    = get_or(options, "export.max-events", defaults::export_::max_events);
  caf::actor writer;
  if (detail::starts_with(target, "pcap")) {
    using defaults_t = defaults::export_::pcap;
    std::string category = defaults_t::category;
    auto output = get_or(options, category + ".write", defaults_t::write);
    auto flush = get_or(options, category + ".flush-interval",
                        defaults_t::flush_interval);
    format::pcap::writer w{output, flush};
    writer = sys.spawn(sink<format::pcap::writer>, std::move(w), limit);
  } else if (detail::starts_with(target, "suricata")) {
    auto w = make_writer<format::json::writer>(sys, invocation.options);
    if (!w)
      return make_message(w.error());
    writer = *w;
  } else if (detail::starts_with(target, "zeek")) {
    auto w = make_writer<format::zeek::writer>(sys, invocation.options);
    if (!w)
      return make_message(w.error());
    writer = *w;
  } else
    return make_message(make_error(ec::unimplemented, "pivoting is only "
                                                      "implemented for pcap, "
                                                      "suricata and zeek"));
  caf::scoped_actor self{sys};
  // Get VAST node.
  auto node_opt
    = spawn_or_connect_to_node(self, invocation.options, content(sys.config()));
  if (auto err = caf::get_if<caf::error>(&node_opt))
    return caf::make_message(std::move(*err));
  auto& node = caf::holds_alternative<caf::actor>(node_opt)
                 ? caf::get<caf::actor>(node_opt)
                 : caf::get<scope_linked_actor>(node_opt).get();
  VAST_ASSERT(node != nullptr);
  // TODO(ch9412): Factor guard into a function.
  // Start signal monitor.
  std::thread sig_mon_thread;
  auto guard = signal_monitor::run_guarded(sig_mon_thread, sys, 750ms, self);
  // Spawn exporter at the node.
  caf::actor exp;
  auto exporter_invocation
    = command::invocation{invocation.options, "spawn exporter", {*query}};
  VAST_DEBUG(invocation.full_name,
             "spawns exporter with parameters:", exporter_invocation);
  error err;
  self->request(node, caf::infinite, std::move(exporter_invocation))
    .receive(
      [&](caf::actor& a) {
        exp = std::move(a);
        if (!exp)
          err = make_error(ec::invalid_result, "remote spawn returned nullptr");
      },
      [&](error& e) { err = std::move(e); });
  if (err) {
    self->send_exit(writer, caf::exit_reason::user_shutdown);
    return caf::make_message(std::move(err));
  }
  // Spawn pivoter at the node.
  caf::actor piv;
  auto pivoter_invocation = command::invocation{
    invocation.options, "spawn pivoter", {invocation.arguments[0], *query}};
  VAST_DEBUG(invocation.full_name,
             "spawns exporter with parameters:", pivoter_invocation);
  self->request(node, caf::infinite, std::move(pivoter_invocation))
    .receive(
      [&](caf::actor& a) {
        piv = std::move(a);
        if (!piv)
          err = make_error(ec::invalid_result, "remote spawn returned nullptr");
      },
      [&](error& e) { err = std::move(e); });
  if (err) {
    self->send_exit(exp, caf::exit_reason::user_shutdown);
    self->send_exit(writer, caf::exit_reason::user_shutdown);
    return caf::make_message(std::move(err));
  }
  self->request(node, caf::infinite, get_atom::value)
    .receive(
      [&](const std::string& id, system::registry& reg) {
        // Assign accountant to sink.
        VAST_DEBUG(invocation.full_name, "assigns accountant from node", id,
                   "to new sink");
        auto er = reg.components[id].find("accountant");
        if (er != reg.components[id].end()) {
          auto accountant = er->second.actor;
          self->send(writer, caf::actor_cast<accountant_type>(accountant));
        }
      },
      [&](error& e) { err = std::move(e); });
  if (err) {
    self->send_exit(writer, caf::exit_reason::user_shutdown);
    return caf::make_message(std::move(err));
  }
  self->monitor(writer);
  self->monitor(piv);
  // Start the exporter.
  self->send(exp, system::sink_atom::value, piv);
  // (Ab)use query_statistics as done message.
  self->send(exp, system::statistics_atom::value, piv);
  self->send(piv, system::sink_atom::value, writer);
  self->send(exp, system::run_atom::value);
  auto stop = false;
  self
    ->do_receive(
      [&](caf::down_msg& msg) {
        if (msg.source == node) {
          VAST_DEBUG_ANON(__func__, "received DOWN from node");
          self->send_exit(writer, caf::exit_reason::user_shutdown);
          self->send_exit(exp, caf::exit_reason::user_shutdown);
          self->send_exit(piv, caf::exit_reason::user_shutdown);
        } else if (msg.source == piv) {
          VAST_DEBUG(invocation.full_name, "received DOWN from pivoter");
          self->send_exit(exp, caf::exit_reason::user_shutdown);
          self->send_exit(writer, caf::exit_reason::user_shutdown);
        } else if (msg.source == writer) {
          VAST_DEBUG(invocation.full_name, "received DOWN from sink");
          self->send_exit(exp, caf::exit_reason::user_shutdown);
          self->send_exit(piv, caf::exit_reason::user_shutdown);
        } else {
          VAST_ASSERT(!"received DOWN from inexplicable actor");
        }
        if (msg.reason) {
          VAST_WARNING(invocation.full_name, "received error message:",
                       self->system().render(msg.reason));
          err = std::move(msg.reason);
        }
        stop = true;
      },
      [&](system::signal_atom, int signal) {
        VAST_DEBUG(invocation.full_name, "got " << ::strsignal(signal));
        if (signal == SIGINT || signal == SIGTERM) {
          self->send_exit(exp, caf::exit_reason::user_shutdown);
          self->send_exit(piv, caf::exit_reason::user_shutdown);
          self->send_exit(writer, caf::exit_reason::user_shutdown);
        }
      })
    .until([&] { return stop; });
  if (err)
    return caf::make_message(std::move(err));
  return caf::none;
}

} // namespace vast::system
<commit_msg>Use node control functions in pivoter command<commit_after>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/system/pivot_command.hpp"

#include "vast/defaults.hpp"
#include "vast/detail/assert.hpp"
#include "vast/detail/make_io_stream.hpp"
#include "vast/error.hpp"
#include "vast/format/csv.hpp"
#include "vast/format/json.hpp"
#include "vast/format/pcap.hpp"
#include "vast/format/zeek.hpp"
#include "vast/logger.hpp"
#include "vast/scope_linked.hpp"
#include "vast/system/atoms.hpp"
#include "vast/system/node_control.hpp"
#include "vast/system/read_query.hpp"
#include "vast/system/signal_monitor.hpp"
#include "vast/system/sink.hpp"
#include "vast/system/sink_command.hpp"
#include "vast/system/spawn_or_connect_to_node.hpp"
#include "vast/system/tracker.hpp"

#include <caf/event_based_actor.hpp>
#include <caf/scoped_actor.hpp>
#include <caf/settings.hpp>
#include <caf/stateful_actor.hpp>
#include <caf/typed_event_based_actor.hpp>

#include <csignal>
#include <string>
#include <string_view>

using namespace std::chrono_literals;

namespace vast::system {

namespace {

template <class Writer>
caf::expected<caf::actor>
make_writer(caf::actor_system& sys, const caf::settings& options) {
  using defaults = typename Writer::defaults;
  using ostream_ptr = std::unique_ptr<std::ostream>;
  std::string category = defaults::category;
  if constexpr (std::is_constructible_v<Writer, ostream_ptr>) {
    auto output = get_or(options, category + ".write", defaults::write);
    auto uds = get_or(options, category + ".uds", false);
    auto out = detail::make_output_stream(output, uds);
    if (!out)
      return out.error();
    Writer writer{std::move(*out)};
    return sys.spawn(sink<Writer>, std::move(writer), max_events);
  } else {
    Writer writer;
    return sys.spawn(sink<Writer>, std::move(writer), max_events);
  }
}

} // namespace

caf::message
pivot_command(const command::invocation& invocation, caf::actor_system& sys) {
  VAST_TRACE(invocation);
  // Read query from input file, STDIN or CLI arguments.
  auto query = read_query(invocation, "export.read", size_t{1});
  if (!query)
    return caf::make_message(std::move(query.error()));
  auto& options = invocation.options;
  auto& target = invocation.arguments[0];
  // using caf::get_or;
  auto limit
    = get_or(options, "export.max-events", defaults::export_::max_events);
  caf::actor writer;
  if (detail::starts_with(target, "pcap")) {
    using defaults_t = defaults::export_::pcap;
    std::string category = defaults_t::category;
    auto output = get_or(options, category + ".write", defaults_t::write);
    auto flush = get_or(options, category + ".flush-interval",
                        defaults_t::flush_interval);
    format::pcap::writer w{output, flush};
    writer = sys.spawn(sink<format::pcap::writer>, std::move(w), limit);
  } else if (detail::starts_with(target, "suricata")) {
    auto w = make_writer<format::json::writer>(sys, invocation.options);
    if (!w)
      return make_message(w.error());
    writer = *w;
  } else if (detail::starts_with(target, "zeek")) {
    auto w = make_writer<format::zeek::writer>(sys, invocation.options);
    if (!w)
      return make_message(w.error());
    writer = *w;
  } else
    return make_message(make_error(ec::unimplemented, "pivoting is only "
                                                      "implemented for pcap, "
                                                      "suricata and zeek"));
  caf::scoped_actor self{sys};
  auto writer_guard = caf::detail::make_scope_guard(
    [&] { self->send_exit(writer, caf::exit_reason::user_shutdown); });
  // Get VAST node.
  auto node_opt
    = spawn_or_connect_to_node(self, invocation.options, content(sys.config()));
  if (auto err = caf::get_if<caf::error>(&node_opt))
    return caf::make_message(std::move(*err));
  auto& node = caf::holds_alternative<caf::actor>(node_opt)
                 ? caf::get<caf::actor>(node_opt)
                 : caf::get<scope_linked_actor>(node_opt).get();
  VAST_ASSERT(node != nullptr);
  // TODO(ch9412): Factor guard into a function.
  // Start signal monitor.
  std::thread sig_mon_thread;
  auto signal_guard
    = signal_monitor::run_guarded(sig_mon_thread, sys, 750ms, self);
  // Spawn exporter at the node.
  auto spawn_exporter
    = command::invocation{invocation.options, "spawn exporter", {*query}};
  VAST_DEBUG(&invocation, "spawns exporter with parameters:", spawn_exporter);
  auto exp = spawn_at_node(self, node, spawn_exporter);
  if (!exp)
    return caf::make_message(std::move(exp.error()));
  auto exp_guard = caf::detail::make_scope_guard(
    [&] { self->send_exit(*exp, caf::exit_reason::user_shutdown); });
  // Spawn pivoter at the node.
  auto spawn_pivoter = command::invocation{
    invocation.options, "spawn pivoter", {invocation.arguments[0], *query}};
  VAST_DEBUG(&invocation, "spawns pivoter with parameters:", spawn_pivoter);
  auto piv = spawn_at_node(self, node, spawn_pivoter);
  if (!piv)
    return caf::make_message(std::move(piv.error()));
  auto piv_guard = caf::detail::make_scope_guard(
    [&] { self->send_exit(*piv, caf::exit_reason::user_shutdown); });
  // Register the accountant at the Sink.
  auto components = get_node_component<accountant_atom>(self, node);
  if (!components)
    return caf::make_message(std::move(components.error()));
  auto& [accountant] = *components;
  if (accountant) {
    VAST_DEBUG(invocation.full_name, "assigns accountant to writer");
    self->send(writer, caf::actor_cast<accountant_type>(*accountant));
  }
  caf::error err;
  self->monitor(writer);
  self->monitor(*piv);
  // Start the exporter.
  self->send(*exp, system::sink_atom::value, *piv);
  // (Ab)use query_statistics as done message.
  self->send(*exp, system::statistics_atom::value, *piv);
  self->send(*piv, system::sink_atom::value, writer);
  self->send(*exp, system::run_atom::value);
  auto stop = false;
  self
    ->do_receive(
      [&](caf::down_msg& msg) {
        if (msg.source == node) {
          VAST_DEBUG(invocation.full_name, "received DOWN from node");
        } else if (msg.source == *piv) {
          VAST_DEBUG(invocation.full_name, "received DOWN from pivoter");
          piv_guard.disable();
        } else if (msg.source == writer) {
          VAST_DEBUG(invocation.full_name, "received DOWN from sink");
          writer_guard.disable();
        } else {
          VAST_ASSERT(!"received DOWN from inexplicable actor");
        }
        if (msg.reason) {
          VAST_WARNING(invocation.full_name, "received error message:",
                       self->system().render(msg.reason));
          err = std::move(msg.reason);
        }
        stop = true;
      },
      [&](system::signal_atom, int signal) {
        VAST_DEBUG(invocation.full_name, "got " << ::strsignal(signal));
        if (signal == SIGINT || signal == SIGTERM) {
          stop = true;
        }
      })
    .until([&] { return stop; });
  if (err)
    return caf::make_message(std::move(err));
  return caf::none;
}

} // namespace vast::system
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sal.hxx"

#include "system.h"
#include <osl/process.h>
#include <sal/types.h>

#ifdef __cplusplus
extern "C" {
#endif

// Prototypes for initialization and deinitialization of SAL library

void SAL_CALL sal_detail_initialize(int argc, char ** argv)
{
    WSADATA wsaData;
    int     error;
    WORD    wVersionRequested;

    wVersionRequested = MAKEWORD(1, 1);

    error = WSAStartup(wVersionRequested, &wsaData);
    if ( 0 == error )
    {
        WORD wMajorVersionRequired = 1;
        WORD wMinorVersionRequired = 1;

        if ((LOBYTE(wsaData.wVersion) <  wMajorVersionRequired) ||
            (LOBYTE(wsaData.wVersion) == wMajorVersionRequired) &&
            ((HIBYTE(wsaData.wVersion) < wMinorVersionRequired)))
            {
                // How to handle a very unlikely error ???
            }
    }
    else
    {
        // How to handle a very unlikely error ???
    }

    osl_setCommandArgs(argc, argv);
}

void SAL_CALL sal_detail_deinitialize()
{
    if ( SOCKET_ERROR == WSACleanup() )
    {
        // We should never reach this point or we did wrong elsewhere
    }
}

#ifdef __cplusplus
}   // extern "C"
#endif
<commit_msg>mhu23 #i113531# use recommended Windows linker flags and DLL search path.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sal.hxx"

#include "system.h"
#include <osl/process.h>
#include <sal/types.h>

#ifdef __cplusplus
extern "C" {
#endif

// Prototypes for initialization and deinitialization of SAL library

void SAL_CALL sal_detail_initialize(int argc, char ** argv)
{
    // SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
    // SetDllDirectoryW(L"");
    // SetSearchPathMode(
    //   BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT);
    HMODULE h = GetModuleHandleW(L"kernel32.dll");
    if (h != 0) {
        FARPROC p = GetProcAddress(h, "SetProcessDEPPolicy");
        if (p != 0) {
            reinterpret_cast< BOOL (WINAPI *)(DWORD) >(p)(0x00000001);
    }
    p = GetProcAddress(h, "SetDllDirectoryW");
        if (p != 0) {
            reinterpret_cast< BOOL (WINAPI *)(LPCWSTR) >(p)(L"");
        }
        p = GetProcAddress(h, "SetSearchPathMode");
        if (p != 0) {
            reinterpret_cast< BOOL (WINAPI *)(DWORD) >(p)(0x8001);
        }
    }

    WSADATA wsaData;
    int     error;
    WORD    wVersionRequested;

    wVersionRequested = MAKEWORD(1, 1);

    error = WSAStartup(wVersionRequested, &wsaData);
    if ( 0 == error )
    {
        WORD wMajorVersionRequired = 1;
        WORD wMinorVersionRequired = 1;

        if ((LOBYTE(wsaData.wVersion) <  wMajorVersionRequired) ||
            (LOBYTE(wsaData.wVersion) == wMajorVersionRequired) &&
            ((HIBYTE(wsaData.wVersion) < wMinorVersionRequired)))
            {
                // How to handle a very unlikely error ???
            }
    }
    else
    {
        // How to handle a very unlikely error ???
    }

    osl_setCommandArgs(argc, argv);
}

void SAL_CALL sal_detail_deinitialize()
{
    if ( SOCKET_ERROR == WSACleanup() )
    {
        // We should never reach this point or we did wrong elsewhere
    }
}

#ifdef __cplusplus
}   // extern "C"
#endif
<|endoftext|>


<commit_before>/*
 alm_cui.cpp

 Copyright (c) 2014, 2015, 2016 Terumasa Tadano

 This file is distributed under the terms of the MIT license.
 Please see the file 'LICENCE.txt' in the root directory
 or http://opensource.org/licenses/mit-license.php for information.
*/

#include "alm_cui.h"
#include "alm.h"
#include "input_parser.h"
#include "timer.h"
#include "version.h"
#include "writer.h"
#include <iostream>
#include <iomanip>

#ifdef _OPENMP

#include <omp.h>

#endif

using namespace ALM_NS;

ALMCUI::ALMCUI() {}

ALMCUI::~ALMCUI() {}

void ALMCUI::run(const int narg,
                 char **arg) const
{
    auto alm = new ALM();

    // alm->mode is set herein.
    auto input_parser = new InputParser();
    input_parser->run(alm, narg, arg);
    auto run_mode = input_parser->get_run_mode();
    delete input_parser;

    if (alm->get_verbosity() > 0) {
        std::cout << " +-----------------------------------------------------------------+" << std::endl;
        std::cout << " +                         Program ALM                             +" << std::endl;
        std::cout << " +                             Ver.";
        std::cout << std::setw(7) << ALAMODE_VERSION;
        std::cout << "                       +" << std::endl;
        std::cout << " +-----------------------------------------------------------------+" << std::endl;
        std::cout << std::endl;
#ifdef _OPENMP
        std::cout << " Number of OpenMP threads = "
                  << omp_get_max_threads() << std::endl << std::endl;
#endif

        std::cout << " Job started at " << alm->timer->DateAndTime() << std::endl;
    }

    auto writer = new Writer();

    if (alm->get_verbosity() > 0) {
        writer->write_input_vars(alm, run_mode);
    }

    alm->init_fc_table();

    if (run_mode == "optimize") {
        alm->run_optimize();
        if (alm->get_optimizer_control().linear_model == 1 ||
            (alm->get_optimizer_control().linear_model >= 2
             && alm->get_optimizer_control().cross_validation == 0)) {
            writer->writeall(alm);
        }
    } else if (run_mode == "suggest") {
        alm->run_suggest();
        writer->write_displacement_pattern(alm);
    }
    delete writer;

    if (alm->get_verbosity() > 0) {
        std::cout << std::endl << " Job finished at "
                  << alm->timer->DateAndTime() << std::endl;
    }

    delete alm;
}
<commit_msg>Minor output formatting<commit_after>/*
 alm_cui.cpp

 Copyright (c) 2014, 2015, 2016 Terumasa Tadano

 This file is distributed under the terms of the MIT license.
 Please see the file 'LICENCE.txt' in the root directory
 or http://opensource.org/licenses/mit-license.php for information.
*/

#include "alm_cui.h"
#include "alm.h"
#include "input_parser.h"
#include "timer.h"
#include "version.h"
#include "writer.h"
#include <iostream>
#include <iomanip>

#ifdef _OPENMP

#include <omp.h>

#endif

using namespace ALM_NS;

ALMCUI::ALMCUI() {}

ALMCUI::~ALMCUI() {}

void ALMCUI::run(const int narg,
                 char **arg) const
{
    auto alm = new ALM();

    // alm->mode is set herein.
    auto input_parser = new InputParser();
    input_parser->run(alm, narg, arg);
    auto run_mode = input_parser->get_run_mode();
    delete input_parser;

    if (alm->get_verbosity() > 0) {
        std::cout << " +-----------------------------------------------------------------+" << std::endl;
        std::cout << " +                         Program ALM                             +" << std::endl;
        std::cout << " +                             Ver.";
        std::cout << std::setw(7) << ALAMODE_VERSION;
        std::cout << "                         +" << std::endl;
        std::cout << " +-----------------------------------------------------------------+" << std::endl;
        std::cout << std::endl;
#ifdef _OPENMP
        std::cout << " Number of OpenMP threads = "
                  << omp_get_max_threads() << std::endl << std::endl;
#endif

        std::cout << " Job started at " << alm->timer->DateAndTime() << std::endl;
    }

    auto writer = new Writer();

    if (alm->get_verbosity() > 0) {
        writer->write_input_vars(alm, run_mode);
    }

    alm->init_fc_table();

    if (run_mode == "optimize") {
        alm->run_optimize();
        if (alm->get_optimizer_control().linear_model == 1 ||
            (alm->get_optimizer_control().linear_model >= 2
             && alm->get_optimizer_control().cross_validation == 0)) {
            writer->writeall(alm);
        }
    } else if (run_mode == "suggest") {
        alm->run_suggest();
        writer->write_displacement_pattern(alm);
    }
    delete writer;

    if (alm->get_verbosity() > 0) {
        std::cout << std::endl << " Job finished at "
                  << alm->timer->DateAndTime() << std::endl;
    }

    delete alm;
}
<|endoftext|>