sftp: Seek to the correct position to resume, fix slow start of transfer

pull/384/head
Tatsuhiro Tsujikawa 2015-05-12 22:31:14 +09:00
parent 89c1916fa5
commit 5723f4211a
8 changed files with 47 additions and 8 deletions

View File

@ -91,8 +91,10 @@ bool InitiateConnectionCommand::executeInternal() {
return false; return false;
} }
try { try {
getDownloadEngine()->addCommand(createNextCommand(hostname, ipaddr, port, auto c = createNextCommand(hostname, ipaddr, port, addrs, proxyRequest);
addrs, proxyRequest)); c->setStatus(Command::STATUS_ONESHOT_REALTIME);
getDownloadEngine()->setNoWait(true);
getDownloadEngine()->addCommand(std::move(c));
return true; return true;
} catch(RecoverableException& ex) { } catch(RecoverableException& ex) {
// Catch exception and retry another address. // Catch exception and retry another address.

View File

@ -227,6 +227,11 @@ int SSHSession::sftpStat(int64_t& totalLength, time_t& mtime)
return SSH_ERR_OK; return SSH_ERR_OK;
} }
void SSHSession::sftpSeek(int64_t pos)
{
libssh2_sftp_seek64(sftph_, pos);
}
std::string SSHSession::getLastErrorString() std::string SSHSession::getLastErrorString()
{ {
if (!ssh2_) { if (!ssh2_) {

View File

@ -122,6 +122,9 @@ public:
// blocks, or SSH_ERR_ERROR. // blocks, or SSH_ERR_ERROR.
int sftpStat(int64_t& totalLength, time_t& mtime); int sftpStat(int64_t& totalLength, time_t& mtime);
// Moves file postion to |pos|.
void sftpSeek(int64_t pos);
// Returns last error string // Returns last error string
std::string getLastErrorString(); std::string getLastErrorString();

View File

@ -84,7 +84,14 @@ bool SftpDownloadCommand::prepareForNextSegment()
return true; return true;
} }
return DownloadCommand::prepareForNextSegment(); auto rv = DownloadCommand::prepareForNextSegment();
if (rv) {
return true;
}
// sftp may not get incoming data. Enable write check to make this
// command invoke.
setWriteCheckSocket(getSocket());
return false;
} }
int64_t SftpDownloadCommand::getRequestEndOffset() const int64_t SftpDownloadCommand::getRequestEndOffset() const

View File

@ -81,7 +81,6 @@ SftpNegotiationCommand::SftpNegotiationCommand
{ {
path_ = getPath(); path_ = getPath();
disableReadCheckSocket();
setWriteCheckSocket(getSocket()); setWriteCheckSocket(getSocket());
} }
@ -108,7 +107,7 @@ bool SftpNegotiationCommand::executeInternal() {
getCuid())); getCuid()));
sequence_ = SEQ_SFTP_OPEN; sequence_ = SEQ_SFTP_OPEN;
break; break;
case SEQ_SFTP_OPEN: { case SEQ_SFTP_OPEN:
if (!getSocket()->sshSFTPOpen(path_)) { if (!getSocket()->sshSFTPOpen(path_)) {
goto again; goto again;
} }
@ -116,7 +115,6 @@ bool SftpNegotiationCommand::executeInternal() {
path_.c_str())); path_.c_str()));
sequence_ = SEQ_SFTP_STAT; sequence_ = SEQ_SFTP_STAT;
break; break;
}
case SEQ_SFTP_STAT: { case SEQ_SFTP_STAT: {
int64_t totalLength; int64_t totalLength;
time_t mtime; time_t mtime;
@ -134,12 +132,26 @@ bool SftpNegotiationCommand::executeInternal() {
} else { } else {
getRequestGroup()->validateTotalLength(getFileEntry()->getLength(), getRequestGroup()->validateTotalLength(getFileEntry()->getLength(),
totalLength); totalLength);
sequence_ = SEQ_NEGOTIATION_COMPLETED; sequence_ = SEQ_SFTP_SEEK;
} }
break; break;
} }
case SEQ_FILE_PREPARATION: case SEQ_SFTP_SEEK: {
sequence_ = SEQ_NEGOTIATION_COMPLETED; sequence_ = SEQ_NEGOTIATION_COMPLETED;
if (getSegments().empty()) {
break;
}
auto& segment = getSegments().front();
A2_LOG_INFO(fmt("CUID#%" PRId64 " - SFTP seek to %" PRId64,
getCuid(), segment->getPositionToWrite()));
getSocket()->sshSFTPSeek(segment->getPositionToWrite());
break;
}
case SEQ_FILE_PREPARATION:
sequence_ = SEQ_SFTP_SEEK;
disableReadCheckSocket(); disableReadCheckSocket();
disableWriteCheckSocket(); disableWriteCheckSocket();
return false; return false;

View File

@ -49,6 +49,7 @@ public:
SEQ_AUTH_PASSWORD, SEQ_AUTH_PASSWORD,
SEQ_SFTP_OPEN, SEQ_SFTP_OPEN,
SEQ_SFTP_STAT, SEQ_SFTP_STAT,
SEQ_SFTP_SEEK,
SEQ_NEGOTIATION_COMPLETED, SEQ_NEGOTIATION_COMPLETED,
SEQ_DOWNLOAD_ALREADY_COMPLETED, SEQ_DOWNLOAD_ALREADY_COMPLETED,
SEQ_HEAD_OK, SEQ_HEAD_OK,

View File

@ -1090,6 +1090,13 @@ bool SocketCore::sshSFTPStat(int64_t& totalLength, time_t& mtime,
return true; return true;
} }
void SocketCore::sshSFTPSeek(int64_t pos)
{
assert(sshSession_);
sshSession_->sftpSeek(pos);
}
bool SocketCore::sshGracefulShutdown() bool SocketCore::sshGracefulShutdown()
{ {
assert(sshSession_); assert(sshSession_);

View File

@ -313,6 +313,8 @@ public:
// opened. |path| is used for logging. // opened. |path| is used for logging.
bool sshSFTPStat(int64_t& totalLength, time_t& mtime, bool sshSFTPStat(int64_t& totalLength, time_t& mtime,
const std::string& path); const std::string& path);
// Seeks file position to |pos|.
void sshSFTPSeek(int64_t pos);
bool sshGracefulShutdown(); bool sshGracefulShutdown();
#endif // HAVE_LIBSSH2 #endif // HAVE_LIBSSH2