From 6dd505f8a61e96fb518a573583441d8e1a4f43f6 Mon Sep 17 00:00:00 2001 From: Matchman Green Date: Wed, 16 May 2012 22:35:22 +0800 Subject: [PATCH] added state --- cmake/Modules/FindGDBM.cmake | 48 ++++++++++++++++++ libgrive/CMakeLists.txt | 8 ++- libgrive/src/drive/Drive.cc | 2 - libgrive/src/drive/State.cc | 68 ++++++++++++++++++++++++++ libgrive/src/drive/State.hh | 44 +++++++++++++++++ libgrive/src/protocol/Json.cc | 16 ++++++ libgrive/src/util/Crypt.cc | 7 +++ libgrive/src/util/Crypt.hh | 3 ++ libgrive/src/util/Gdbm.cc | 83 ++++++++++++++++++++++++++++++++ libgrive/src/util/Gdbm.hh | 49 +++++++++++++++++++ libgrive/test/UnitTest.cc | 10 ++++ libgrive/test/drive/StateTest.cc | 42 ++++++++++++++++ libgrive/test/drive/StateTest.hh | 41 ++++++++++++++++ libgrive/test/util/GdbmTest.cc | 54 +++++++++++++++++++++ libgrive/test/util/GdbmTest.hh | 44 +++++++++++++++++ 15 files changed, 515 insertions(+), 4 deletions(-) create mode 100644 cmake/Modules/FindGDBM.cmake create mode 100644 libgrive/src/drive/State.cc create mode 100644 libgrive/src/drive/State.hh create mode 100644 libgrive/src/util/Gdbm.cc create mode 100644 libgrive/src/util/Gdbm.hh create mode 100644 libgrive/test/drive/StateTest.cc create mode 100644 libgrive/test/drive/StateTest.hh create mode 100644 libgrive/test/util/GdbmTest.cc create mode 100644 libgrive/test/util/GdbmTest.hh diff --git a/cmake/Modules/FindGDBM.cmake b/cmake/Modules/FindGDBM.cmake new file mode 100644 index 0000000..e1ba00a --- /dev/null +++ b/cmake/Modules/FindGDBM.cmake @@ -0,0 +1,48 @@ +# - Find gdbm +# Find the native GDBM includes and library +# +# GDBM_INCLUDE_DIR - where to find gdbm.h, etc. +# GDBM_LIBRARIES - List of libraries when using gdbm. +# GDBM_FOUND - True if gdbm found. + + +IF (GDBM_INCLUDE_DIR) + # Already in cache, be silent + SET(GDBM_FIND_QUIETLY TRUE) +ENDIF (GDBM_INCLUDE_DIR) + +FIND_PATH(GDBM_INCLUDE_DIR gdbm.h + /usr/local/include + /usr/include + /opt/local/include +) + +SET(GDBM_NAMES gdbm) +FIND_LIBRARY(GDBM_LIBRARY + NAMES ${GDBM_NAMES} + PATHS /usr/lib /usr/local/lib /opt/local/lib +) + +IF (GDBM_INCLUDE_DIR AND GDBM_LIBRARY) + SET(GDBM_FOUND TRUE) + SET( GDBM_LIBRARIES ${GDBM_LIBRARY} ) +ELSE (GDBM_INCLUDE_DIR AND GDBM_LIBRARY) + SET(GDBM_FOUND FALSE) + SET( GDBM_LIBRARIES ) +ENDIF (GDBM_INCLUDE_DIR AND GDBM_LIBRARY) + +IF (GDBM_FOUND) + IF (NOT GDBM_FIND_QUIETLY) + MESSAGE(STATUS "Found GDBM: ${GDBM_LIBRARY}") + ENDIF (NOT GDBM_FIND_QUIETLY) +ELSE (GDBM_FOUND) + IF (GDBM_FIND_REQUIRED) + MESSAGE(STATUS "Looked for gdbm libraries named ${GDBMS_NAMES}.") + MESSAGE(FATAL_ERROR "Could NOT find gdbm library") + ENDIF (GDBM_FIND_REQUIRED) +ENDIF (GDBM_FOUND) + +MARK_AS_ADVANCED( + GDBM_LIBRARY + GDBM_INCLUDE_DIR +) diff --git a/libgrive/CMakeLists.txt b/libgrive/CMakeLists.txt index c76e4bb..0d0a9fb 100644 --- a/libgrive/CMakeLists.txt +++ b/libgrive/CMakeLists.txt @@ -6,9 +6,10 @@ find_package(OpenSSL REQUIRED) find_package(JSONC REQUIRED) find_package(CURL REQUIRED) find_package(EXPAT REQUIRED) -find_package(CppUnit) -find_package(Boost REQUIRED) +find_package(Boost COMPONENTS filesystem system REQUIRED) +find_package(GDBM REQUIRED) find_package(BFD) +find_package(CppUnit) IF ( CPPUNIT_FOUND ) set( OPT_INCS ${CPPUNIT_INCLUDE_DIR} ) @@ -26,6 +27,7 @@ endif ( BFD_FOUND ) include_directories( ${libgrive_SOURCE_DIR}/src ${libgrive_SOURCE_DIR}/test + ${GDBM_INCLUDE_DIR} ${OPT_INCS} ) @@ -65,6 +67,8 @@ target_link_libraries( grive ${CURL_LIBRARIES} ${JSONC_LIBRARY} ${OPENSSL_LIBRARIES} + ${GDBM_LIBRARIES} + ${Boost_LIBRARIES} ${OPT_LIBS} expat ) diff --git a/libgrive/src/drive/Drive.cc b/libgrive/src/drive/Drive.cc index 1acecf2..cda1f78 100644 --- a/libgrive/src/drive/Drive.cc +++ b/libgrive/src/drive/Drive.cc @@ -71,8 +71,6 @@ Drive::Drive( OAuth2& auth, const Json& state ) : ConstructDirTree( &http ) ; -// http::ResponseLog log( "first-", ".xml", &xrsp ) ; - std::string uri = feed_base + "?showfolders=true&showroot=true" ; /* if ( !change_stamp.empty() ) { diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc new file mode 100644 index 0000000..751c964 --- /dev/null +++ b/libgrive/src/drive/State.cc @@ -0,0 +1,68 @@ +/* + 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 "State.hh" + +#include "util/Crypt.hh" +#include "util/Log.hh" +#include "protocol/Json.hh" + +namespace gr { + +namespace fs = boost::filesystem ; + +State::State( const std::string& filename ) : + m_db( filename ) +{ +} + +void State::Sync( const fs::path& p ) +{ + for ( fs::directory_iterator i( p ) ; i != fs::directory_iterator() ; ++i ) + { + Trace( "file found = %1%", i->path() ) ; + + std::string json = m_db.Get( i->path().string() ) ; + if ( json.empty() ) + { + Trace( "create new entry" ) ; + json = FileInfo(p).Str() ; + } + else + { + Json j = Json::Parse( json ) ; + if ( j["mtime"].Int() != fs::last_write_time(p) ) + { + Trace( "file changed" ) ; + json = FileInfo(p).Str() ; + } + } + + m_db.Set( i->path().string(), json ) ; + } +} + +Json State::FileInfo( const boost::filesystem::path& p ) +{ + Json info ; + info.Add( "mtime", Json( fs::last_write_time(p) ) ) ; + return info ; +} + +} // end of namespace diff --git a/libgrive/src/drive/State.hh b/libgrive/src/drive/State.hh new file mode 100644 index 0000000..f6746a6 --- /dev/null +++ b/libgrive/src/drive/State.hh @@ -0,0 +1,44 @@ +/* + 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 "util/Gdbm.hh" + +#include + +namespace gr { + +class Json ; + +class State +{ +public : + explicit State( const std::string& filename ) ; + + void Sync( const boost::filesystem::path& p ) ; + +private : + static Json FileInfo( const boost::filesystem::path& p ) ; + +private : + Gdbm m_db ; +} ; + +} // end of namespace diff --git a/libgrive/src/protocol/Json.cc b/libgrive/src/protocol/Json.cc index 5ffb19d..ef78a5c 100644 --- a/libgrive/src/protocol/Json.cc +++ b/libgrive/src/protocol/Json.cc @@ -48,6 +48,22 @@ Json::Json( const std::string& str ) : assert( ::json_object_get_string( m_json ) == str ) ; } +template <> +Json::Json( const int& l ) : + m_json( ::json_object_new_int( l ) ) +{ + if ( m_json == 0 ) + throw Error() << expt::ErrMsg( "cannot create json int" ) ; +} + +template <> +Json::Json( const long& l ) : + m_json( ::json_object_new_int( static_cast(l) ) ) +{ + if ( m_json == 0 ) + throw Error() << expt::ErrMsg( "cannot create json int" ) ; +} + Json Json::Parse( const std::string& str ) { struct json_object *json = ::json_tokener_parse( str.c_str() ) ; diff --git a/libgrive/src/util/Crypt.cc b/libgrive/src/util/Crypt.cc index 35deeb0..c1f3f1d 100644 --- a/libgrive/src/util/Crypt.cc +++ b/libgrive/src/util/Crypt.cc @@ -21,12 +21,19 @@ #include #include +#include // dependent libraries #include namespace gr { namespace crypt { +std::string MD5( const boost::filesystem::path& file ) +{ + std::ifstream ifile( file.string().c_str(), std::ios::binary | std::ios::in ) ; + return MD5( ifile.rdbuf() ) ; +} + std::string MD5( std::streambuf *file ) { char buf[64 * 1024] ; diff --git a/libgrive/src/util/Crypt.hh b/libgrive/src/util/Crypt.hh index e7f0293..21a8b6a 100644 --- a/libgrive/src/util/Crypt.hh +++ b/libgrive/src/util/Crypt.hh @@ -22,11 +22,14 @@ #include #include +#include + namespace gr { namespace crypt { std::string MD5( std::streambuf *file ) ; + std::string MD5( const boost::filesystem::path& file ) ; } } // end of namespace gr diff --git a/libgrive/src/util/Gdbm.cc b/libgrive/src/util/Gdbm.cc new file mode 100644 index 0000000..8746b82 --- /dev/null +++ b/libgrive/src/util/Gdbm.cc @@ -0,0 +1,83 @@ +/* + 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 "Gdbm.hh" + +#include + +#include + +#include + +namespace gr { + +struct Gdbm::Impl +{ + GDBM_FILE db ; +} ; + +Gdbm::Gdbm( const std::string& filename ) : + m_impl( new Impl ) +{ + std::string str( filename ) ; + m_impl->db = ::gdbm_open( &str[0], 4096, GDBM_WRCREAT, 0600, &Gdbm::OnError ) ; + if ( m_impl->db == 0 ) + { + char *msg = gdbm_strerror(gdbm_errno) ; + BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( msg ) ) ; + } +} + +Gdbm::~Gdbm() +{ +} + +std::string Gdbm::Get( const std::string& key ) const +{ + std::string ckey = key ; + datum dkey = { &ckey[0], ckey.size() } ; + datum val = gdbm_fetch( m_impl->db, dkey ) ; + + std::string result ; + if ( val.dptr != 0 ) + { + result.append( val.dptr, val.dsize ) ; + ::free( val.dptr ) ; + } + + return result ; +} + +void Gdbm::Set( const std::string& key, const std::string& val ) +{ + assert( m_impl->db != 0 ) ; + + std::string ckey = key, cval = val ; + datum dkey = { &ckey[0], ckey.size() } ; + datum dval = { &cval[0], cval.size() } ; + + gdbm_store( m_impl->db, dkey, dval, GDBM_REPLACE ) ; +} + +void Gdbm::OnError( ) +{ + BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( gdbm_strerror(gdbm_errno) ) ) ; +} + +} // end of namespace diff --git a/libgrive/src/util/Gdbm.hh b/libgrive/src/util/Gdbm.hh new file mode 100644 index 0000000..bd4d49a --- /dev/null +++ b/libgrive/src/util/Gdbm.hh @@ -0,0 +1,49 @@ +/* + 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 +#include + +namespace gr { + +class Gdbm +{ +public : + struct Error : virtual Exception {} ; + +public : + explicit Gdbm( const std::string& filename ) ; + ~Gdbm() ; + + std::string Get( const std::string& key ) const ; + void Set( const std::string& key, const std::string& val ) ; + +private : + static void OnError( ) ; + +private : + struct Impl ; + std::auto_ptr m_impl ; +} ; + +} // end of namespace diff --git a/libgrive/test/UnitTest.cc b/libgrive/test/UnitTest.cc index e02239d..215aa5c 100644 --- a/libgrive/test/UnitTest.cc +++ b/libgrive/test/UnitTest.cc @@ -19,9 +19,13 @@ #include +#include "util/DefaultLog.hh" + #include "drive/EntryTest.hh" +#include "drive/StateTest.hh" #include "util/DateTimeTest.hh" #include "util/FunctionTest.hh" +#include "util/GdbmTest.hh" #include "util/PathTest.hh" #include "util/SignalHandlerTest.hh" #include "xml/NodeTest.hh" @@ -29,13 +33,19 @@ int main( int argc, char **argv ) { using namespace grut ; + + gr::DefaultLog nofile_log ; + nofile_log.Enable( gr::log::debug, true ) ; + gr::LogBase::Inst( &nofile_log ) ; CppUnit::TextUi::TestRunner runner; runner.addTest( EntryTest::suite( ) ) ; + runner.addTest( StateTest::suite( ) ) ; runner.addTest( DateTimeTest::suite( ) ) ; runner.addTest( FunctionTest::suite( ) ) ; runner.addTest( PathTest::suite( ) ) ; runner.addTest( SignalHandlerTest::suite( ) ) ; + runner.addTest( GdbmTest::suite( ) ) ; runner.addTest( NodeTest::suite( ) ) ; runner.run(); diff --git a/libgrive/test/drive/StateTest.cc b/libgrive/test/drive/StateTest.cc new file mode 100644 index 0000000..82261ea --- /dev/null +++ b/libgrive/test/drive/StateTest.cc @@ -0,0 +1,42 @@ +/* + 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 "StateTest.hh" + +#include "Assert.hh" + +#include "drive/State.hh" + +#include + +namespace grut { + +using namespace gr ; + +StateTest::StateTest( ) +{ +} + +void StateTest::TestSync( ) +{ + State s( ".grive_state" ) ; + s.Sync( TEST_DATA ) ; +} + +} // end of namespace grut diff --git a/libgrive/test/drive/StateTest.hh b/libgrive/test/drive/StateTest.hh new file mode 100644 index 0000000..5b2da01 --- /dev/null +++ b/libgrive/test/drive/StateTest.hh @@ -0,0 +1,41 @@ +/* + 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 +#include + +namespace grut { + +class StateTest : public CppUnit::TestFixture +{ +public : + StateTest( ) ; + + // declare suit function + CPPUNIT_TEST_SUITE( StateTest ) ; + CPPUNIT_TEST( TestSync ) ; + CPPUNIT_TEST_SUITE_END(); + +private : + void TestSync( ) ; +} ; + +} // end of namespace diff --git a/libgrive/test/util/GdbmTest.cc b/libgrive/test/util/GdbmTest.cc new file mode 100644 index 0000000..0fbcafa --- /dev/null +++ b/libgrive/test/util/GdbmTest.cc @@ -0,0 +1,54 @@ +/* + 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 "GdbmTest.hh" + +#include "Assert.hh" + +#include "util/Gdbm.hh" + +#include + +namespace grut { + +using namespace gr ; + +GdbmTest::GdbmTest( ) +{ +} + +void GdbmTest::Test( ) +{ + { + Gdbm db( "test.db" ) ; + db.Set( "key", "value" ) ; + GRUT_ASSERT_EQUAL( db.Get("key"), "value" ) ; + } + + // re-open and verify + Gdbm db( "test.db" ) ; + GRUT_ASSERT_EQUAL( db.Get("key"), "value" ) ; +} + +void GdbmTest::tearDown() +{ + unlink( "test.db" ) ; +} + +} // end of namespace grut diff --git a/libgrive/test/util/GdbmTest.hh b/libgrive/test/util/GdbmTest.hh new file mode 100644 index 0000000..d7477d9 --- /dev/null +++ b/libgrive/test/util/GdbmTest.hh @@ -0,0 +1,44 @@ +/* + 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 +#include + +namespace grut { + +class GdbmTest : public CppUnit::TestFixture +{ +public : + GdbmTest( ) ; + + // declare suit function + CPPUNIT_TEST_SUITE( GdbmTest ) ; + CPPUNIT_TEST( Test ) ; + CPPUNIT_TEST_SUITE_END(); + +public : + void tearDown() ; + +private : + void Test( ) ; +} ; + +} // end of namespace