<commit_before>//----------------------------------------------------------------------------
/// \file   persist_blob.cpp
/// \author <NAME>
//----------------------------------------------------------------------------
/// \brief Persistent blob stored in memory mapped file
//----------------------------------------------------------------------------
// Copyright (c) 2010 <NAME> <<EMAIL>>
// Created: 2010-1-15
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 <NAME> <<EMAIL>>

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

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

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

***** END LICENSE BLOCK *****
*/

#ifndef _UTXX_PERSIST_BLOB_HPP_
#define _UTXX_PERSIST_BLOB_HPP_

#include <utxx/config.h>

#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/scope_exit.hpp>
#include <boost/assert.hpp>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/unistd.h>
//#include <sys/mman.h>
#include <string>
#include <string.h>
#include <utxx/atomic.hpp>
#include <utxx/meta.hpp>
#include <utxx/path.hpp>
#include <utxx/error.hpp>
#include <utxx/lock.hpp>

namespace utxx {

    namespace {
        namespace bip = boost::interprocess;
    }

/// Persistent blob of type T stored in memory mapped file.
template<typename T, typename Lock = robust_lock>
class persist_blob
{
private:
    struct blob_t {
        static const uint32_t s_version = 0xFEAB0001;
        typename Lock::lock_data lock_data;
        uint32_t version;
        T        data;
    } __attribute__((aligned(UTXX_CL_SIZE)));

    BOOST_STATIC_ASSERT(sizeof(blob_t) % atomic::cacheline::size == 0);

    blob_t*             m_blob;
    bip::file_mapping   m_file;
    bip::mapped_region  m_region;

    std::string         m_filename;
    Lock                m_lock;

public:
    typedef T                               value_type;
    typedef typename Lock::scoped_lock      scoped_lock;
    typedef typename Lock::scoped_try_lock  scoped_try_lock;

    persist_blob()
        : m_blob(NULL)
        , m_lock(false)
    {}

    ~persist_blob() { close(); }

    /// Default permission mask used for opening a file
    static int default_file_mode() { return S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; }

    /// @return true if file didn't exist and was created.
    bool init(const char* a_file, const T* a_init_val = NULL,
        bool a_read_only = true, int a_mode = default_file_mode())
        throw (io_error);

    bool is_open() const { return m_blob; }

    void close();

    void reset();

    int  flush()  { return m_blob && m_region.flush() ? 0 : -1; }

    /// Name of the underlying memory mapped file
    const std::string& filename() const { return m_filename; }

    // Use the following get/set functions for concurrent access
    T    get();
    void set(const T& src);

    Lock& get_lock() { return m_lock; }

    // Use the following get/set functions for non-concurrent "dirty" access
    T&       dirty_get()                { BOOST_ASSERT(m_blob); return m_blob->data; }
    const T& dirty_get() const          { BOOST_ASSERT(m_blob); return m_blob->data; }
    void     dirty_set(const T& src)    { BOOST_ASSERT(m_blob); m_blob->data = src;  }

    T*       operator->()               { return dirty_get(); }
    const T* operator->()       const   { return dirty_get(); }

};

template<typename T, typename L>
bool persist_blob<T,L>::init(const char* a_file, const T* a_init_val,
    bool a_read_only, int a_mode) throw (io_error)
{
    BOOST_ASSERT(a_file);

    close();

    bool l_created     = !path::file_exists(a_file);
    bool l_initialized = false;
    {<commit_msg>persist_blob operator->() minor fix<commit_after>//----------------------------------------------------------------------------
/// \file   persist_blob.cpp
/// \author <NAME>
//----------------------------------------------------------------------------
/// \brief Persistent blob stored in memory mapped file
//----------------------------------------------------------------------------
// Copyright (c) 2010 <NAME> <<EMAIL>>
// Created: 2010-1-15
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 <NAME> <<EMAIL>>

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

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

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

***** END LICENSE BLOCK *****
*/

#ifndef _UTXX_PERSIST_BLOB_HPP_
#define _UTXX_PERSIST_BLOB_HPP_

#include <utxx/config.h>

#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/scope_exit.hpp>
#include <boost/assert.hpp>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/unistd.h>
//#include <sys/mman.h>
#include <string>
#include <string.h>
#include <utxx/atomic.hpp>
#include <utxx/meta.hpp>
#include <utxx/path.hpp>
#include <utxx/error.hpp>
#include <utxx/lock.hpp>

namespace utxx {

    namespace {
        namespace bip = boost::interprocess;
    }

/// Persistent blob of type T stored in memory mapped file.
template<typename T, typename Lock = robust_lock>
class persist_blob
{
private:
    struct blob_t {
        static const uint32_t s_version = 0xFEAB0001;
        typename Lock::lock_data lock_data;
        uint32_t version;
        T        data;
    } __attribute__((aligned(UTXX_CL_SIZE)));

    BOOST_STATIC_ASSERT(sizeof(blob_t) % atomic::cacheline::size == 0);

    blob_t*             m_blob;
    bip::file_mapping   m_file;
    bip::mapped_region  m_region;

    std::string         m_filename;
    Lock                m_lock;

public:
    typedef T                               value_type;
    typedef typename Lock::scoped_lock      scoped_lock;
    typedef typename Lock::scoped_try_lock  scoped_try_lock;

    persist_blob()
        : m_blob(NULL)
        , m_lock(false)
    {}

    ~persist_blob() { close(); }

    /// Default permission mask used for opening a file
    static int default_file_mode() { return S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; }

    /// @return true if file didn't exist and was created.
    bool init(const char* a_file, const T* a_init_val = NULL,
        bool a_read_only = true, int a_mode = default_file_mode())
        throw (io_error);

    bool is_open() const { return m_blob; }

    void close();

    void reset();

    int  flush()  { return m_blob && m_region.flush() ? 0 : -1; }

    /// Name of the underlying memory mapped file
    const std::string& filename() const { return m_filename; }

    // Use the following get/set functions for concurrent access
    T    get();
    void set(const T& src);

    Lock& get_lock() { return m_lock; }

    // Use the following get/set functions for non-concurrent "dirty" access
    T&       dirty_get()                { BOOST_ASSERT(m_blob); return m_blob->data; }
    const T& dirty_get() const          { BOOST_ASSERT(m_blob); return m_blob->data; }
    void     dirty_set(const T& src)    { BOOST_ASSERT(m_blob); m_blob->data = src;  }

    T*       operator->()               { return &dirty_get(); }
    const T* operator->()       const   { return &dirty_get(); }

};

template<typename T, typename L>
bool persist_blob<T,L>::init(const char* a_file, const T* a_init_val,
    bool a_read_only, int a_mode) throw (io_error)
{
    BOOST_ASSERT(a_file);

    close();

    bool l_created     = !path::file_exists(a_file);
    bool l_initialized = false;
    {
{'fraction_non_alphanumeric': 0.17094794271425323, 'fraction_numerical': 0.00977494885201182, 'mean_word_length': 2.32163080407701, 'pattern_counts': {'":': 0, '<': 57, '<?xml version=': 0, '>': 68, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7194646', 'n_tokens_mistral': 2747, 'n_tokens_neox': 2592, 'n_words': 831}