<commit_before>#ifndef __BTREE_NODE_HPP__
#define __BTREE_NODE_HPP__

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "utils.hpp"
#include "buffer_cache/types.hpp"

static const char btree_superblock_magic[] = {'b', 't', 'r', 'e', 'e', 's', 'b', 'k'};

struct btree_superblock_t {

    char magic[sizeof(btree_superblock_magic)];

    block_id_t root_block;
};

#define MAX_KEY_SIZE 250

enum btree_node_type_enum {
    // Choose 1 and 2 instead of 0 and 1 to make it less likely that garbage will be interpreted as
    // a valid node
    btree_node_type_invalid = 0,
    btree_node_type_leaf = 1,
    btree_node_type_internal = 2
};

typedef uint16_t btree_node_type;

//Note: This struct is stored directly on disk.  Changing it invalidates old data.
struct btree_internal_node {
    btree_node_type type;
    uint16_t npairs;
    uint16_t frontmost_offset;
    uint16_t pair_offsets[0];
};

typedef btree_internal_node internal_node_t;

//Note: This struct is stored directly on disk.  Changing it invalidates old data.
struct btree_leaf_node {
    btree_node_type type;
    uint16_t npairs;
    uint16_t frontmost_offset; // The smallest offset in pair_offsets
    uint16_t pair_offsets[0];
};

typedef btree_leaf_node leaf_node_t;

enum metadata_flags {
    MEMCACHED_FLAGS   = 0x01,
    MEMCACHED_CAS     = 0x02,
    MEMCACHED_EXPTIME = 0x04,
    // DELETE_QUEUE   = 0x08, // If we implement this.
    LARGE_VALUE       = 0x80
};

// Note: Changing this struct changes the format of the data stored on disk.
// If you change this struct, previous stored data will be misinterpreted.
struct btree_key {
    uint8_t size;
    char contents[0];
    void print() {
        //printf("%*.*s", size, size, contents);
        printf("%d", size);
    }
};

struct btree_value {
    uint8_t size;
    byte metadata_flags;
    byte contents[0];

    void init() { // XXX
    }

    uint16_t mem_size() {
        //assert(!is_large());
        return value_offset() + size;
                //(is_large() ? sizeof(block_id_t) + (assert(0),0) : value_size());
    }

    uint32_t value_size() {
        if (is_large()) {
            // Size is stored in contents along with the block ID.
            // TODO: Should the size go here or in the index block? Should other metadata go here?
            // TODO: Is it a good idea to store other metadata in here?
            // TODO: If we really wanted to, we could save a byte by using the size field and only three bytes of contents.
            assert(*lv_size_addr() > MAX_IN_NODE_VALUE_SIZE);
            return *lv_size_addr();
        } else {
            return size;
        }
    }

    void value_size(uint32_t new_size) {
        if (new_size <= MAX_IN_NODE_VALUE_SIZE) {
            if (is_large()) {
                clear_space((byte *) lv_size_addr(), sizeof(uint32_t), lv_size_offset());
                metadata_flags &= ~LARGE_VALUE;
            }
            size = new_size;
        } else {
            if (!is_large()) {
                metadata_flags |= LARGE_VALUE;
                make_space((byte *) lv_size_addr(), sizeof(uint32_t), lv_size_offset());
            }
            size = sizeof(block_id_t);
            *lv_size_addr() = new_size;
        }
    }

    typedef uint32_t mcflags_t;
    typedef uint64_t cas_t;

    // TODO: We assume that time_t can be converted to an exptime_t,
    // which is 32 bits.  We may run into problems in 2038 or 2106.
    typedef uint32_t exptime_t;

    // Every value has mcflags, but they're very often 0, in which case we just
    // store a bit instead of 4 bytes.
    bool has_mcflags() { return metadata_flags & MEMCACHED_FLAGS;   }
    bool has_cas()     { return metadata_flags & MEMCACHED_CAS;     }
    bool has_exptime() { return metadata_flags & MEMCACHED_EXPTIME; }
    bool is_large()    { return metadata_flags & LARGE_VALUE;       }

    uint8_t mcflags_offset() { return 0;                                                    }
    uint8_t exptime_offset() { return mcflags_offset() + sizeof(mcflags_t) * has_mcflags(); }
    uint8_t cas_offset()     { return exptime_offset() + sizeof(exptime_t) * has_exptime(); }
    uint8_t lv_size_offset() { return     cas_offset() + sizeof(cas_t)     * has_cas();     }
    uint8_t value_offset()   { return lv_size_offset() + sizeof(uint32_t)  * is_large(); }

    mcflags_t *mcflags_addr() { return (mcflags_t *) (contents + mcflags_offset()); }
    exptime_t *exptime_addr() { return (exptime_t *) (contents + exptime_offset()); }
    cas_t         *cas_addr() { return (cas_t     *) (contents +     cas_offset()); }
    uint32_t  *lv_size_addr() { return (uint32_t  *) (contents + lv_size_offset()); }
    byte             *value() { return (byte      *) (contents +   value_offset()); }

    block_id_t lv_index_block_id() { return * (block_id_t *) value(); }
    void set_lv_index_block_id(block_id_t block_id) {
        assert(is_large());
        *(block_id_t *) value() = block_id;
    }

    mcflags_t mcflags() { return has_mcflags() ? *mcflags_addr() : 0; }
    exptime_t exptime() { return has_exptime() ? *exptime_addr() : 0; }
    cas_t         cas() { // We shouldn't be asking for a value's CAS unless we know it has one.
        assert(has_cas());
        return *cas_addr();
    }

    void clear_space(byte *faddr, uint8_t fsize, uint8_t offset) {
        memmove(faddr, faddr + fsize, mem_size() - offset - fsize);
        //size -= fsize;
    }

    void make_space(byte *faddr, uint8_t fsize, uint8_t offset) { // XXX This assumes there's enough space allocated to move the value into.
        assert(mem_size() + fsize <= MAX_TOTAL_NODE_CONTENTS_SIZE);
        //size += fsize;
        memmove(faddr + fsize, faddr, mem_size() - offset);
    }

    void set_mcflags(mcflags_t new_mcflags) {
        if (has_mcflags() && new_mcflags == 0) { // Flags is being set to 0, so we clear the 4 bytes we kept for it.
            clear_space((byte *) mcflags_addr(), sizeof(mcflags_t), mcflags_offset());
            metadata_flags &= ~MEMCACHED_FLAGS;
        } else if (!has_mcflags() && new_mcflags) { // Make space for non-zero mcflags.
            metadata_flags |= MEMCACHED_FLAGS;
            make_space((byte *) mcflags_addr(), sizeof(mcflags_t), mcflags_offset());
        }
        if (new_mcflags) { // We've made space, so copy the mcflags over.
            *mcflags_addr() = new_mcflags;
        }
    }

    void set_exptime(exptime_t new_exptime) {
        if (has_exptime() && new_exptime == 0) { // Exptime is being set to 0, so we clear the 4 bytes we kept for it.
            clear_space((byte *) exptime_addr(), sizeof(exptime_t), exptime_offset());
            metadata_flags &= ~MEMCACHED_EXPTIME;
        } else if (!has_exptime() && new_exptime) { // Make space for non-zero exptime.
            metadata_flags |= MEMCACHED_EXPTIME;
            make_space((byte *) exptime_addr(), sizeof(exptime_t), exptime_offset());
        }
        if (new_exptime) {
            *exptime_addr() = new_exptime;
        }
    }

    bool expired() {
        return exptime() ? time(NULL) >= exptime() : false;
    }

    // CAS is treated differently from the other fields. Values initially don't
    // have a CAS; once it's added, though, we assume it's there for good. An
    // existing CAS should never be set to 0.
    void set_cas(cas_t new_cas) {
        if (!new_cas) {
            assert(!has_cas());
            return;
        }
        if (!has_cas()) { // Make space for CAS.
            metadata_flags |= MEMCACHED_CAS;
            make_space((byte *) cas_addr(), sizeof(cas_t), cas_offset());
        }
        *cas_addr() = new_cas;
    }

    void print() {
        printf("%*.*s", size, size, value());
    }
};

// A btree_node is either a btree_internal_node or a btree_leaf_node.
//
// Note: &type == &internal.type == &leaf.type.
//
// Note: The reason this is not a struct btree_node { btree_node_type
// tag; union { btree_internal_node internal; btree_leaf_node leaf; }
// u; } is that btree_node used to superclass
// btree_{leaf|internal}_node, with one member, type.  A lot of code
// freely casts between a subclass and parent class type.
union btree_node {
    btree_node_type type;
    btree_internal_node internal;
    btree_leaf_node leaf;
};

typedef btree_node node_t;

class node_handler {
    public:
        static bool is_leaf(const btree_node *node) {
            assert(node->type == btree_node_type_leaf || node->type == btree_node_type_internal);
            return node->type == btree_node_type_leaf;
        }

        static bool is_internal(const btree_node *node) {
            assert(node->type == btree_node_type_leaf || node->type == btree_node_type_internal);
            return node->type == btree_node_type_internal;
        }

        static void str_to_key(char *str, btree_key *buf) {
            int len = strlen(str);
            check("string too long", len > MAX_KEY_SIZE);
            memcpy(buf->contents, str, len);
            buf->size = (unsigned char)len;
        }

        static bool is_underfull(size_t block_size, const btree_node *node);
        static bool is_mergable(size_t block_size, const btree_node *node, const btree_node *sibling, const btree_node *parent);
        static int nodecmp(const btree_node *node1, const btree_node *node2);
        static void merge(size_t block_size, btree_node *node, btree_node *rnode, btree_key *key_to_remove, btree_node *parent);
        static void remove(size_t block_size, btree_node *node, btree_key *key);
        static bool level(size_t block_size, btree_node *node, btree_node *rnode, btree_key *key_to_replace, btree_key *replacement_key, btree_node *parent);

        static void print(const btree_node *node);

        static void validate(size_t block_size, const btree_node *node);

        static inline const btree_node* node(const void *ptr) {
            return (const btree_node *) ptr;
        }
        static inline btree_node* node(void *ptr) {
            return (btree_node *) ptr;
        }
};

inline void keycpy(btree_key *dest, btree_key *src) {
    memcpy(dest, src, sizeof(btree_key) + src->size);
}

inline void valuecpy(btree_value *dest, btree_value *src) {
    memcpy(dest, src, sizeof(btree_value) + src->mem_size());
}

#endif // __BTREE_NODE_HPP__
<commit_msg>Made btree_superblock_t::database_exists an int64_t.<commit_after>#ifndef __BTREE_NODE_HPP__
#define __BTREE_NODE_HPP__

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "utils.hpp"
#include "buffer_cache/types.hpp"

static const char btree_superblock_magic[] = {'b', 't', 'r', 'e', 'e', 's', 'b', 'k'};

struct btree_superblock_t {

    char magic[sizeof(btree_superblock_magic)];

    int64_t database_exists;
    block_id_t root_block;
};

#define MAX_KEY_SIZE 250

enum btree_node_type_enum {
    // Choose 1 and 2 instead of 0 and 1 to make it less likely that garbage will be interpreted as
    // a valid node
    btree_node_type_invalid = 0,
    btree_node_type_leaf = 1,
    btree_node_type_internal = 2
};

typedef uint16_t btree_node_type;

//Note: This struct is stored directly on disk.  Changing it invalidates old data.
struct btree_internal_node {
    btree_node_type type;
    uint16_t npairs;
    uint16_t frontmost_offset;
    uint16_t pair_offsets[0];
};

typedef btree_internal_node internal_node_t;

//Note: This struct is stored directly on disk.  Changing it invalidates old data.
struct btree_leaf_node {
    btree_node_type type;
    uint16_t npairs;
    uint16_t frontmost_offset; // The smallest offset in pair_offsets
    uint16_t pair_offsets[0];
};

typedef btree_leaf_node leaf_node_t;

enum metadata_flags {
    MEMCACHED_FLAGS   = 0x01,
    MEMCACHED_CAS     = 0x02,
    MEMCACHED_EXPTIME = 0x04,
    // DELETE_QUEUE   = 0x08, // If we implement this.
    LARGE_VALUE       = 0x80
};

// Note: Changing this struct changes the format of the data stored on disk.
// If you change this struct, previous stored data will be misinterpreted.
struct btree_key {
    uint8_t size;
    char contents[0];
    void print() {
        //printf("%*.*s", size, size, contents);
        printf("%d", size);
    }
};

// Note: This struct is stored directly on disk.
struct btree_value {
    uint8_t size;
    byte metadata_flags;
    byte contents[0];

    void init() { // XXX
    }

    uint16_t mem_size() {
        //assert(!is_large());
        return value_offset() + size;
                //(is_large() ? sizeof(block_id_t) + (assert(0),0) : value_size());
    }

    uint32_t value_size() {
        if (is_large()) {
            // Size is stored in contents along with the block ID.
            // TODO: Should the size go here or in the index block? Should other metadata go here?
            // TODO: Is it a good idea to store other metadata in here?
            // TODO: If we really wanted to, we could save a byte by using the size field and only three bytes of contents.
            assert(*lv_size_addr() > MAX_IN_NODE_VALUE_SIZE);
            return *lv_size_addr();
        } else {
            return size;
        }
    }

    void value_size(uint32_t new_size) {
        if (new_size <= MAX_IN_NODE_VALUE_SIZE) {
            if (is_large()) {
                clear_space((byte *) lv_size_addr(), sizeof(uint32_t), lv_size_offset());
                metadata_flags &= ~LARGE_VALUE;
            }
            size = new_size;
        } else {
            if (!is_large()) {
                metadata_flags |= LARGE_VALUE;
                make_space((byte *) lv_size_addr(), sizeof(uint32_t), lv_size_offset());
            }
            size = sizeof(block_id_t);
            *lv_size_addr() = new_size;
        }
    }

    typedef uint32_t mcflags_t;
    typedef uint64_t cas_t;

    // TODO: We assume that time_t can be converted to an exptime_t,
    // which is 32 bits.  We may run into problems in 2038 or 2106.
    typedef uint32_t exptime_t;

    // Every value has mcflags, but they're very often 0, in which case we just
    // store a bit instead of 4 bytes.
    bool has_mcflags() { return metadata_flags & MEMCACHED_FLAGS;   }
    bool has_cas()     { return metadata_flags & MEMCACHED_CAS;     }
    bool has_exptime() { return metadata_flags & MEMCACHED_EXPTIME; }
    bool is_large()    { return metadata_flags & LARGE_VALUE;       }

    uint8_t mcflags_offset() { return 0;                                                    }
    uint8_t exptime_offset() { return mcflags_offset() + sizeof(mcflags_t) * has_mcflags(); }
    uint8_t cas_offset()     { return exptime_offset() + sizeof(exptime_t) * has_exptime(); }
    uint8_t lv_size_offset() { return     cas_offset() + sizeof(cas_t)     * has_cas();     }
    uint8_t value_offset()   { return lv_size_offset() + sizeof(uint32_t)  * is_large(); }

    mcflags_t *mcflags_addr() { return (mcflags_t *) (contents + mcflags_offset()); }
    exptime_t *exptime_addr() { return (exptime_t *) (contents + exptime_offset()); }
    cas_t         *cas_addr() { return (cas_t     *) (contents +     cas_offset()); }
    uint32_t  *lv_size_addr() { return (uint32_t  *) (contents + lv_size_offset()); }
    byte             *value() { return (byte      *) (contents +   value_offset()); }

    block_id_t lv_index_block_id() { return * (block_id_t *) value(); }
    void set_lv_index_block_id(block_id_t block_id) {
        assert(is_large());
        *(block_id_t *) value() = block_id;
    }

    mcflags_t mcflags() { return has_mcflags() ? *mcflags_addr() : 0; }
    exptime_t exptime() { return has_exptime() ? *exptime_addr() : 0; }
    cas_t         cas() { // We shouldn't be asking for a value's CAS unless we know it has one.
        assert(has_cas());
        return *cas_addr();
    }

    void clear_space(byte *faddr, uint8_t fsize, uint8_t offset) {
        memmove(faddr, faddr + fsize, mem_size() - offset - fsize);
        //size -= fsize;
    }

    void make_space(byte *faddr, uint8_t fsize, uint8_t offset) { // XXX This assumes there's enough space allocated to move the value into.
        assert(mem_size() + fsize <= MAX_TOTAL_NODE_CONTENTS_SIZE);
        //size += fsize;
        memmove(faddr + fsize, faddr, mem_size() - offset);
    }

    void set_mcflags(mcflags_t new_mcflags) {
        if (has_mcflags() && new_mcflags == 0) { // Flags is being set to 0, so we clear the 4 bytes we kept for it.
            clear_space((byte *) mcflags_addr(), sizeof(mcflags_t), mcflags_offset());
            metadata_flags &= ~MEMCACHED_FLAGS;
        } else if (!has_mcflags() && new_mcflags) { // Make space for non-zero mcflags.
            metadata_flags |= MEMCACHED_FLAGS;
            make_space((byte *) mcflags_addr(), sizeof(mcflags_t), mcflags_offset());
        }
        if (new_mcflags) { // We've made space, so copy the mcflags over.
            *mcflags_addr() = new_mcflags;
        }
    }

    void set_exptime(exptime_t new_exptime) {
        if (has_exptime() && new_exptime == 0) { // Exptime is being set to 0, so we clear the 4 bytes we kept for it.
            clear_space((byte *) exptime_addr(), sizeof(exptime_t), exptime_offset());
            metadata_flags &= ~MEMCACHED_EXPTIME;
        } else if (!has_exptime() && new_exptime) { // Make space for non-zero exptime.
            metadata_flags |= MEMCACHED_EXPTIME;
            make_space((byte *) exptime_addr(), sizeof(exptime_t), exptime_offset());
        }
        if (new_exptime) {
            *exptime_addr() = new_exptime;
        }
    }

    bool expired() {
        return exptime() ? time(NULL) >= exptime() : false;
    }

    // CAS is treated differently from the other fields. Values initially don't
    // have a CAS; once it's added, though, we assume it's there for good. An
    // existing CAS should never be set to 0.
    void set_cas(cas_t new_cas) {
        if (!new_cas) {
            assert(!has_cas());
            return;
        }
        if (!has_cas()) { // Make space for CAS.
            metadata_flags |= MEMCACHED_CAS;
            make_space((byte *) cas_addr(), sizeof(cas_t), cas_offset());
        }
        *cas_addr() = new_cas;
    }

    void print() {
        printf("%*.*s", size, size, value());
    }
};

// A btree_node is either a btree_internal_node or a btree_leaf_node.
//
// Note: &type == &internal.type == &leaf.type.
//
// Note: The reason this is not a struct btree_node { btree_node_type
// tag; union { btree_internal_node internal; btree_leaf_node leaf; }
// u; } is that btree_node used to superclass
// btree_{leaf|internal}_node, with one member, type.  A lot of code
// freely casts between a subclass and parent class type.
union btree_node {
    btree_node_type type;
    btree_internal_node internal;
    btree_leaf_node leaf;
};

typedef btree_node node_t;

class node_handler {
    public:
        static bool is_leaf(const btree_node *node) {
            assert(node->type == btree_node_type_leaf || node->type == btree_node_type_internal);
            return node->type == btree_node_type_leaf;
        }

        static bool is_internal(const btree_node *node) {
            assert(node->type == btree_node_type_leaf || node->type == btree_node_type_internal);
            return node->type == btree_node_type_internal;
        }

        static void str_to_key(char *str, btree_key *buf) {
            int len = strlen(str);
            check("string too long", len > MAX_KEY_SIZE);
            memcpy(buf->contents, str, len);
            buf->size = (unsigned char)len;
        }

        static bool is_underfull(size_t block_size, const btree_node *node);
        static bool is_mergable(size_t block_size, const btree_node *node, const btree_node *sibling, const btree_node *parent);
        static int nodecmp(const btree_node *node1, const btree_node *node2);
        static void merge(size_t block_size, btree_node *node, btree_node *rnode, btree_key *key_to_remove, btree_node *parent);
        static void remove(size_t block_size, btree_node *node, btree_key *key);
        static bool level(size_t block_size, btree_node *node, btree_node *rnode, btree_key *key_to_replace, btree_key *replacement_key, btree_node *parent);

        static void print(const btree_node *node);

        static void validate(size_t block_size, const btree_node *node);

        static inline const btree_node* node(const void *ptr) {
            return (const btree_node *) ptr;
        }
        static inline btree_node* node(void *ptr) {
            return (btree_node *) ptr;
        }
};

inline void keycpy(btree_key *dest, btree_key *src) {
    memcpy(dest, src, sizeof(btree_key) + src->size);
}

inline void valuecpy(btree_value *dest, btree_value *src) {
    memcpy(dest, src, sizeof(btree_value) + src->mem_size());
}

#endif // __BTREE_NODE_HPP__
<|endoftext|>


<commit_before>#include "bufferAgent.h"
#include "helpers/storageHelperFactory.h"
#include "glog/logging.h"

using boost::shared_ptr;
using boost::thread;
using boost::bind;

using std::string;

namespace veil {
namespace helpers {

BufferAgent::BufferAgent(write_fun w, read_fun r)
  : m_agentActive(false),
    doWrite(w),
    doRead(r)
{
    agentStart();
}
BufferAgent::~BufferAgent()
{
    agentStop();
}

int BufferAgent::onOpen(std::string path, ffi_type ffi)
{
    {
        unique_lock guard(m_wrMutex);
        m_wrCacheMap.erase(ffi->fh);

        write_buffer_ptr lCache(new WriteCache());
        lCache->fileName = path;
        lCache->buffer = newFileCache(true);
        lCache->ffi = *ffi;

        m_wrCacheMap[ffi->fh] = lCache;
    }

    {
        unique_lock guard(m_rdMutex);
        read_cache_map_t::iterator it;
        if(( it = m_rdCacheMap.find(path) ) != m_rdCacheMap.end()) {
            it->second->openCount++;
        } else {
            read_buffer_ptr lCache(new ReadCache());
            lCache->fileName = path;
            lCache->openCount = 1;
            lCache->ffi = *ffi;
            lCache->buffer = newFileCache(false);

            m_rdCacheMap[path] = lCache;
        }

        m_rdJobQueue.push_front(PrefetchJob(path, 0, 512));
        m_rdCond.notify_one();
    }

    return 0;
}

int BufferAgent::onWrite(std::string path, const std::string &buf, size_t size, off_t offset, ffi_type ffi)
{
    unique_lock guard(m_wrMutex);
        write_buffer_ptr wrapper = m_wrCacheMap[ffi->fh];
    guard.unlock();

    {
        if(wrapper->buffer->byteSize() > 1024 * 1024 * 64) {
            if(int fRet = onFlush(path, ffi)) {
                return fRet;
            }
        }

        if(wrapper->buffer->byteSize() > 1024 * 1024 * 64) {
            return doWrite(path, buf, size, offset, ffi);
        }

        wrapper->buffer->writeData(offset, buf);
    }

    unique_lock buffGuard(wrapper->mutex);
    guard.lock();
    if(!wrapper->opPending)
    {
        wrapper->opPending = true;
        m_wrJobQueue.push_back(ffi->fh);
        m_wrCond.notify_one();
    }

    return size;
}

int BufferAgent::onRead(std::string path, std::string &buf, size_t size, off_t offset, ffi_type ffi)
{
    unique_lock guard(m_rdMutex);
        read_buffer_ptr wrapper = m_rdCacheMap[path];
    guard.unlock();

    wrapper->buffer->readData(offset, size, buf);

    if(buf.size() < size) {

        string buf2;
        if(offset + buf.size() < 10 * 1024 * 1024)
        {
            buf2.resize(size - buf.size());
        }
        // int ret = doRead(path, buf2, size - buf.size(), offset + buf.size(), &wrapper->ffi);
        // if(ret < 0)
        //     return ret;

        wrapper->buffer->writeData(offset + buf.size(), buf2);

        buf += buf2;

        //DLOG(INFO) << "doRead ret: " << ret << " bufSize: " << buf2.size() << " globalBufSize: " << buf.size() ;

        {
            unique_lock buffGuard(wrapper->mutex);
            wrapper->blockSize = std::min((size_t) 1024 * 1024, (size_t) std::max(size, 2*wrapper->blockSize));
        }

        guard.lock();
            m_rdJobQueue.push_back(PrefetchJob(wrapper->fileName, offset + buf.size(), wrapper->blockSize));
        guard.unlock();
    } else {
        string tmp;
        size_t prefSize = std::max(2*size, wrapper->blockSize);
        wrapper->buffer->readData(offset + size, prefSize, tmp);

        if(tmp.size() != prefSize) {
            guard.lock();
                m_rdJobQueue.push_back(PrefetchJob(wrapper->fileName, offset + size + tmp.size(), wrapper->blockSize));
                m_rdJobQueue.push_back(PrefetchJob(wrapper->fileName, offset + size + tmp.size() + wrapper->blockSize, wrapper->blockSize));
            guard.unlock();
        }
    }

    m_rdCond.notify_one();

    return buf.size();
}

int BufferAgent::onFlush(std::string path, ffi_type ffi)
{
    unique_lock guard(m_wrMutex);
        write_buffer_ptr wrapper = m_wrCacheMap[ffi->fh];
    guard.unlock();

    unique_lock sendGuard(wrapper->sendMutex);
    unique_lock buff_guard(wrapper->mutex);

    while(wrapper->buffer->blockCount() > 0)
    {
        block_ptr block = wrapper->buffer->removeOldestBlock();
        uint64_t start = utils::mtime<uint64_t>();
        int res = doWrite(wrapper->fileName, block->data, block->data.size(), block->offset, &wrapper->ffi);
        uint64_t end = utils::mtime<uint64_t>();

        //LOG(INFO) << "Roundtrip: " << (end - start) << " for " << block->data.size() << " bytes";

        if(res < 0)
        {
            while(wrapper->buffer->blockCount() > 0)
            {
                (void) wrapper->buffer->removeOldestBlock();
            }
            return res;
        }
    }

    guard.lock();
    m_wrJobQueue.remove(ffi->fh);

    return 0;
}

int BufferAgent::onRelease(std::string path, ffi_type ffi)
{
    {
        unique_lock guard(m_wrMutex);
        m_wrCacheMap.erase(ffi->fh);
        m_wrJobQueue.remove(ffi->fh);
    }

    {
        unique_lock guard(m_rdMutex);

        read_cache_map_t::iterator it;
        if(( it = m_rdCacheMap.find(path) ) != m_rdCacheMap.end()) {
            it->second->openCount--;
            if(it->second->openCount <= 0) {
                m_rdCacheMap.erase(it);
            }
        }
    }

    return 0;
}

void BufferAgent::agentStart(int worker_count)
{
    m_workers.clear();
    m_agentActive = true;

    while(worker_count--)
    {
        m_workers.push_back(shared_ptr<thread>(new thread(bind(&BufferAgent::writerLoop, this))));
        m_workers.push_back(shared_ptr<thread>(new thread(bind(&BufferAgent::readerLoop, this))));
    }
}

void BufferAgent::agentStop()
{
    m_agentActive = false;
    m_wrCond.notify_all();
    m_rdCond.notify_all();

    while(m_workers.size() > 0)
    {
        m_workers.back()->join();
        m_workers.pop_back();
    }
}

void BufferAgent::readerLoop()
{
    unique_lock guard(m_rdMutex);
    while(m_agentActive)
    {
        while(m_rdJobQueue.empty() && m_agentActive)
            m_rdCond.wait(guard);

        if(!m_agentActive)
            return;

        PrefetchJob job = m_rdJobQueue.front();
        read_buffer_ptr wrapper = m_rdCacheMap[job.fileName];
        m_rdJobQueue.pop_front();
        m_rdCond.notify_one();

        if(!wrapper)
            continue;

        guard.unlock();

        {
            string buff;
            wrapper->buffer->readData(job.offset, job.size, buff);
            if(buff.size() < job.size)
            {
                string tmp;
                if(job.offset < 10 * 1024 * 1024)
                {
                    tmp.resize(job.size);
                    int ret  = job.size;
                    //int ret = doRead(wrapper->fileName, tmp, job.size - buff.size(), job.offset + buff.size(), &wrapper->ffi);
                    if(ret > 0 && tmp.size() >= ret) {
                        wrapper->buffer->writeData(job.offset + buff.size(), tmp);
                    }
                }
            }
        }

        guard.lock();
    }
}

void BufferAgent::writerLoop()
{
    unique_lock guard(m_wrMutex);
    while(m_agentActive)
    {
        while(m_wrJobQueue.empty() && m_agentActive)
            m_wrCond.wait(guard);

        if(!m_agentActive)
            return;

        fd_type file = m_wrJobQueue.front();
        write_buffer_ptr wrapper = m_wrCacheMap[file];
        m_wrJobQueue.pop_front();
        m_wrCond.notify_one();

        if(!wrapper)
            continue;

        guard.unlock();

        {
            unique_lock sendGuard(wrapper->sendMutex);

            block_ptr block;
            {
                unique_lock buff_guard(wrapper->mutex);
                block = wrapper->buffer->removeOldestBlock();
            }

            if(block)
            {
                uint64_t start = utils::mtime<uint64_t>();
                int res = doWrite(wrapper->fileName, block->data, block->data.size(), block->offset, &wrapper->ffi);
                uint64_t end = utils::mtime<uint64_t>();

                //LOG(INFO) << "Roundtrip: " << (end - start) << " for " << block->data.size() << " bytes";

                wrapper->cond.notify_all();
            }

            {
                unique_lock buff_guard(wrapper->mutex);
                guard.lock();
                if(wrapper->buffer->blockCount() > 0)
                {
                    m_wrJobQueue.push_back(file);
                }
                else
                {
                    wrapper->opPending = false;
                }
            }
        }

        wrapper->cond.notify_all();
    }
}

boost::shared_ptr<FileCache> BufferAgent::newFileCache(bool isBuffer)
{
    return boost::shared_ptr<FileCache>(new FileCache(10 * 1024 * 1024, isBuffer));
}

} // namespace helpers
} // namespace veil

<commit_msg>VFS-292: improve read speed<commit_after>#include "bufferAgent.h"
#include "helpers/storageHelperFactory.h"
#include "glog/logging.h"

using boost::shared_ptr;
using boost::thread;
using boost::bind;

using std::string;

namespace veil {
namespace helpers {

BufferAgent::BufferAgent(write_fun w, read_fun r)
  : m_agentActive(false),
    doWrite(w),
    doRead(r)
{
    agentStart();
}
BufferAgent::~BufferAgent()
{
    agentStop();
}

int BufferAgent::onOpen(std::string path, ffi_type ffi)
{
    {
        unique_lock guard(m_wrMutex);
        m_wrCacheMap.erase(ffi->fh);

        write_buffer_ptr lCache(new WriteCache());
        lCache->fileName = path;
        lCache->buffer = newFileCache(true);
        lCache->ffi = *ffi;

        m_wrCacheMap[ffi->fh] = lCache;
    }

    {
        unique_lock guard(m_rdMutex);
        read_cache_map_t::iterator it;
        if(( it = m_rdCacheMap.find(path) ) != m_rdCacheMap.end()) {
            it->second->openCount++;
        } else {
            read_buffer_ptr lCache(new ReadCache());
            lCache->fileName = path;
            lCache->openCount = 1;
            lCache->ffi = *ffi;
            lCache->buffer = newFileCache(false);

            m_rdCacheMap[path] = lCache;
        }

        m_rdJobQueue.push_front(PrefetchJob(path, 0, 512));
        m_rdCond.notify_one();
    }

    return 0;
}

int BufferAgent::onWrite(std::string path, const std::string &buf, size_t size, off_t offset, ffi_type ffi)
{
    unique_lock guard(m_wrMutex);
        write_buffer_ptr wrapper = m_wrCacheMap[ffi->fh];
    guard.unlock();

    {
        if(wrapper->buffer->byteSize() > 1024 * 1024 * 64) {
            if(int fRet = onFlush(path, ffi)) {
                return fRet;
            }
        }

        if(wrapper->buffer->byteSize() > 1024 * 1024 * 64) {
            return doWrite(path, buf, size, offset, ffi);
        }

        wrapper->buffer->writeData(offset, buf);
    }

    unique_lock buffGuard(wrapper->mutex);
    guard.lock();
    if(!wrapper->opPending)
    {
        wrapper->opPending = true;
        m_wrJobQueue.push_back(ffi->fh);
        m_wrCond.notify_one();
    }

    return size;
}

int BufferAgent::onRead(std::string path, std::string &buf, size_t size, off_t offset, ffi_type ffi)
{
    unique_lock guard(m_rdMutex);
        read_buffer_ptr wrapper = m_rdCacheMap[path];
    guard.unlock();

    wrapper->buffer->readData(offset, size, buf);

    if(buf.size() < size) {

        string buf2;
        int ret = doRead(path, buf2, size - buf.size(), offset + buf.size(), &wrapper->ffi);
        if(ret < 0)
            return ret;

        wrapper->buffer->writeData(offset + buf.size(), buf2);

        buf += buf2;

        //DLOG(INFO) << "doRead ret: " << ret << " bufSize: " << buf2.size() << " globalBufSize: " << buf.size() ;

        {
            unique_lock buffGuard(wrapper->mutex);
            wrapper->blockSize = std::min((size_t) 1024 * 1024, (size_t) std::max(size, 2*wrapper->blockSize));
        }

        guard.lock();
            m_rdJobQueue.push_back(PrefetchJob(wrapper->fileName, offset + buf.size(), wrapper->blockSize));
        guard.unlock();
    } else {
        string tmp;
        size_t prefSize = std::max(2*size, wrapper->blockSize);
        wrapper->buffer->readData(offset + size, prefSize, tmp);

        if(tmp.size() != prefSize) {
            guard.lock();
                m_rdJobQueue.push_back(PrefetchJob(wrapper->fileName, offset + size + tmp.size(), wrapper->blockSize));
                m_rdJobQueue.push_back(PrefetchJob(wrapper->fileName, offset + size + tmp.size() + wrapper->blockSize, wrapper->blockSize));
            guard.unlock();
        }
    }

    m_rdCond.notify_one();

    return buf.size();
}

int BufferAgent::onFlush(std::string path, ffi_type ffi)
{
    unique_lock guard(m_wrMutex);
        write_buffer_ptr wrapper = m_wrCacheMap[ffi->fh];
    guard.unlock();

    unique_lock sendGuard(wrapper->sendMutex);
    unique_lock buff_guard(wrapper->mutex);

    while(wrapper->buffer->blockCount() > 0)
    {
        block_ptr block = wrapper->buffer->removeOldestBlock();
        uint64_t start = utils::mtime<uint64_t>();
        int res = doWrite(wrapper->fileName, block->data, block->data.size(), block->offset, &wrapper->ffi);
        uint64_t end = utils::mtime<uint64_t>();

        //LOG(INFO) << "Roundtrip: " << (end - start) << " for " << block->data.size() << " bytes";

        if(res < 0)
        {
            while(wrapper->buffer->blockCount() > 0)
            {
                (void) wrapper->buffer->removeOldestBlock();
            }
            return res;
        }
    }

    guard.lock();
    m_wrJobQueue.remove(ffi->fh);

    return 0;
}

int BufferAgent::onRelease(std::string path, ffi_type ffi)
{
    {
        unique_lock guard(m_wrMutex);
        m_wrCacheMap.erase(ffi->fh);
        m_wrJobQueue.remove(ffi->fh);
    }

    {
        unique_lock guard(m_rdMutex);

        read_cache_map_t::iterator it;
        if(( it = m_rdCacheMap.find(path) ) != m_rdCacheMap.end()) {
            it->second->openCount--;
            if(it->second->openCount <= 0) {
                m_rdCacheMap.erase(it);
            }
        }
    }

    return 0;
}

void BufferAgent::agentStart(int worker_count)
{
    m_workers.clear();
    m_agentActive = true;

    while(worker_count--)
    {
        m_workers.push_back(shared_ptr<thread>(new thread(bind(&BufferAgent::writerLoop, this))));
        m_workers.push_back(shared_ptr<thread>(new thread(bind(&BufferAgent::readerLoop, this))));
    }
}

void BufferAgent::agentStop()
{
    m_agentActive = false;
    m_wrCond.notify_all();
    m_rdCond.notify_all();

    while(m_workers.size() > 0)
    {
        m_workers.back()->join();
        m_workers.pop_back();
    }
}

void BufferAgent::readerLoop()
{
    unique_lock guard(m_rdMutex);
    while(m_agentActive)
    {
        while(m_rdJobQueue.empty() && m_agentActive)
            m_rdCond.wait(guard);

        if(!m_agentActive)
            return;

        PrefetchJob job = m_rdJobQueue.front();
        read_buffer_ptr wrapper = m_rdCacheMap[job.fileName];
        m_rdJobQueue.pop_front();
        m_rdCond.notify_one();

        if(!wrapper)
            continue;

        guard.unlock();

        {
            string buff;
            wrapper->buffer->readData(job.offset, job.size, buff);
            if(buff.size() < job.size)
            {
                string tmp;
                int ret = doRead(wrapper->fileName, tmp, job.size - buff.size(), job.offset + buff.size(), &wrapper->ffi);
                if(ret > 0 && tmp.size() >= ret) {
                    wrapper->buffer->writeData(job.offset + buff.size(), tmp);
                }
            }
        }

        guard.lock();
    }
}

void BufferAgent::writerLoop()
{
    unique_lock guard(m_wrMutex);
    while(m_agentActive)
    {
        while(m_wrJobQueue.empty() && m_agentActive)
            m_wrCond.wait(guard);

        if(!m_agentActive)
            return;

        fd_type file = m_wrJobQueue.front();
        write_buffer_ptr wrapper = m_wrCacheMap[file];
        m_wrJobQueue.pop_front();
        m_wrCond.notify_one();

        if(!wrapper)
            continue;

        guard.unlock();

        {
            unique_lock sendGuard(wrapper->sendMutex);

            block_ptr block;
            {
                unique_lock buff_guard(wrapper->mutex);
                block = wrapper->buffer->removeOldestBlock();
            }

            if(block)
            {
                uint64_t start = utils::mtime<uint64_t>();
                int res = doWrite(wrapper->fileName, block->data, block->data.size(), block->offset, &wrapper->ffi);
                uint64_t end = utils::mtime<uint64_t>();

                //LOG(INFO) << "Roundtrip: " << (end - start) << " for " << block->data.size() << " bytes";

                wrapper->cond.notify_all();
            }

            {
                unique_lock buff_guard(wrapper->mutex);
                guard.lock();
                if(wrapper->buffer->blockCount() > 0)
                {
                    m_wrJobQueue.push_back(file);
                }
                else
                {
                    wrapper->opPending = false;
                }
            }
        }

        wrapper->cond.notify_all();
    }
}

boost::shared_ptr<FileCache> BufferAgent::newFileCache(bool isBuffer)
{
    return boost::shared_ptr<FileCache>(new FileCache(10 * 1024 * 1024, isBuffer));
}

} // namespace helpers
} // namespace veil

<|endoftext|>


<commit_before>#include "bufferAgent.h"

using boost::shared_ptr;
using boost::thread;
using boost::bind;

using std::string;

namespace veil {
namespace helpers {

BufferAgent::BufferAgent(write_fun w, read_fun r)
  : m_agentActive(false),
    doWrite(w),
    doRead(r)
{
    agentStart();
}
BufferAgent::~BufferAgent()
{
    agentStop();
}

int BufferAgent::onOpen(std::string path, ffi_type ffi)
{
    unique_lock guard(m_loopMutex);
    m_cacheMap.erase(ffi->fh);

    buffer_ptr lCache(new LockableCache());
    lCache->fileName = path;
    lCache->buffer = newFileCache();
    lCache->ffi = *ffi;

    m_cacheMap[ffi->fh] = lCache;

    return 0;
}

int BufferAgent::onWrite(std::string path, const std::string &buf, size_t size, off_t offset, ffi_type ffi)
{
    unique_lock guard(m_loopMutex);
        buffer_ptr wrapper = m_cacheMap[ffi->fh];
    guard.unlock();

    {
        if(wrapper->buffer->byteSize() > 1024 * 1024 * 64) {
            if(int fRet = onFlush(path, ffi)) {
                return fRet;
            }
        }

        if(wrapper->buffer->byteSize() > 1024 * 1024 * 64) {
            return doWrite(path, buf, size, offset, ffi);
        }

        wrapper->buffer->writeData(offset, buf);
    }

    unique_lock buffGuard(wrapper->mutex);
    guard.lock();
    if(!wrapper->opPending)
    {
        wrapper->opPending = true;
        m_jobQueue.push_back(ffi->fh);
        m_loopCond.notify_all();
    }

    return size;
}

int BufferAgent::onRead(std::string path, std::string &buf, size_t size, off_t offset, ffi_type ffi)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_loopMutex);
    return EOPNOTSUPP;
}

int BufferAgent::onFlush(std::string path, ffi_type ffi)
{
    unique_lock guard(m_loopMutex);
        buffer_ptr wrapper = m_cacheMap[ffi->fh];
    guard.unlock();

    unique_lock sendGuard(wrapper->sendMutex);
    unique_lock buff_guard(wrapper->mutex);

    while(wrapper->buffer->blockCount() > 0)
    {
        block_ptr block = wrapper->buffer->removeOldestBlock();
        int res = doWrite(wrapper->fileName, block->data, block->data.size(), block->offset, &wrapper->ffi);
        if(res < 0)
        {
            while(wrapper->buffer->blockCount() > 0)
            {
                (void) wrapper->buffer->removeOldestBlock();
            }
            return res;
        }
    }

    guard.lock();
    m_jobQueue.remove(ffi->fh);

    return 0;
}

int BufferAgent::onRelease(std::string path, ffi_type ffi)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_loopMutex);
    m_cacheMap.erase(ffi->fh);
    m_jobQueue.remove(ffi->fh);

    return 0;
}

void BufferAgent::agentStart(int worker_count)
{
    m_workers.clear();
    m_agentActive = true;

    while(worker_count--)
    {
        m_workers.push_back(shared_ptr<thread>(new thread(bind(&BufferAgent::workerLoop, this))));
    }
}

void BufferAgent::agentStop()
{
    m_agentActive = false;
    m_loopCond.notify_all();
    while(m_workers.size() > 0)
    {
        m_workers.back()->join();
        m_workers.pop_back();
    }
}

void BufferAgent::workerLoop()
{
    unique_lock guard(m_loopMutex);
    while(m_agentActive)
    {
        while(m_jobQueue.empty() && m_agentActive)
            m_loopCond.wait(guard);

        if(!m_agentActive)
            return;

        fd_type file = m_jobQueue.front();
        buffer_ptr wrapper = m_cacheMap[file];
        m_jobQueue.pop_front();
        m_loopCond.notify_one();

        if(!wrapper)
            continue;

        guard.unlock();

        {
            unique_lock sendGuard(wrapper->sendMutex);

            block_ptr block;
            {
                unique_lock buff_guard(wrapper->mutex);
                block = wrapper->buffer->removeOldestBlock();
            }

            if(block)
            {
                //int res = doWrite(wrapper->fileName, block->data, block->data.size(), block->offset, &wrapper->ffi);

                wrapper->cond.notify_all();
            }

            {
                unique_lock buff_guard(wrapper->mutex);
                guard.lock();
                if(wrapper->buffer->blockCount() > 0)
                {
                    m_jobQueue.push_back(file);
                }
                else
                {
                    wrapper->opPending = false;
                }
            }
        }

        wrapper->cond.notify_all();
    }
}

boost::shared_ptr<FileCache> BufferAgent::newFileCache()
{
    return boost::shared_ptr<FileCache>(new FileCache(1024 * 1024));
}

} // namespace helpers
} // namespace veil

<commit_msg>VFS-292: improve write speed<commit_after>#include "bufferAgent.h"

using boost::shared_ptr;
using boost::thread;
using boost::bind;

using std::string;

namespace veil {
namespace helpers {

BufferAgent::BufferAgent(write_fun w, read_fun r)
  : m_agentActive(false),
    doWrite(w),
    doRead(r)
{
    agentStart();
}
BufferAgent::~BufferAgent()
{
    agentStop();
}

int BufferAgent::onOpen(std::string path, ffi_type ffi)
{
    unique_lock guard(m_loopMutex);
    m_cacheMap.erase(ffi->fh);

    buffer_ptr lCache(new LockableCache());
    lCache->fileName = path;
    lCache->buffer = newFileCache();
    lCache->ffi = *ffi;

    m_cacheMap[ffi->fh] = lCache;

    return 0;
}

int BufferAgent::onWrite(std::string path, const std::string &buf, size_t size, off_t offset, ffi_type ffi)
{
    unique_lock guard(m_loopMutex);
        buffer_ptr wrapper = m_cacheMap[ffi->fh];
    guard.unlock();

    {
        if(wrapper->buffer->byteSize() > 1024 * 1024 * 64) {
            if(int fRet = onFlush(path, ffi)) {
                return fRet;
            }
        }

        if(wrapper->buffer->byteSize() > 1024 * 1024 * 64) {
            return doWrite(path, buf, size, offset, ffi);
        }

        wrapper->buffer->writeData(offset, buf);
    }

    unique_lock buffGuard(wrapper->mutex);
    guard.lock();
    if(!wrapper->opPending)
    {
        wrapper->opPending = true;
        m_jobQueue.push_back(ffi->fh);
        m_loopCond.notify_one();
    }

    return size;
}

int BufferAgent::onRead(std::string path, std::string &buf, size_t size, off_t offset, ffi_type ffi)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_loopMutex);
    return EOPNOTSUPP;
}

int BufferAgent::onFlush(std::string path, ffi_type ffi)
{
    unique_lock guard(m_loopMutex);
        buffer_ptr wrapper = m_cacheMap[ffi->fh];
    guard.unlock();

    unique_lock sendGuard(wrapper->sendMutex);
    unique_lock buff_guard(wrapper->mutex);

    while(wrapper->buffer->blockCount() > 0)
    {
        block_ptr block = wrapper->buffer->removeOldestBlock();
        int res = doWrite(wrapper->fileName, block->data, block->data.size(), block->offset, &wrapper->ffi);
        if(res < 0)
        {
            while(wrapper->buffer->blockCount() > 0)
            {
                (void) wrapper->buffer->removeOldestBlock();
            }
            return res;
        }
    }

    guard.lock();
    m_jobQueue.remove(ffi->fh);

    return 0;
}

int BufferAgent::onRelease(std::string path, ffi_type ffi)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_loopMutex);
    m_cacheMap.erase(ffi->fh);
    m_jobQueue.remove(ffi->fh);

    return 0;
}

void BufferAgent::agentStart(int worker_count)
{
    m_workers.clear();
    m_agentActive = true;

    while(worker_count--)
    {
        m_workers.push_back(shared_ptr<thread>(new thread(bind(&BufferAgent::workerLoop, this))));
    }
}

void BufferAgent::agentStop()
{
    m_agentActive = false;
    m_loopCond.notify_all();
    while(m_workers.size() > 0)
    {
        m_workers.back()->join();
        m_workers.pop_back();
    }
}

void BufferAgent::workerLoop()
{
    unique_lock guard(m_loopMutex);
    while(m_agentActive)
    {
        while(m_jobQueue.empty() && m_agentActive)
            m_loopCond.wait(guard);

        if(!m_agentActive)
            return;

        fd_type file = m_jobQueue.front();
        buffer_ptr wrapper = m_cacheMap[file];
        m_jobQueue.pop_front();
        m_loopCond.notify_one();

        if(!wrapper)
            continue;

        guard.unlock();

        {
            unique_lock sendGuard(wrapper->sendMutex);

            block_ptr block;
            {
                unique_lock buff_guard(wrapper->mutex);
                block = wrapper->buffer->removeOldestBlock();
            }

            if(block)
            {
                //int res = doWrite(wrapper->fileName, block->data, block->data.size(), block->offset, &wrapper->ffi);

                wrapper->cond.notify_all();
            }

            {
                unique_lock buff_guard(wrapper->mutex);
                guard.lock();
                if(wrapper->buffer->blockCount() > 0)
                {
                    m_jobQueue.push_back(file);
                }
                else
                {
                    wrapper->opPending = false;
                }
            }
        }

        wrapper->cond.notify_all();
    }
}

boost::shared_ptr<FileCache> BufferAgent::newFileCache()
{
    return boost::shared_ptr<FileCache>(new FileCache(1024 * 1024));
}

} // namespace helpers
} // namespace veil

<|endoftext|>


<commit_before>//
// Created by cheyulin on 4/16/16.
//

#include <memory>
#include <set>
#include <iostream>
using namespace std;
int main(){
    set<int> first_set;
    first_set.insert(1);
    first_set.insert(2);
    //use The Rvalue Assignment Constructor
    auto second_set = std::move(first_set);
    cout << second_set.size() << endl;
    cout << first_set.size() << endl;
    getchar();
}<commit_msg>add some coments for move sementics<commit_after>//
// Created by cheyulin on 4/16/16.
//

#include <memory>
#include <set>
#include <iostream>

using namespace std;

//If unique_ptr<int> implement move assignment constructor
//Call callfunction(std::move(xxx))
//Will call the move assignment constructor
int callfunction(unique_ptr<int> int_ptr) {
    cout << "In Function:" << *int_ptr << endl;
    return -1;
}

//If set<int> implement move assignment constructor
//Call callfunction2(std::move(xxx))
//Will call the move assignment constructor
void callfunction2(set<int> set_r_val) {
    for (auto integer:set_r_val) {
        cout << integer << ",";
    }
    cout << endl;
}

int main() {
    set<int> first_set;
    first_set.insert(1);
    first_set.insert(2);
    //use The Rvalue Assignment Constructor
    auto second_set = std::move(first_set);
    cout << second_set.size() << endl;
    cout << first_set.size() << endl;

    auto int_ptr = make_unique<int>(1);
    cout << "!!" << (int_ptr == nullptr) << endl;

    callfunction(std::move(int_ptr));
    cout << "!!" << (int_ptr == nullptr) << endl;

    callfunction2(std::move(second_set));
    cout << second_set.size() << endl;
    getchar();

}<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2010 Couchbase, Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

#include <stdint.h>
#include <string.h>

#include "configuration.h"
#include "system_resource_stats.h"

static ssize_t prime_size_table[] = {
    11, 31, 47, 73, 97, 109, 211, 313, 419, -1
};

fdb_config get_default_config(void) {
    fdb_config fconfig;

    fconfig.chunksize = sizeof(uint64_t);
    // 4KB by default.
    fconfig.blocksize = FDB_BLOCKSIZE;
    // 128MB by default.
    fconfig.buffercache_size = 134217728;
    // 4K WAL entries by default.
    fconfig.wal_threshold = 4096;
    fconfig.wal_flush_before_commit = true;
    fconfig.auto_commit = false;
    // 0 second by default.
    fconfig.purging_interval = 0;
    // Sequnce trees are disabled by default.
    fconfig.seqtree_opt = FDB_SEQTREE_NOT_USE;
    // Use a synchronous commit by default.
    fconfig.durability_opt = FDB_DRB_NONE;
    fconfig.flags = FDB_OPEN_FLAG_CREATE;
    // 4MB by default.
    fconfig.compaction_buf_maxsize = FDB_COMP_BUF_MINSIZE;
    // Clean up cache entries when a file is closed.
    fconfig.cleanup_cache_onclose = true;
    // Compress the body of documents using snappy.
    fconfig.compress_document_body = false;
    // Auto compaction is disabled by default
    fconfig.compaction_mode = FDB_COMPACTION_MANUAL;
    // Compaction threshold, 30% by default
    fconfig.compaction_threshold = FDB_DEFAULT_COMPACTION_THRESHOLD;
    fconfig.compaction_minimum_filesize = 1048576; // 1MB by default
    // 15 seconds by default
    fconfig.compactor_sleep_duration = FDB_COMPACTOR_SLEEP_DURATION;
    // Disable supporting multiple KV instances by default
    fconfig.multi_kv_instances = true;
    // TODO: Re-enable this after prefetch ThreadSanitizer fixes are in..
    fconfig.prefetch_duration = 0;

    // Determine the number of WAL and buffer cache partitions by considering the
    // number of cores available in the host environment.
    int i = 0;
    ssize_t num_cores = (ssize_t) get_num_cores();
    for (; prime_size_table[i] > 0 && prime_size_table[i] < num_cores; ++i) {
        // Finding the smallest prime number that is greater than the number of cores.
    }
    if (prime_size_table[i] == -1) {
        fconfig.num_wal_partitions = prime_size_table[i-1];
        fconfig.num_bcache_partitions = prime_size_table[i-1];
    } else {
        fconfig.num_wal_partitions = prime_size_table[i];
        // For bcache partitions pick a higher value for smaller avl trees
        fconfig.num_bcache_partitions = prime_size_table[i];
    }

    // No compaction callback function by default
    fconfig.compaction_cb = NULL;
    fconfig.compaction_cb_mask = 0x0;
    fconfig.compaction_cb_ctx = NULL;
    fconfig.max_writer_lock_prob = 100;
    // 4 daemon compactor threads by default
    fconfig.num_compactor_threads = DEFAULT_NUM_COMPACTOR_THREADS;
    fconfig.num_bgflusher_threads = DEFAULT_NUM_BGFLUSHER_THREADS;
    // Block reusing threshold, 65% by default (i.e., almost 3x space amplification)
    fconfig.block_reusing_threshold = 65;
    // Keep at least 5 headers
    fconfig.num_keeping_headers = 5;

    fconfig.encryption_key.algorithm = FDB_ENCRYPTION_NONE;
    memset(fconfig.encryption_key.bytes, 0, sizeof(fconfig.encryption_key.bytes));

    // Breakpad minidump directory, set to current working dir
    fconfig.breakpad_minidump_dir = ".";

    return fconfig;
}

fdb_kvs_config get_default_kvs_config(void) {
    fdb_kvs_config kvs_config;

    // create an empty KV store if it doesn't exist.
    kvs_config.create_if_missing = true;
    // lexicographical key order by default
    kvs_config.custom_cmp = NULL;

    return kvs_config;
}

bool validate_fdb_config(fdb_config *fconfig) {
    assert(fconfig);

    if (fconfig->chunksize < 4 || fconfig->chunksize > 64) {
        // Chunk size should be set between 4 and 64 bytes.
        return false;
    }
    if (fconfig->chunksize < sizeof(void *)) {
        // Chunk size should be equal to or greater than the address bus size
        return false;
    }
    if (fconfig->blocksize < 1024 || fconfig->blocksize > 131072) {
        // Block size should be set between 1KB and 128KB
        return false;
    }
    if (fconfig->seqtree_opt != FDB_SEQTREE_NOT_USE &&
        fconfig->seqtree_opt != FDB_SEQTREE_USE) {
        return false;
    }
    if (fconfig->durability_opt != FDB_DRB_NONE &&
        fconfig->durability_opt != FDB_DRB_ODIRECT &&
        fconfig->durability_opt != FDB_DRB_ASYNC &&
        fconfig->durability_opt != FDB_DRB_ODIRECT_ASYNC) {
        return false;
    }
    if ((fconfig->flags & FDB_OPEN_FLAG_CREATE) &&
        (fconfig->flags & FDB_OPEN_FLAG_RDONLY)) {
        return false;
    }
    if (fconfig->compaction_threshold > 100) {
        // Compaction threshold should be equal or less then 100 (%).
        return false;
    }
    if (fconfig->compactor_sleep_duration == 0) {
        // Sleep duration should be larger than zero
        return false;
    }
    if (!fconfig->num_wal_partitions ||
        (fconfig->num_wal_partitions > MAX_NUM_WAL_PARTITIONS)) {
        return false;
    }
    if (!fconfig->num_bcache_partitions ||
        (fconfig->num_bcache_partitions > MAX_NUM_BCACHE_PARTITIONS)) {
        return false;
    }
    if (fconfig->max_writer_lock_prob < 20 ||
        fconfig->max_writer_lock_prob > 100) {
        return false;
    }
    if (fconfig->num_compactor_threads < 1 ||
        fconfig->num_compactor_threads > MAX_NUM_COMPACTOR_THREADS) {
        return false;
    }
    if (fconfig->num_bgflusher_threads > MAX_NUM_BGFLUSHER_THREADS) {
        return false;
    }

    return true;
}

bool validate_fdb_kvs_config(fdb_kvs_config *kvs_config) {
    return true;
}

<commit_msg>fix comment errors in default configuration<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2010 Couchbase, Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

#include <stdint.h>
#include <string.h>

#include "configuration.h"
#include "system_resource_stats.h"

static ssize_t prime_size_table[] = {
    11, 31, 47, 73, 97, 109, 211, 313, 419, -1
};

fdb_config get_default_config(void) {
    fdb_config fconfig;

    fconfig.chunksize = sizeof(uint64_t);
    // 4KB by default.
    fconfig.blocksize = FDB_BLOCKSIZE;
    // 128MB by default.
    fconfig.buffercache_size = 134217728;
    // 4K WAL entries by default.
    fconfig.wal_threshold = 4096;
    fconfig.wal_flush_before_commit = true;
    fconfig.auto_commit = false;
    // 0 second by default.
    fconfig.purging_interval = 0;
    // Sequnce trees are disabled by default.
    fconfig.seqtree_opt = FDB_SEQTREE_NOT_USE;
    // Use a synchronous commit by default.
    fconfig.durability_opt = FDB_DRB_NONE;
    fconfig.flags = FDB_OPEN_FLAG_CREATE;
    // 4MB by default.
    fconfig.compaction_buf_maxsize = FDB_COMP_BUF_MINSIZE;
    // Clean up cache entries when a file is closed.
    fconfig.cleanup_cache_onclose = true;
    // Compress the body of documents using snappy. Disabled by default.
    fconfig.compress_document_body = false;
    // Auto compaction is disabled by default
    fconfig.compaction_mode = FDB_COMPACTION_MANUAL;
    // Compaction threshold, 30% by default
    fconfig.compaction_threshold = FDB_DEFAULT_COMPACTION_THRESHOLD;
    fconfig.compaction_minimum_filesize = 1048576; // 1MB by default
    // 8 hours by default
    fconfig.compactor_sleep_duration = FDB_COMPACTOR_SLEEP_DURATION;
    // Multi KV Instance mode is enabled by default
    fconfig.multi_kv_instances = true;
    // TODO: Re-enable this after prefetch ThreadSanitizer fixes are in..
    fconfig.prefetch_duration = 0;

    // Determine the number of WAL and buffer cache partitions by considering the
    // number of cores available in the host environment.
    int i = 0;
    ssize_t num_cores = (ssize_t) get_num_cores();
    for (; prime_size_table[i] > 0 && prime_size_table[i] < num_cores; ++i) {
        // Finding the smallest prime number that is greater than the number of cores.
    }
    if (prime_size_table[i] == -1) {
        fconfig.num_wal_partitions = prime_size_table[i-1];
        fconfig.num_bcache_partitions = prime_size_table[i-1];
    } else {
        fconfig.num_wal_partitions = prime_size_table[i];
        // For bcache partitions pick a higher value for smaller avl trees
        fconfig.num_bcache_partitions = prime_size_table[i];
    }

    // No compaction callback function by default
    fconfig.compaction_cb = NULL;
    fconfig.compaction_cb_mask = 0x0;
    fconfig.compaction_cb_ctx = NULL;
    fconfig.max_writer_lock_prob = 100;
    // 4 daemon compactor threads by default
    fconfig.num_compactor_threads = DEFAULT_NUM_COMPACTOR_THREADS;
    fconfig.num_bgflusher_threads = DEFAULT_NUM_BGFLUSHER_THREADS;
    // Block reusing threshold, 65% by default (i.e., almost 3x space amplification)
    fconfig.block_reusing_threshold = 65;
    // Keep at most 5 recent committed database snapshots
    fconfig.num_keeping_headers = 5;

    fconfig.encryption_key.algorithm = FDB_ENCRYPTION_NONE;
    memset(fconfig.encryption_key.bytes, 0, sizeof(fconfig.encryption_key.bytes));

    // Breakpad minidump directory, set to current working dir
    fconfig.breakpad_minidump_dir = ".";

    return fconfig;
}

fdb_kvs_config get_default_kvs_config(void) {
    fdb_kvs_config kvs_config;

    // create an empty KV store if it doesn't exist.
    kvs_config.create_if_missing = true;
    // lexicographical key order by default
    kvs_config.custom_cmp = NULL;

    return kvs_config;
}

bool validate_fdb_config(fdb_config *fconfig) {
    assert(fconfig);

    if (fconfig->chunksize < 4 || fconfig->chunksize > 64) {
        // Chunk size should be set between 4 and 64 bytes.
        return false;
    }
    if (fconfig->chunksize < sizeof(void *)) {
        // Chunk size should be equal to or greater than the address bus size
        return false;
    }
    if (fconfig->blocksize < 1024 || fconfig->blocksize > 131072) {
        // Block size should be set between 1KB and 128KB
        return false;
    }
    if (fconfig->seqtree_opt != FDB_SEQTREE_NOT_USE &&
        fconfig->seqtree_opt != FDB_SEQTREE_USE) {
        return false;
    }
    if (fconfig->durability_opt != FDB_DRB_NONE &&
        fconfig->durability_opt != FDB_DRB_ODIRECT &&
        fconfig->durability_opt != FDB_DRB_ASYNC &&
        fconfig->durability_opt != FDB_DRB_ODIRECT_ASYNC) {
        return false;
    }
    if ((fconfig->flags & FDB_OPEN_FLAG_CREATE) &&
        (fconfig->flags & FDB_OPEN_FLAG_RDONLY)) {
        return false;
    }
    if (fconfig->compaction_threshold > 100) {
        // Compaction threshold should be equal or less then 100 (%).
        return false;
    }
    if (fconfig->compactor_sleep_duration == 0) {
        // Sleep duration should be larger than zero
        return false;
    }
    if (!fconfig->num_wal_partitions ||
        (fconfig->num_wal_partitions > MAX_NUM_WAL_PARTITIONS)) {
        return false;
    }
    if (!fconfig->num_bcache_partitions ||
        (fconfig->num_bcache_partitions > MAX_NUM_BCACHE_PARTITIONS)) {
        return false;
    }
    if (fconfig->max_writer_lock_prob < 20 ||
        fconfig->max_writer_lock_prob > 100) {
        return false;
    }
    if (fconfig->num_compactor_threads < 1 ||
        fconfig->num_compactor_threads > MAX_NUM_COMPACTOR_THREADS) {
        return false;
    }
    if (fconfig->num_bgflusher_threads > MAX_NUM_BGFLUSHER_THREADS) {
        return false;
    }

    return true;
}

bool validate_fdb_kvs_config(fdb_kvs_config *kvs_config) {
    return true;
}

<|endoftext|>


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

/// @file  main.cpp
/// @brief Command-line version of primesieve, multi-threaded (OpenMP).
/// @see   http://primesieve.googlecode.com
/// primesieve is a highly optimized implementation of the sieve of
/// Eratosthenes that generates prime numbers and prime k-tuplets (twin
/// primes, prime triplets, ...) up to 2^64 maximum.

#include "../soe/ParallelPrimeSieve.h"
#include "../expr/ExpressionParser.h"

#include <stdint.h>
#include <exception>
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
#include <algorithm>

void test();

namespace {

// start and stop number for sieving
std::vector<uint64_t> number;

int preSieve   = -1;
int sieveSize  = -1;
int threads    = -1;
int maxThreads = ParallelPrimeSieve::getMaxThreads();
int flags      = 0;

bool quietMode = false;
bool printParserResult = false;

const std::string primes[7] = {
  "Prime numbers",
  "Twin primes",
  "Prime triplets",
  "Prime quadruplets",
  "Prime quintuplets",
  "Prime sextuplets",
  "Prime septuplets"
};

enum {
  COUNT_PRIMES = ParallelPrimeSieve::COUNT_PRIMES,
  PRINT_PRIMES = ParallelPrimeSieve::PRINT_PRIMES
};

void help() {
  std::cout << "Usage: primesieve START STOP [OPTION]..."                                              << std::endl
            << "Use the segmented sieve of Eratosthenes to generate the prime numbers and/or"          << std::endl
            << "prime k-tuplets in the interval [START, STOP] < 2^64"                                  << std::endl
                                                                                << std::endl
            << "Options:"                                                                              << std::endl
                                                                                << std::endl
            << "  -c<N+>        Count prime numbers and/or prime k-tuplets, 1 <= N <= 7"               << std::endl
            << "                e.g. -c1 count prime numbers (DEFAULT)"                                << std::endl
            << "                     -c23 count twin primes and prime triplets"                        << std::endl
            << "  -o<OFFSET>    Sieve the interval [START, START+OFFSET]"                              << std::endl
            << "  -p<N>         Print prime numbers or prime k-tuplets, 1 <= N <= 7"                   << std::endl
            << "                e.g. -p1 print prime numbers"                                          << std::endl
            << "                     -p5 print prime quintuplets"                                      << std::endl
            << "  -q            Quiet mode, print less output"                                         << std::endl
            << "  -r<PRE-SIEVE> Pre-sieve multiples of small primes <= PRE-SIEVE to speed up"          << std::endl
            << "                the sieve of Eratosthenes, 13 <= PRE-SIEVE <= 23"                      << std::endl
            << "  -s<SIZE>      Set the sieve size in kilobytes, 1 <= SIZE <= 4096"                    << std::endl
            << "                Set SIZE to your CPU's L1/L2 cache size for best performance"          << std::endl
            << "  -t<THREADS>   Set the number of threads for sieving, 1 <= THREADS <= " << maxThreads << std::endl
            << "                Primes are not generated in order if THREADS >= 2"                     << std::endl
            << "  -test         Run various sieving tests and exit"                                    << std::endl
            << "  -v            Print version and license information and exit"                        << std::endl
                                                                                << std::endl
            << "Examples:"                                                                             << std::endl
                                                                                << std::endl
            << "Print the prime numbers up to 1000:"                                                   << std::endl
            << "> primesieve 2 1000 -p1"                                                               << std::endl
                                                                                << std::endl
            << "Count the twin primes in the interval [1E10, 1E10+2^32]:"                              << std::endl
            << "> primesieve 1E10 -o2**32 -c2"                                                         << std::endl;
  std::exit(1);
}

void version() {
  std::cout << "primesieve " << PRIMESIEVE_VERSION << ", <http://primesieve.googlecode.com>" << std::endl
            << "Copyright (C) " << PRIMESIEVE_YEAR << " Kim Walisch" << std::endl
            << "This software is licensed under the New BSD License. See the LICENSE file" << std::endl
            << "for more information." << std::endl;
  std::exit(1);
}

int getWidth(const ParallelPrimeSieve& pps) {
  std::size_t size = 0;
  for (int i = 0; i < 7; i++) {
    if (pps.isCount(i))
      size = std::max(size, primes[i].size());
  }
  return static_cast<int>(size);
}

bool isDigits(const std::string &str) {
  const std::string digits("0123456789");
  if (str.size() == 0)
    return false;
  return str.find_first_not_of(digits) == std::string::npos;
}

/// Process the command-line options.
/// @see help()
///
void processOptions(int argc, char* argv[]) {
  if (argc < 2 || argc > 20) help();
  std::string arg;
  ExpressionParser<uint64_t> parser64;
  ExpressionParser<int> parser;
  uint64_t res = 0;
  int i = 1;

  // process START and STOP number
  for (; i < std::min(3, argc); i++) {
    try {
      number.push_back(parser64.eval(argv[i]));
      if (!isDigits(argv[i]))
        printParserResult = true;
    } catch (...) {
      break;
    }
  }
  for (; i < argc; i++) {
    if (*argv[i] != '-' &&
        *argv[i] != '/') help();
    argv[i]++;
    try {
      switch (*argv[i]++) {
        case 'c': res = parser.eval(argv[i]);
                  do {
                    if (res % 10 < 1 || res % 10 > 7)
                      help();
                    flags |= COUNT_PRIMES << (res % 10 - 1);
                    res /= 10;
                  } while (res > 0);
                  break;
        case 'o': if (number.size() == 0)
                    help();
                  res = number[0] + parser64.eval(argv[i]);
                  number.push_back(res);
                  break;
        case 'p': res = parser.eval(argv[i]);
                  if (res < 1 || res > 7)
                    help();
                  flags |= PRINT_PRIMES << (res - 1);
                  quietMode = true;
                  break;
        case 'q': quietMode = true;                 break;
        case 'r': preSieve  = parser.eval(argv[i]); break;
        case 's': sieveSize = parser.eval(argv[i]); break;
        case 't': arg = argv[i];
                  if (arg.compare("est") == 0)
                    test();
                  threads = parser.eval(argv[i]);
                  break;
        case 'v': version();
        default : help();
      }
    } catch (parser_error&) {
      help();
    }
  }
  if (number.size() != 2)
    help();
}

} // end namespace

int main(int argc, char* argv[]) {
  processOptions(argc, argv);

  std::cout << std::left;
  if (!quietMode && printParserResult) {
    std::cout << std::setw(10) << "START" << " = " << number[0] << std::endl;
    std::cout << std::setw(10) << "STOP"  << " = " << number[1] << std::endl;
  }
  try {
    ParallelPrimeSieve pps;
    pps.setStart(number[0]);
    pps.setStop (number[1]);
    if (flags     !=  0) pps.setFlags(flags);
    if (sieveSize != -1) pps.setSieveSize(sieveSize);
    if (preSieve  != -1) pps.setPreSieve(preSieve);
    if (threads   != -1) pps.setNumThreads(threads);

    // set default settings
    if (!pps.isPrint() && !pps.isCount()) pps.addFlags(pps.COUNT_PRIMES);
    if (!pps.isPrint() && !quietMode)     pps.addFlags(pps.PRINT_STATUS);

    if (!quietMode) {
      if (preSieve != -1)
      std::cout << std::setw(10) << "Pre-sieve"  << " = " << pps.getPreSieve()                  << std::endl;
      std::cout << std::setw(10) << "Sieve size" << " = " << pps.getSieveSize() << " kilobytes" << std::endl;
      std::cout << std::setw(10) << "Threads"    << " = " << pps.getNumThreads()                << std::endl;
    }
    // start sieving primes
    pps.sieve();

    if (pps.isFlag(pps.PRINT_STATUS))   std::cout << std::endl;
    if (pps.isPrint() && pps.isCount()) std::cout << std::endl;
    int width = getWidth(pps);

    for (int i = 0; i < 7; i++) {
      if (pps.isCount(i))
        std::cout << std::setw(width)
                  << primes[i] << " : " << pps.getCounts(i)
                  << std::endl;
    }
    if (!pps.isPrint()) {
      std::cout << std::setw(width)
                << "Time elapsed"   << " : "
                << pps.getSeconds() << " sec"
                << std::endl;
    }
    if (!quietMode && pps.getNumThreads() >= 64) {
      std::cout << "\nHint: the -q (Quiet mode) option significantly reduces the thread" << std::endl
                << "synchronization overhead when using >= 64 threads."                  << std::endl;
    }
  }
  catch (std::exception& e) {
    std::cerr << "Error: " << e.what()                          << std::endl
              << "Try `primesieve -help' for more information." << std::endl;
    return 1;
  }
  return 0;
}
<commit_msg>updated exception handling<commit_after>//
// Copyright (c) 2012 Kim Walisch, <kim.walisch@gmail.com>.
// All rights reserved.
//
// This file is part of primesieve.
// Homepage: http://primesieve.googlecode.com
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above
//     copyright notice, this list of conditions and the following
//     disclaimer in the documentation and/or other materials provided
//     with the distribution.
//   * Neither the name of the author nor the names of its
//     contributors may be used to endorse or promote products derived
//     from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

/// @file  main.cpp
/// @brief Command-line version of primesieve, multi-threaded (OpenMP).
/// @see   http://primesieve.googlecode.com
/// primesieve is a highly optimized implementation of the sieve of
/// Eratosthenes that generates prime numbers and prime k-tuplets (twin
/// primes, prime triplets, ...) up to 2^64 maximum.

#include "../soe/ParallelPrimeSieve.h"
#include "../expr/ExpressionParser.h"

#include <stdint.h>
#include <exception>
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
#include <algorithm>

void test();

namespace {

// start and stop number for sieving
std::vector<uint64_t> number;

int preSieve   = -1;
int sieveSize  = -1;
int threads    = -1;
int maxThreads = ParallelPrimeSieve::getMaxThreads();
int flags      = 0;

bool quietMode = false;
bool printParserResult = false;

const std::string primes[7] = {
  "Prime numbers",
  "Twin primes",
  "Prime triplets",
  "Prime quadruplets",
  "Prime quintuplets",
  "Prime sextuplets",
  "Prime septuplets"
};

enum {
  COUNT_PRIMES = ParallelPrimeSieve::COUNT_PRIMES,
  PRINT_PRIMES = ParallelPrimeSieve::PRINT_PRIMES
};

void help() {
  std::cout << "Usage: primesieve START STOP [OPTION]..."                                              << std::endl
            << "Use the segmented sieve of Eratosthenes to generate the prime numbers and/or"          << std::endl
            << "prime k-tuplets in the interval [START, STOP] < 2^64"                                  << std::endl
                                                                                << std::endl
            << "Options:"                                                                              << std::endl
                                                                                << std::endl
            << "  -c<N+>        Count prime numbers and/or prime k-tuplets, 1 <= N <= 7"               << std::endl
            << "                e.g. -c1 count prime numbers (DEFAULT)"                                << std::endl
            << "                     -c23 count twin primes and prime triplets"                        << std::endl
            << "  -o<OFFSET>    Sieve the interval [START, START+OFFSET]"                              << std::endl
            << "  -p<N>         Print prime numbers or prime k-tuplets, 1 <= N <= 7"                   << std::endl
            << "                e.g. -p1 print prime numbers"                                          << std::endl
            << "                     -p5 print prime quintuplets"                                      << std::endl
            << "  -q            Quiet mode, print less output"                                         << std::endl
            << "  -r<PRE-SIEVE> Pre-sieve multiples of small primes <= PRE-SIEVE to speed up"          << std::endl
            << "                the sieve of Eratosthenes, 13 <= PRE-SIEVE <= 23"                      << std::endl
            << "  -s<SIZE>      Set the sieve size in kilobytes, 1 <= SIZE <= 4096"                    << std::endl
            << "                Set SIZE to your CPU's L1/L2 cache size for best performance"          << std::endl
            << "  -t<THREADS>   Set the number of threads for sieving, 1 <= THREADS <= " << maxThreads << std::endl
            << "                Primes are not generated in order if THREADS >= 2"                     << std::endl
            << "  -test         Run various sieving tests and exit"                                    << std::endl
            << "  -v            Print version and license information and exit"                        << std::endl
                                                                                << std::endl
            << "Examples:"                                                                             << std::endl
                                                                                << std::endl
            << "Print the prime numbers up to 1000:"                                                   << std::endl
            << "> primesieve 2 1000 -p1"                                                               << std::endl
                                                                                << std::endl
            << "Count the twin primes in the interval [1E10, 1E10+2^32]:"                              << std::endl
            << "> primesieve 1E10 -o2**32 -c2"                                                         << std::endl;
  std::exit(1);
}

void version() {
  std::cout << "primesieve " << PRIMESIEVE_VERSION << ", <http://primesieve.googlecode.com>" << std::endl
            << "Copyright (C) " << PRIMESIEVE_YEAR << " Kim Walisch" << std::endl
            << "This software is licensed under the New BSD License. See the LICENSE file" << std::endl
            << "for more information." << std::endl;
  std::exit(1);
}

int getWidth(const ParallelPrimeSieve& pps) {
  std::size_t size = 0;
  for (int i = 0; i < 7; i++) {
    if (pps.isCount(i))
      size = std::max(size, primes[i].size());
  }
  return static_cast<int>(size);
}

bool isDigits(const std::string &str) {
  const std::string digits("0123456789");
  if (str.size() == 0)
    return false;
  return str.find_first_not_of(digits) == std::string::npos;
}

/// Process the command-line options.
/// @see help()
///
void processOptions(int argc, char* argv[]) {
  if (argc < 2 || argc > 20) help();
  std::string arg;
  ExpressionParser<uint64_t> parser64;
  ExpressionParser<int> parser;
  uint64_t res = 0;
  int i = 1;

  // process START and STOP number
  for (; i < std::min(3, argc); i++) {
    try {
      number.push_back(parser64.eval(argv[i]));
      if (!isDigits(argv[i]))
        printParserResult = true;
    } catch (...) {
      break;
    }
  }
  for (; i < argc; i++) {
    if (*argv[i] != '-' &&
        *argv[i] != '/') help();
    argv[i]++;
    try {
      switch (*argv[i]++) {
        case 'c': res = parser.eval(argv[i]);
                  do {
                    if (res % 10 < 1 || res % 10 > 7)
                      help();
                    flags |= COUNT_PRIMES << (res % 10 - 1);
                    res /= 10;
                  } while (res > 0);
                  break;
        case 'o': if (number.size() == 0)
                    help();
                  res = number[0] + parser64.eval(argv[i]);
                  number.push_back(res);
                  break;
        case 'p': res = parser.eval(argv[i]);
                  if (res < 1 || res > 7)
                    help();
                  flags |= PRINT_PRIMES << (res - 1);
                  quietMode = true;
                  break;
        case 'q': quietMode = true;                 break;
        case 'r': preSieve  = parser.eval(argv[i]); break;
        case 's': sieveSize = parser.eval(argv[i]); break;
        case 't': arg = argv[i];
                  if (arg.compare("est") == 0)
                    test();
                  threads = parser.eval(argv[i]);
                  break;
        case 'v': version();
        default : help();
      }
    } catch (parser_error&) {
      help();
    }
  }
  if (number.size() != 2)
    help();
}

} // end namespace

int main(int argc, char* argv[]) {
  processOptions(argc, argv);

  std::cout << std::left;
  if (!quietMode && printParserResult) {
    std::cout << std::setw(10) << "START" << " = " << number[0] << std::endl;
    std::cout << std::setw(10) << "STOP"  << " = " << number[1] << std::endl;
  }
  try {
    ParallelPrimeSieve pps;
    pps.setStart(number[0]);
    pps.setStop (number[1]);
    if (flags     !=  0) pps.setFlags(flags);
    if (sieveSize != -1) pps.setSieveSize(sieveSize);
    if (preSieve  != -1) pps.setPreSieve(preSieve);
    if (threads   != -1) pps.setNumThreads(threads);

    // set default settings
    if (!pps.isPrint() && !pps.isCount()) pps.addFlags(pps.COUNT_PRIMES);
    if (!pps.isPrint() && !quietMode)     pps.addFlags(pps.PRINT_STATUS);

    if (!quietMode) {
      if (preSieve != -1)
      std::cout << std::setw(10) << "Pre-sieve"  << " = " << pps.getPreSieve()                  << std::endl;
      std::cout << std::setw(10) << "Sieve size" << " = " << pps.getSieveSize() << " kilobytes" << std::endl;
      std::cout << std::setw(10) << "Threads"    << " = " << pps.getNumThreads()                << std::endl;
    }
    // start sieving primes
    pps.sieve();

    if (pps.isFlag(pps.PRINT_STATUS))   std::cout << std::endl;
    if (pps.isPrint() && pps.isCount()) std::cout << std::endl;
    int width = getWidth(pps);

    for (int i = 0; i < 7; i++) {
      if (pps.isCount(i))
        std::cout << std::setw(width)
                  << primes[i] << " : " << pps.getCounts(i)
                  << std::endl;
    }
    if (!pps.isPrint()) {
      std::cout << std::setw(width)
                << "Time elapsed"   << " : "
                << pps.getSeconds() << " sec"
                << std::endl;
    }
    if (!quietMode && pps.getNumThreads() >= 64) {
      std::cout << "\nHint: the -q (Quiet mode) option significantly reduces the thread" << std::endl
                << "synchronization overhead when using >= 64 threads."                  << std::endl;
    }
  }
  catch (std::exception& e) {
    std::cerr << "Error: " << e.what() << "."                   << std::endl
              << "Try `primesieve -help' for more information." << std::endl;
    return 1;
  }
  return 0;
}
<|endoftext|>


<commit_before>#include <string>
#include <sstream>
#include <iostream>
#include <utility>
#include "texture.hpp"
#include "vfs.hpp"
#include "png.hpp"

namespace MgCore
{
    static int _texCount = 0;

    Image loadPNG(std::string filename)
    {
        std::istringstream file(MgCore::read_file( filename ));
        png::image<png::rgba_pixel> image(file);

        auto pixelBuffer = image.get_pixbuf();

        Image imgData;

        imgData.width = image.get_width();
        imgData.height = image.get_height();
        imgData.length = imgData.width * imgData.height * 4;
        std::unique_ptr<unsigned char[]> data(new unsigned char[imgData.length]());
        imgData.pixelData = std::move(data);

        int i = 0;

        for (int x = 0;x < imgData.width; x++) {
            for (int y = 0; y < imgData.height; y++) {
                auto pixel = pixelBuffer.get_pixel(x, y);
                i = 4 * (y * imgData.width + x);

                imgData.pixelData[i+0] = pixel.red;
                imgData.pixelData[i+1] = pixel.green;
                imgData.pixelData[i+2] = pixel.blue;
                imgData.pixelData[i+3] = pixel.alpha;

            }
        }
        return imgData;
    }

    Texture::Texture(std::string path, ShaderProgram *program)
    : m_path(path), m_program(program)
    {
        _texCount++;
        m_texUnitID = _texCount;

        m_image = MgCore::loadPNG(m_path);

        m_texSampID = m_program->uniform_attribute("textureSampler");

        GLuint texid;
        glGenTextures(1, &texid);
        m_texID = texid;
        glBindTexture(GL_TEXTURE_2D, m_texID);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width, m_image.height,
                0, GL_RGBA, GL_UNSIGNED_BYTE, &(m_image.pixelData.get())[0]);

    }

    void Texture::bind()
    {
        glActiveTexture(GL_TEXTURE0+m_texUnitID);
        glBindTexture(GL_TEXTURE_2D, m_texID);
        m_program->set_uniform(m_texSampID, m_texUnitID);
    }
}<commit_msg>Don't bind the texture again if its the currently active texture.<commit_after>#include <string>
#include <sstream>
#include <iostream>
#include <utility>
#include "texture.hpp"
#include "vfs.hpp"
#include "png.hpp"

namespace MgCore
{
    static int _texCount = 0;
    static GLuint _currentBoundtexture = 0;

    Image loadPNG(std::string filename)
    {
        std::istringstream file(MgCore::read_file( filename ));
        png::image<png::rgba_pixel> image(file);

        auto pixelBuffer = image.get_pixbuf();

        Image imgData;

        imgData.width = image.get_width();
        imgData.height = image.get_height();
        imgData.length = imgData.width * imgData.height * 4;
        std::unique_ptr<unsigned char[]> data(new unsigned char[imgData.length]());
        imgData.pixelData = std::move(data);

        int i = 0;

        for (int x = 0;x < imgData.width; x++) {
            for (int y = 0; y < imgData.height; y++) {
                auto pixel = pixelBuffer.get_pixel(x, y);
                i = 4 * (y * imgData.width + x);

                imgData.pixelData[i+0] = pixel.red;
                imgData.pixelData[i+1] = pixel.green;
                imgData.pixelData[i+2] = pixel.blue;
                imgData.pixelData[i+3] = pixel.alpha;

            }
        }
        return imgData;
    }

    Texture::Texture(std::string path, ShaderProgram *program)
    : m_path(path), m_program(program)
    {
        _texCount++;
        m_texUnitID = _texCount;

        m_image = MgCore::loadPNG(m_path);

        m_texSampID = m_program->uniform_attribute("textureSampler");

        GLuint texid;
        glGenTextures(1, &texid);
        m_texID = texid;
        glBindTexture(GL_TEXTURE_2D, m_texID);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width, m_image.height,
                0, GL_RGBA, GL_UNSIGNED_BYTE, &(m_image.pixelData.get())[0]);

    }

    void Texture::bind()
    {
        if (_currentBoundtexture != m_texUnitID) {
            _currentBoundtexture = m_texUnitID;

            glActiveTexture(GL_TEXTURE0+m_texUnitID);
            glBindTexture(GL_TEXTURE_2D, m_texID);
            m_program->set_uniform(m_texSampID, m_texUnitID);
            std::cout << "Texture bound" << std::endl;

        }
    }
}<|endoftext|>