From 75c67dad8d9861f5c3f64a9260af4f1692306a7a Mon Sep 17 00:00:00 2001 From: Nestal Wan Date: Tue, 17 Jul 2012 01:08:34 +0800 Subject: [PATCH] added class & functions for memory mapped files --- libgrive/src/drive/Resource.cc | 6 ++- libgrive/src/util/MemMap.cc | 46 +++++++++++++++++++ libgrive/src/util/MemMap.hh | 47 +++++++++++++++++++ libgrive/src/util/StdioFile.cc | 83 ++++++++++++++++++++++++++++++++-- libgrive/src/util/StdioFile.hh | 9 +++- libgrive/src/util/Types.hh | 31 +++++++++++++ 6 files changed, 214 insertions(+), 8 deletions(-) create mode 100644 libgrive/src/util/MemMap.cc create mode 100644 libgrive/src/util/MemMap.hh create mode 100644 libgrive/src/util/Types.hh diff --git a/libgrive/src/drive/Resource.cc b/libgrive/src/drive/Resource.cc index 5e7529d..0f056fc 100644 --- a/libgrive/src/drive/Resource.cc +++ b/libgrive/src/drive/Resource.cc @@ -589,9 +589,11 @@ bool Resource::Upload( std::size_t count = 0 ; while ( (count = file.Read( buf, sizeof(buf) )) > 0 ) data.append( buf, count ) ; - + + assert( file.Size() == data.size() ) ; + std::ostringstream xcontent_len ; - xcontent_len << "X-Upload-Content-Length: " << data.size() ; + xcontent_len << "X-Upload-Content-Length: " << file.Size() ; http::Header hdr( auth ) ; hdr.Add( "Content-Type: application/atom+xml" ) ; diff --git a/libgrive/src/util/MemMap.cc b/libgrive/src/util/MemMap.cc new file mode 100644 index 0000000..6f8b4c7 --- /dev/null +++ b/libgrive/src/util/MemMap.cc @@ -0,0 +1,46 @@ +/* + grive: an GPL program to sync a local directory with Google Drive + Copyright (C) 2012 Wan Wai Ho + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "MemMap.hh" +#include "StdioFile.hh" + +namespace gr { + +MemMap::MemMap( StdioFile& file, off_t offset, std::size_t length ) : + m_addr ( file.Map( offset, length ) ), + m_length( length ) +{ +} + +MemMap::~MemMap() +{ + StdioFile::UnMap( m_addr, m_length ) ; +} + +void* MemMap::Addr() const +{ + return m_addr ; +} + +std::size_t MemMap::Length() const +{ + return m_length ; +} + +} // end of namespace diff --git a/libgrive/src/util/MemMap.hh b/libgrive/src/util/MemMap.hh new file mode 100644 index 0000000..91a3033 --- /dev/null +++ b/libgrive/src/util/MemMap.hh @@ -0,0 +1,47 @@ +/* + grive: an GPL program to sync a local directory with Google Drive + Copyright (C) 2012 Wan Wai Ho + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include "Exception.hh" +#include "Types.hh" +#include + +namespace gr { + +class StdioFile ; + +class MemMap +{ +public : + struct Error : virtual Exception {} ; + +public : + MemMap( StdioFile& file, off_t offset, std::size_t length ) ; + ~MemMap() ; + + void* Addr() const ; + std::size_t Length() const ; + +private : + void *m_addr ; + std::size_t m_length ; +} ; + +} // end of namespace diff --git a/libgrive/src/util/StdioFile.cc b/libgrive/src/util/StdioFile.cc index ae0d41b..435aea9 100644 --- a/libgrive/src/util/StdioFile.cc +++ b/libgrive/src/util/StdioFile.cc @@ -30,10 +30,47 @@ #include #include +#include #include #include #include +// local functions +namespace { + +off_t LSeek( int fd, off_t offset, int whence ) +{ + assert( fd >= 0 ) ; + + off_t r = ::lseek( fd, offset, whence ) ; + if ( r == static_cast(-1) ) + { + BOOST_THROW_EXCEPTION( + gr::StdioFile::Error() + << boost::errinfo_api_function("lseek") + << boost::errinfo_errno(errno) + ) ; + } + + return r ; +} + +struct stat FStat( int fd ) +{ + struct stat s = {} ; + if ( ::fstat( fd, &s ) != 0 ) + { + BOOST_THROW_EXCEPTION( + gr::StdioFile::Error() + << boost::errinfo_api_function("fstat") + << boost::errinfo_errno(errno) + ) ; + } + return s ; +} + +} // end of local functions + namespace gr { StdioFile::StdioFile( ) : m_fd( -1 ) @@ -127,16 +164,26 @@ std::size_t StdioFile::Write( const void *ptr, std::size_t size ) return count ; } -long StdioFile::Seek( long offset, int whence ) +off_t StdioFile::Seek( off_t offset, int whence ) { assert( IsOpened() ) ; - return ::lseek( m_fd, offset, whence ) ; + return LSeek( m_fd, offset, whence ) ; } -long StdioFile::Tell() const +off_t StdioFile::Tell() const { assert( IsOpened() ) ; - return ::lseek( m_fd, 0, SEEK_CUR ) ; + return LSeek( m_fd, 0, SEEK_CUR ) ; +} + +u64_t StdioFile::Size() const +{ + assert( IsOpened() ) ; + + struct stat s = FStat(m_fd) ; + + assert( s.st_size >= 0 ) ; + return static_cast( s.st_size ) ; } void StdioFile::Chmod( int mode ) @@ -153,4 +200,32 @@ void StdioFile::Chmod( int mode ) } } +void* StdioFile::Map( off_t offset, std::size_t length ) +{ + assert( IsOpened() ) ; + + void *addr = ::mmap( 0, length, PROT_READ, MAP_PRIVATE, m_fd, offset ) ; + if ( addr == reinterpret_cast( -1 ) ) + { + BOOST_THROW_EXCEPTION( + Error() + << boost::errinfo_api_function("mmap") + << boost::errinfo_errno(errno) + ) ; + } + return addr ; +} + +void StdioFile::UnMap( void *addr, std::size_t length ) +{ + if ( ::munmap( addr, length ) != 0 ) + { + BOOST_THROW_EXCEPTION( + Error() + << boost::errinfo_api_function("munmap") + << boost::errinfo_errno(errno) + ) ; + } +} + } // end of namespace diff --git a/libgrive/src/util/StdioFile.hh b/libgrive/src/util/StdioFile.hh index 30de2fb..21443b6 100644 --- a/libgrive/src/util/StdioFile.hh +++ b/libgrive/src/util/StdioFile.hh @@ -21,6 +21,7 @@ #include "Exception.hh" #include "FileSystem.hh" +#include "Types.hh" #include @@ -45,11 +46,15 @@ public : std::size_t Read( void *ptr, std::size_t size ) ; std::size_t Write( const void *ptr, std::size_t size ) ; - long Seek( long offset, int whence ) ; - long Tell() const ; + off_t Seek( off_t offset, int whence ) ; + off_t Tell() const ; + u64_t Size() const ; void Chmod( int mode ) ; + void* Map( off_t offset, std::size_t length ) ; + static void UnMap( void *addr, std::size_t length ) ; + private : void Open( const fs::path& path, int flags, int mode ) ; diff --git a/libgrive/src/util/Types.hh b/libgrive/src/util/Types.hh new file mode 100644 index 0000000..a981c6d --- /dev/null +++ b/libgrive/src/util/Types.hh @@ -0,0 +1,31 @@ +/* + grive: an GPL program to sync a local directory with Google Drive + Copyright (C) 2012 Wan Wai Ho + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include + +// import types into the Grive namespace +namespace gr +{ + using ::off_t ; + + // should use boost/cstdint + typedef unsigned long long u64_t ; +}