From c7c49b094ae62964146b750d9fcb891e9fd1536d Mon Sep 17 00:00:00 2001 From: Matchman Green Date: Mon, 21 May 2012 00:10:29 +0800 Subject: [PATCH] fixed upload --- libgrive/src/drive/Entry.cc | 16 ++++++++ libgrive/src/drive/Entry.hh | 3 ++ libgrive/src/drive/Resource.cc | 69 ++++++++++++++++---------------- libgrive/src/drive/Resource.hh | 1 - libgrive/src/http/Agent.cc | 10 ++--- libgrive/src/http/Error.hh | 3 ++ libgrive/src/http/XmlResponse.cc | 1 + 7 files changed, 62 insertions(+), 41 deletions(-) diff --git a/libgrive/src/drive/Entry.cc b/libgrive/src/drive/Entry.cc index d5fe5f9..bd0ca5d 100644 --- a/libgrive/src/drive/Entry.cc +++ b/libgrive/src/drive/Entry.cc @@ -103,6 +103,22 @@ const std::vector& Entry::ParentHrefs() const return m_parent_hrefs ; } +/// only assign the key members +void Entry::AssignID( const Entry& entry ) +{ + m_self_href = entry.m_self_href ; + m_resource_id = entry.m_resource_id ; + m_parent_hrefs = entry.m_parent_hrefs ; + m_upload_link = entry.m_upload_link ; + m_etag = entry.m_etag ; +} + +void Entry::Update( const std::string& md5, const DateTime& mtime ) +{ + m_mtime = mtime ; + m_md5 = md5 ; +} + std::string Entry::Title() const { return m_title ; diff --git a/libgrive/src/drive/Entry.hh b/libgrive/src/drive/Entry.hh index d4f508e..0119fe8 100644 --- a/libgrive/src/drive/Entry.hh +++ b/libgrive/src/drive/Entry.hh @@ -54,6 +54,8 @@ public : const DateTime& mtime, const std::string& parent_href ) ; + void AssignID( const Entry& entry ) ; + std::string Title() const ; std::string Filename() const ; std::string Kind() const ; @@ -73,6 +75,7 @@ public : void Swap( Entry& e ) ; void Update( const xml::Node& entry ) ; + void Update( const std::string& md5, const DateTime& mtime ) ; private : std::string m_title ; diff --git a/libgrive/src/drive/Resource.cc b/libgrive/src/drive/Resource.cc index fdccc4b..1f5804d 100644 --- a/libgrive/src/drive/Resource.cc +++ b/libgrive/src/drive/Resource.cc @@ -28,11 +28,11 @@ #include "util/Crypt.hh" #include "util/Log.hh" #include "util/OS.hh" +#include "util/StdioFile.hh" #include "xml/Node.hh" #include "xml/NodeSet.hh" #include -#include // for debugging #include @@ -103,12 +103,14 @@ void Resource::FromRemote( const Entry& remote ) 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 ) ; + m_state = ( m_state == local_new ? local_changed : m_state ) ; + Log( "%1% state is %2%", Name(), m_state, log::verbose ) ; } - m_entry = remote ; + m_entry.AssignID( remote ) ; } void Resource::FromLocal() @@ -119,25 +121,19 @@ void Resource::FromLocal() 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 ( 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_new ; - Log( "%1% unchanged on disk: %2%", Name(), m_state ) ; + + // to save time, compare mtime before checksum + DateTime mtime = os::FileMTime( path ) ; + if ( mtime > m_entry.MTime() ) + { + Log( "%1% mtime newer on disk: %2%", Name(), m_state ) ; + m_entry.Update( crypt::MD5( path ), mtime ) ; + } + else + Log( "%1% unchanged on disk: %2%", Name(), m_state ) ; } } @@ -279,12 +275,6 @@ void Resource::Download( http::Agent* http, const fs::path& file, const http::He } bool Resource::Upload( http::Agent* http, const http::Headers& auth ) -{ - std::ifstream ifile( Path().string().c_str(), std::ios::binary | std::ios::in ) ; - return Upload( http, ifile.rdbuf(), auth ) ; -} - -bool Resource::Upload( http::Agent* http, std::streambuf *file, const http::Headers& auth ) { // upload link missing means that file is read only if ( m_entry.UploadLink().empty() ) @@ -294,6 +284,7 @@ bool Resource::Upload( http::Agent* http, std::streambuf *file, const http::Head } Log( "Uploading %1%", m_entry.Title() ) ; +// std::ifstream ifile( Path().string().c_str(), std::ios::binary | std::ios::in ) ; std::string meta = "\n" @@ -303,10 +294,20 @@ bool Resource::Upload( http::Agent* http, std::streambuf *file, const http::Head "" + m_entry.Filename() + "" "" ; - std::string data( - (std::istreambuf_iterator(file)), - (std::istreambuf_iterator()) ) ; +// std::string data( +// (std::istreambuf_iterator(ifile)), +// (std::istreambuf_iterator()) ) ; + StdioFile file( Path(), "rb" ) ; + std::string data ; + char buf[4096] ; + std::size_t count = 0 ; + while ( (count = file.Read( buf, sizeof(buf) )) > 0 ) + data.append( buf, count ) ; + +Trace( "%1% bytes: \"%2%\"", data.size(), data ) ; +Trace( "etag \"%1%\"", m_entry.ETag() ) ; + std::ostringstream xcontent_len ; xcontent_len << "X-Upload-Content-Length: " << data.size() ; @@ -320,18 +321,16 @@ bool Resource::Upload( http::Agent* http, std::streambuf *file, const http::Head http::StringResponse str ; http->Put( m_entry.UploadLink(), meta, &str, hdr ) ; - std::string uplink = http->RedirLocation() ; - - // parse the header and find "Location" http::Headers uphdr ; uphdr.push_back( "Expect:" ) ; uphdr.push_back( "Accept:" ) ; - - http::XmlResponse xml ; - http->Put( uplink, data, &xml, uphdr ) ; +// uphdr.push_back( "If-Match: " + m_entry.ETag() ) ; - Trace( "Receipted response = %1%", xml.Response() ) ; + // the content upload URL is in the "Location" HTTP header + std::string uplink = http->RedirLocation() ; + http::XmlResponse xml ; + http->Put( uplink, data, &xml, uphdr ) ; m_entry.Update( xml.Response() ) ; return true ; diff --git a/libgrive/src/drive/Resource.hh b/libgrive/src/drive/Resource.hh index bab7df0..e69b18c 100644 --- a/libgrive/src/drive/Resource.hh +++ b/libgrive/src/drive/Resource.hh @@ -114,7 +114,6 @@ private : 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 ; diff --git a/libgrive/src/http/Agent.cc b/libgrive/src/http/Agent.cc index dc94e51..33dbfc6 100644 --- a/libgrive/src/http/Agent.cc +++ b/libgrive/src/http/Agent.cc @@ -72,8 +72,6 @@ struct Agent::Impl { CURL *curl ; std::string location ; - char error[CURL_ERROR_SIZE] ; - std::string log_prefix ; } ; @@ -85,7 +83,6 @@ Agent::Agent() : ::curl_easy_setopt( m_pimpl->curl, CURLOPT_SSL_VERIFYHOST, 0L ) ; ::curl_easy_setopt( m_pimpl->curl, CURLOPT_HEADERFUNCTION, &Agent::HeaderCallback ) ; ::curl_easy_setopt( m_pimpl->curl, CURLOPT_WRITEHEADER , this ) ; - ::curl_easy_setopt( m_pimpl->curl, CURLOPT_ERRORBUFFER, m_pimpl->error ) ; ::curl_easy_setopt( m_pimpl->curl, CURLOPT_HEADER, 0L ) ; } @@ -127,9 +124,12 @@ long Agent::ExecCurl( { CURL *curl = m_pimpl->curl ; assert( curl != 0 ) ; + + char error[CURL_ERROR_SIZE] ; + ::curl_easy_setopt( m_pimpl->curl, CURLOPT_ERRORBUFFER, error ) ; SetHeader( hdr ) ; - + dest->Clear() ; CURLcode curl_code = ::curl_easy_perform(curl); @@ -143,7 +143,7 @@ long Agent::ExecCurl( throw Error() << CurlCode( curl_code ) << HttpResponse( http_code ) - << expt::ErrMsg( m_pimpl->error ) ; + << expt::ErrMsg( error ) ; } return http_code ; diff --git a/libgrive/src/http/Error.hh b/libgrive/src/http/Error.hh index f6ed2d7..10dadbe 100644 --- a/libgrive/src/http/Error.hh +++ b/libgrive/src/http/Error.hh @@ -31,4 +31,7 @@ typedef boost::error_info CurlCode ; // HTTP response code typedef boost::error_info HttpResponse ; +// HTTP response code +typedef boost::error_info HttpResponseText ; + } } // end of namespace diff --git a/libgrive/src/http/XmlResponse.cc b/libgrive/src/http/XmlResponse.cc index 49395f1..586a916 100644 --- a/libgrive/src/http/XmlResponse.cc +++ b/libgrive/src/http/XmlResponse.cc @@ -19,6 +19,7 @@ #include "XmlResponse.hh" +#include "util/Log.hh" #include "xml/Node.hh" #include "xml/TreeBuilder.hh"