improved logging and fixed exception on MD5 calculation

pull/40/head
Matchman Green 2012-05-20 23:16:59 +08:00
parent 90bf78e716
commit 99f6e4cc58
11 changed files with 123 additions and 30 deletions

View File

@ -49,7 +49,7 @@ int main( int argc, char **argv )
LogBase::Inst( &nofile_log ) ; LogBase::Inst( &nofile_log ) ;
int c ; int c ;
while ((c = getopt(argc, argv, "al:v")) != -1) while ((c = getopt(argc, argv, "al:vV")) != -1)
{ {
switch ( c ) switch ( c )
{ {
@ -91,6 +91,12 @@ int main( int argc, char **argv )
<< "grive version " VERSION " " __DATE__ " " __TIME__ << std::endl ; << "grive version " VERSION " " __DATE__ " " __TIME__ << std::endl ;
return 0 ; return 0 ;
} }
case 'V' :
{
LogBase::Inst()->Enable( log::verbose ) ;
break ;
}
} }
} }
@ -117,9 +123,9 @@ int main( int argc, char **argv )
Drive drive( token ) ; Drive drive( token ) ;
drive.Update() ; drive.Update() ;
// drive.SaveState() ; drive.SaveState() ;
config.Save() ; // config.Save() ;
} }
catch ( gr::Exception& e ) catch ( gr::Exception& e )
{ {

View File

@ -92,20 +92,20 @@ Drive::Drive( OAuth2& auth ) :
{ {
if ( (*i)["content"] == "" ) if ( (*i)["content"] == "" )
continue ; continue ;
Entry file( *i ) ; Entry file( *i ) ;
if ( file.Kind() != "folder" ) if ( file.Kind() != "folder" )
{ {
Resource *p = m_state.FindFolderByHref( file.ParentHref() ) ; Resource *p = m_state.FindFolderByHref( file.ParentHref() ) ;
if ( file.Filename().empty() ) if ( file.Filename().empty() )
Log( "file \"%1%\" is a google document, ignored", file.Title() ) ; Log( "file \"%1%\" is a google document, ignored", file.Title(), log::info ) ;
else if ( file.ParentHref().empty() || p == 0 || !p->IsInRootTree() ) else if ( file.ParentHref().empty() || p == 0 || !p->IsInRootTree() )
Log( "file \"%1%\" parent doesn't exist, ignored", file.Title() ) ; Log( "file \"%1%\" parent doesn't exist, ignored", file.Title(), log::info ) ;
else if ( p != 0 && !p->IsFolder() ) else if ( p != 0 && !p->IsFolder() )
Log( "entry %1% has parent %2% which is not a folder, ignored", Log( "entry %1% has parent %2% which is not a folder, ignored",
file.Title(), p->Name() ) ; file.Title(), p->Name(), log::info ) ;
else else
m_state.FromRemote( file ) ; m_state.FromRemote( file ) ;

View File

@ -24,6 +24,7 @@
#include "http/StringResponse.hh" #include "http/StringResponse.hh"
#include "http/XmlResponse.hh" #include "http/XmlResponse.hh"
#include "protocol/Json.hh" #include "protocol/Json.hh"
#include "util/CArray.hh"
#include "util/Crypt.hh" #include "util/Crypt.hh"
#include "util/Log.hh" #include "util/Log.hh"
#include "util/OS.hh" #include "util/OS.hh"
@ -94,14 +95,17 @@ void Resource::FromRemote( const Entry& remote )
{ {
// if checksum is equal, no need to compare the mtime // if checksum is equal, no need to compare the mtime
if ( remote.MD5() == m_entry.MD5() ) if ( remote.MD5() == m_entry.MD5() )
{
Log( "MD5 matches: %1% is already in sync", Name(), log::verbose ) ;
m_state = sync ; m_state = sync ;
}
// use mtime to check which one is more recent // use mtime to check which one is more recent
else else
{ {
assert( m_state == local_new || m_state == local_changed || m_state == local_deleted ) ; assert( m_state == local_new || m_state == local_changed || m_state == local_deleted ) ;
m_state = ( remote.MTime() > m_entry.MTime() ? remote_changed : m_state ) ; m_state = ( remote.MTime() > m_entry.MTime() ? remote_changed : m_state ) ;
Log( "%1% state is %2%", Name(), m_state, log::verbose ) ;
} }
m_entry = remote ; m_entry = remote ;
@ -111,18 +115,30 @@ void Resource::FromLocal()
{ {
fs::path path = Path() ; fs::path path = Path() ;
if ( !fs::exists( path ) ) if ( !fs::exists( path ) )
{
m_state = local_deleted ; m_state = local_deleted ;
Log( "%1% in state but not exist on disk: %2%", Name(), m_state ) ;
}
// to save time, compare mtime before checksum // to save time, compare mtime before checksum
else if ( m_entry.MTime() > os::FileMTime( path ) ) else if ( os::FileMTime( path ) > m_entry.MTime() )
{ {
if ( m_entry.MD5() == crypt::MD5( path ) ) if ( m_entry.MD5() == crypt::MD5( path ) )
{
m_state = local_new ; m_state = local_new ;
Log( "%1% mtime newer on disk but unchanged: %2%", Name(), m_state ) ;
}
else else
{
m_state = local_changed ; m_state = local_changed ;
Log( "%1% changed on disk: %2%", Name(), m_state ) ;
}
} }
else else
m_state = local_changed ; {
m_state = local_new ;
Log( "%1% unchanged on disk: %2%", Name(), m_state ) ;
}
} }
std::string Resource::SelfHref() const std::string Resource::SelfHref() const
@ -214,25 +230,30 @@ void Resource::Sync( http::Agent *http, const http::Headers& auth )
switch ( m_state ) switch ( m_state )
{ {
case local_new : case local_new :
Trace( "file %1% doesn't exist in server. upload?", m_entry.Filename() ) ; Log( "sync %1% doesn't exist in server. upload?", m_entry.Filename(), log::verbose ) ;
break ;
case local_deleted :
Log( "sync %1% deleted in local. delete?", m_entry.Filename(), log::verbose ) ;
break ; break ;
case local_changed : case local_changed :
Trace( "file %1% changed in local", m_entry.Filename() ) ; Log( "sync %1% changed in local", m_entry.Filename(), log::verbose ) ;
if ( Upload( http, auth ) ) if ( Upload( http, auth ) )
m_state = sync ; m_state = sync ;
break ; break ;
case remote_new : case remote_new :
case remote_changed : case remote_changed :
Trace( "file %1% changed in remote", m_entry.Filename() ) ; Log( "sync %1% changed in remote. download?", m_entry.Filename(), log::verbose ) ;
Download( http, Path(), auth ) ; Download( http, Path(), auth ) ;
m_state = sync ; m_state = sync ;
break ; break ;
case sync : case sync :
Trace( "file %1% already in sync", m_entry.Filename() ) ; Log( "sync %1% already in sync", m_entry.Filename(), log::verbose ) ;
break ;
default : default :
break ; break ;
} }
@ -356,6 +377,16 @@ std::size_t Resource::size() const
return m_child.size() ; return m_child.size() ;
} }
std::ostream& operator<<( std::ostream& os, Resource::State s )
{
static const char *state[] =
{
"sync", "local_new", "local_changed", "local_deleted", "remote_new", "remote_changed"
} ;
assert( s >= 0 && s < Count(state) ) ;
return os << state[s] ;
}
} // end of namespace } // end of namespace
namespace std namespace std

View File

@ -108,12 +108,14 @@ private :
/// Resource exists in both local & remote, but remote is newer. /// Resource exists in both local & remote, but remote is newer.
remote_changed remote_changed
} ; } ;
friend std::ostream& operator<<( std::ostream& os, State s ) ;
private : private :
void Download( http::Agent* http, const fs::path& file, const http::Headers& auth ) const ; void Download( http::Agent* http, const fs::path& file, const http::Headers& auth ) const ;
bool Upload( http::Agent* http, const http::Headers& auth ) ; bool Upload( http::Agent* http, const http::Headers& auth ) ;
bool Upload( http::Agent* http, std::streambuf *file, const http::Headers& auth ) ; bool Upload( http::Agent* http, std::streambuf *file, const http::Headers& auth ) ;
private : private :
Entry m_entry ; Entry m_entry ;

View File

@ -74,9 +74,12 @@ void State::FromLocal( const fs::path& p, gr::Resource* folder )
else else
{ {
// if the Resource object of the child already exists, it should
// have been so no need to do anything here
Resource *c = folder->FindChild( fname ) ; Resource *c = folder->FindChild( fname ) ;
if ( c == 0 ) if ( c == 0 )
{ {
Log( "detected new file %1% in local", fname, log::verbose ) ;
c = new Resource( i->path() ) ; c = new Resource( i->path() ) ;
folder->AddChild( c ) ; folder->AddChild( c ) ;
m_res.Insert( c ) ; m_res.Insert( c ) ;

View File

@ -19,22 +19,30 @@
#include "Crypt.hh" #include "Crypt.hh"
#include "StdioFile.hh"
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <fstream>
// dependent libraries // dependent libraries
#include <openssl/evp.h> #include <openssl/evp.h>
namespace gr { namespace crypt { namespace gr { namespace crypt {
std::string MD5( const boost::filesystem::path& file ) std::string MD5( const fs::path& file )
{ {
std::ifstream ifile( file.string().c_str(), std::ios::binary | std::ios::in ) ; try
return MD5( ifile.rdbuf() ) ; {
StdioFile sfile( file, "rb" ) ;
return MD5( sfile ) ;
}
catch ( StdioFile::Error& )
{
return "" ;
}
} }
std::string MD5( std::streambuf *file ) std::string MD5( StdioFile& file )
{ {
char buf[64 * 1024] ; char buf[64 * 1024] ;
EVP_MD_CTX md ; EVP_MD_CTX md ;
@ -42,7 +50,7 @@ std::string MD5( std::streambuf *file )
EVP_DigestInit_ex( &md, EVP_md5(), 0 ) ; EVP_DigestInit_ex( &md, EVP_md5(), 0 ) ;
std::size_t count = 0 ; std::size_t count = 0 ;
while ( (count = file->sgetn( buf, sizeof(buf) )) > 0 ) while ( (count = file.Read( buf, sizeof(buf) )) > 0 )
{ {
EVP_DigestUpdate( &md, buf, count ) ; EVP_DigestUpdate( &md, buf, count ) ;
} }

View File

@ -20,15 +20,16 @@
#pragma once #pragma once
#include <string> #include <string>
#include <iosfwd>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
namespace gr { namespace gr {
class StdioFile ;
namespace crypt namespace crypt
{ {
std::string MD5( std::streambuf *file ) ; std::string MD5( StdioFile& file ) ;
std::string MD5( const boost::filesystem::path& file ) ; std::string MD5( const boost::filesystem::path& file ) ;
} }

View File

@ -28,6 +28,7 @@ DefaultLog::DefaultLog() :
m_log( std::cerr ) m_log( std::cerr )
{ {
m_enabled[log::debug] = false ; m_enabled[log::debug] = false ;
m_enabled[log::verbose] = false ;
m_enabled[log::info] = true ; m_enabled[log::info] = true ;
m_enabled[log::warning] = true ; m_enabled[log::warning] = true ;
m_enabled[log::error] = true ; m_enabled[log::error] = true ;
@ -39,6 +40,7 @@ DefaultLog::DefaultLog( const std::string& filename ) :
m_log( m_file ) m_log( m_file )
{ {
m_enabled[log::debug] = true ; m_enabled[log::debug] = true ;
m_enabled[log::verbose] = true ;
m_enabled[log::info] = true ; m_enabled[log::info] = true ;
m_enabled[log::warning] = true ; m_enabled[log::warning] = true ;
m_enabled[log::error] = true ; m_enabled[log::error] = true ;

View File

@ -25,7 +25,7 @@ namespace gr {
namespace log namespace log
{ {
enum Serverity { debug, info, warning, error, critical } ; enum Serverity { debug, verbose, info, warning, error, critical } ;
typedef boost::format Fmt ; typedef boost::format Fmt ;
} }

View File

@ -32,9 +32,29 @@
namespace gr { namespace gr {
StdioFile::StdioFile( const std::string& filename, const char *mode ) : StdioFile::StdioFile( const std::string& filename, const char *mode ) : m_file( 0 )
m_file( std::fopen( filename.c_str(), mode ) )
{ {
Open( filename, mode ) ;
}
StdioFile::StdioFile( const fs::path& path, const char *mode ) : m_file( 0 )
{
Open( path, mode ) ;
}
StdioFile::~StdioFile( )
{
Close() ;
}
void StdioFile::Open( const std::string& filename, const char *mode )
{
if ( IsOpened() )
Close() ;
assert( m_file == 0 ) ;
m_file = std::fopen( filename.c_str(), mode ) ;
if ( m_file == 0 ) if ( m_file == 0 )
{ {
BOOST_THROW_EXCEPTION( BOOST_THROW_EXCEPTION(
@ -47,10 +67,23 @@ StdioFile::StdioFile( const std::string& filename, const char *mode ) :
} }
} }
StdioFile::~StdioFile( ) void StdioFile::Open( const fs::path& path, const char *mode )
{ {
assert( m_file != 0 ) ; Open( path.string(), mode ) ;
std::fclose( m_file ) ; }
void StdioFile::Close()
{
if ( IsOpened() )
{
std::fclose( m_file ) ;
m_file = 0 ;
}
}
bool StdioFile::IsOpened() const
{
return m_file != 0 ;
} }
std::size_t StdioFile::Read( void *ptr, std::size_t size ) std::size_t StdioFile::Read( void *ptr, std::size_t size )

View File

@ -20,6 +20,7 @@
#pragma once #pragma once
#include "Exception.hh" #include "Exception.hh"
#include "FileSystem.hh"
#include <cstdio> #include <cstdio>
#include <string> #include <string>
@ -33,7 +34,13 @@ public :
public : public :
StdioFile( const std::string& filename, const char *mode ) ; StdioFile( const std::string& filename, const char *mode ) ;
StdioFile( const fs::path& path, const char *mode ) ;
~StdioFile( ) ; ~StdioFile( ) ;
void Open( const std::string& filename, const char *mode ) ;
void Open( const boost::filesystem3::path& path, const char* mode ) ;
void Close() ;
bool IsOpened() const ;
std::size_t Read( void *ptr, std::size_t size ) ; std::size_t Read( void *ptr, std::size_t size ) ;
std::size_t Write( const void *ptr, std::size_t size ) ; std::size_t Write( const void *ptr, std::size_t size ) ;