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

View File

@ -92,20 +92,20 @@ Drive::Drive( OAuth2& auth ) :
{
if ( (*i)["content"] == "" )
continue ;
Entry file( *i ) ;
if ( file.Kind() != "folder" )
{
Resource *p = m_state.FindFolderByHref( file.ParentHref() ) ;
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() )
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() )
Log( "entry %1% has parent %2% which is not a folder, ignored",
file.Title(), p->Name() ) ;
file.Title(), p->Name(), log::info ) ;
else
m_state.FromRemote( file ) ;

View File

@ -24,6 +24,7 @@
#include "http/StringResponse.hh"
#include "http/XmlResponse.hh"
#include "protocol/Json.hh"
#include "util/CArray.hh"
#include "util/Crypt.hh"
#include "util/Log.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 ( remote.MD5() == m_entry.MD5() )
{
Log( "MD5 matches: %1% is already in sync", Name(), log::verbose ) ;
m_state = sync ;
}
// use mtime to check which one is more recent
else
{
assert( m_state == local_new || m_state == local_changed || m_state == local_deleted ) ;
m_state = ( remote.MTime() > m_entry.MTime() ? remote_changed : m_state ) ;
Log( "%1% state is %2%", Name(), m_state, log::verbose ) ;
}
m_entry = remote ;
@ -111,18 +115,30 @@ void Resource::FromLocal()
{
fs::path path = Path() ;
if ( !fs::exists( path ) )
{
m_state = local_deleted ;
Log( "%1% in state but not exist on disk: %2%", Name(), m_state ) ;
}
// 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 ) )
{
m_state = local_new ;
Log( "%1% mtime newer on disk but unchanged: %2%", Name(), m_state ) ;
}
else
{
m_state = local_changed ;
Log( "%1% changed on disk: %2%", Name(), m_state ) ;
}
}
else
m_state = local_changed ;
{
m_state = local_new ;
Log( "%1% unchanged on disk: %2%", Name(), m_state ) ;
}
}
std::string Resource::SelfHref() const
@ -214,25 +230,30 @@ void Resource::Sync( http::Agent *http, const http::Headers& auth )
switch ( m_state )
{
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 ;
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 ) )
m_state = sync ;
break ;
case remote_new :
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 ) ;
m_state = sync ;
break ;
case sync :
Trace( "file %1% already in sync", m_entry.Filename() ) ;
Log( "sync %1% already in sync", m_entry.Filename(), log::verbose ) ;
break ;
default :
break ;
}
@ -356,6 +377,16 @@ std::size_t Resource::size() const
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
namespace std

View File

@ -108,12 +108,14 @@ private :
/// Resource exists in both local & remote, but remote is newer.
remote_changed
} ;
friend std::ostream& operator<<( std::ostream& os, State s ) ;
private :
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, std::streambuf *file, const http::Headers& auth ) ;
private :
Entry m_entry ;

View File

@ -74,9 +74,12 @@ void State::FromLocal( const fs::path& p, gr::Resource* folder )
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 ) ;
if ( c == 0 )
{
Log( "detected new file %1% in local", fname, log::verbose ) ;
c = new Resource( i->path() ) ;
folder->AddChild( c ) ;
m_res.Insert( c ) ;

View File

@ -19,22 +19,30 @@
#include "Crypt.hh"
#include "StdioFile.hh"
#include <iomanip>
#include <sstream>
#include <fstream>
// dependent libraries
#include <openssl/evp.h>
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 ) ;
return MD5( ifile.rdbuf() ) ;
try
{
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] ;
EVP_MD_CTX md ;
@ -42,7 +50,7 @@ std::string MD5( std::streambuf *file )
EVP_DigestInit_ex( &md, EVP_md5(), 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 ) ;
}

View File

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

View File

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

View File

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

View File

@ -32,9 +32,29 @@
namespace gr {
StdioFile::StdioFile( const std::string& filename, const char *mode ) :
m_file( std::fopen( filename.c_str(), mode ) )
StdioFile::StdioFile( const std::string& filename, const char *mode ) : m_file( 0 )
{
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 )
{
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 ) ;
std::fclose( m_file ) ;
Open( path.string(), mode ) ;
}
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 )

View File

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