diff options
author | Denis Koronchik <denis@mapswithme.com> | 2014-09-16 12:05:39 +0400 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-23 02:28:17 +0300 |
commit | d8f3008ecc7300e87262308e753c7bf3d850c9e9 (patch) | |
tree | 44b2d2bc6df3299d66681a200bf4d7f2962f4d59 /coding/file_container.cpp | |
parent | b353a8adaef05206e4bf6769695e566d8e5989ce (diff) |
[coding] Implement FileMappingContainer
Diffstat (limited to 'coding/file_container.cpp')
-rw-r--r-- | coding/file_container.cpp | 85 |
1 files changed, 79 insertions, 6 deletions
diff --git a/coding/file_container.cpp b/coding/file_container.cpp index 28716334e1..40c64f7e64 100644 --- a/coding/file_container.cpp +++ b/coding/file_container.cpp @@ -5,6 +5,17 @@ #include "write_to_sink.hpp" #include "internal/file_data.hpp" +#ifndef OMIM_OS_WINDOWS + #include <unistd.h> + #include <sys/mman.h> + #include <sys/stat.h> + #ifdef OMIM_OS_ANDROID + #include <fcntl.h> + #else + #include <sys/fcntl.h> + #endif +#endif + template <class TSource> void Read(TSource & src, FilesContainerBase::Info & i) { @@ -64,21 +75,83 @@ FilesContainerR::FilesContainerR(ReaderT const & file) FilesContainerR::ReaderT FilesContainerR::GetReader(Tag const & tag) const { + Info const * p = GetInfo(tag); + if (p) + return m_source.SubReader(p->m_offset, p->m_size); + else + MYTHROW(Reader::OpenException, (tag)); +} + +FilesContainerBase::Info const * FilesContainerBase::GetInfo(Tag const & tag) const +{ InfoContainer::const_iterator i = lower_bound(m_info.begin(), m_info.end(), tag, LessInfo()); if (i != m_info.end() && i->m_tag == tag) - return m_source.SubReader(i->m_offset, i->m_size); + return &(*i); else - MYTHROW(Reader::OpenException, (tag)); + return 0; } -bool FilesContainerR::IsReaderExist(Tag const & tag) const +///////////////////////////////////////////////////////////////////////////// +// FilesMappingContainer +///////////////////////////////////////////////////////////////////////////// + +FilesMappingContainer::FilesMappingContainer(string const & fName) { - InfoContainer::const_iterator i = - lower_bound(m_info.begin(), m_info.end(), tag, LessInfo()); + { + FileReader reader(fName, 10, 1); + ReadInfo(reader); + } + + m_fd = open(fName.c_str(), O_RDONLY | O_NONBLOCK); + if (m_fd == -1) + MYTHROW(Reader::OpenException, ("Can't open file:", fName)); +} + +FilesMappingContainer::~FilesMappingContainer() +{ + close(m_fd); +} + +FilesMappingContainer::Handle FilesMappingContainer::Map(Tag const & tag) const +{ + Info const * p = GetInfo(tag); + if (p) + { + long const offsetAlign = sysconf(_SC_PAGE_SIZE); + + uint64_t const offset = (p->m_offset / offsetAlign) * offsetAlign; + ASSERT_LESS_OR_EQUAL(offset, p->m_offset, ()); + uint64_t const length = p->m_size + (p->m_offset - offset); + ASSERT_GREATER_OR_EQUAL(length, p->m_size, ()); + + char const * data = reinterpret_cast<char const *>(mmap(0, length, PROT_READ, MAP_SHARED, m_fd, offset)); + + if (data == reinterpret_cast<char const *>(-1)) + MYTHROW(Reader::OpenException, ("Can't map section:", tag, "with [offset, size]:", *p)); + + char const * d = data + (p->m_offset - offset); + return Handle(d, data, p->m_size, length); + } + else + MYTHROW(Reader::OpenException, ("Can't find section:", tag)); + + return Handle(); +} + +FilesMappingContainer::Handle::~Handle() +{ +// CHECK(!IsValid(), ()); +} + +void FilesMappingContainer::Handle::Unmap() +{ + ASSERT(IsValid(), ()); + VERIFY(0 == munmap((void*)m_origBase, m_origSize), ()); - return (i != m_info.end() && i->m_tag == tag); + m_origBase = m_base = 0; + m_origSize = m_size = 0; } ///////////////////////////////////////////////////////////////////////////// |