Skip to content

Commit a16cd7c

Browse files
sadyrovgouriano
authored andcommitted
Added upload/download streams and tests. JIRA CXX-13855
git-svn-id: https://anonsvn.ncbi.nlm.nih.gov/repos/v1/trunk/c++@104402 78c7ea69-d796-4a43-9a09-de51944f1b03
1 parent 11e0e94 commit a16cd7c

File tree

4 files changed

+142
-38
lines changed

4 files changed

+142
-38
lines changed

include/connect/ncbi_sftp.hpp

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,63 @@ class NCBI_XCONNSFTP_EXPORT CSFTP_Session
9292
class NCBI_XCONNSFTP_EXPORT CSFTP_Stream : public CRWStream
9393
{
9494
public:
95-
CSFTP_Stream(CSFTP_Session session,
96-
string_view path = {});
95+
CSFTP_Stream(const CSFTP_Session& session,
96+
string_view path = {}) :
97+
CSFTP_Stream(session, path, {}, 0, false)
98+
{
99+
}
100+
101+
protected:
102+
CSFTP_Stream(const CSFTP_Session& session, string_view path,
103+
string_view file, uint64_t offset, bool upload);
104+
};
105+
106+
107+
/// CSFTP_Stream specialization (ctors) for download
108+
///
109+
/// @sa CSFTP_Stream, CConn_FTPDownloadStream
110+
///
111+
class NCBI_XCONNSFTP_EXPORT CSFTP_DownloadStream : public CSFTP_Stream
112+
{
113+
public:
114+
CSFTP_DownloadStream(const CSFTP_Session& session,
115+
string_view file,
116+
string_view path = {}) :
117+
CSFTP_Stream(session, path, file, 0, false)
118+
{
119+
}
120+
121+
CSFTP_DownloadStream(const CSFTP_Session& session,
122+
string_view file,
123+
uint64_t offset,
124+
string_view path = {}) :
125+
CSFTP_Stream(session, path, file, offset, false)
126+
{
127+
}
128+
};
129+
130+
131+
/// CSFTP_Stream specialization (ctors) for upload
132+
///
133+
/// @sa CSFTP_Stream, CConn_FTPUploadStream
134+
///
135+
class NCBI_XCONNSFTP_EXPORT CSFTP_UploadStream : public CSFTP_Stream
136+
{
137+
public:
138+
CSFTP_UploadStream(const CSFTP_Session& session,
139+
string_view file,
140+
string_view path = {}) :
141+
CSFTP_Stream(session, path, file, 0, true)
142+
{
143+
}
144+
145+
CSFTP_UploadStream(const CSFTP_Session& session,
146+
string_view file,
147+
uint64_t offset,
148+
string_view path = {}) :
149+
CSFTP_Stream(session, path, file, offset, true)
150+
{
151+
}
97152
};
98153

99154

src/connect/ncbi_sftp.cpp

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,10 @@ ERW_Result SWrtrState::Write(const void* buf, size_t count, size_t* bytes_writte
164164
}
165165

166166

167-
SRWFsm::SRWFsm(shared_ptr<SSession> session, string_view start_path) :
167+
SRWFsm::SRWFsm(shared_ptr<SSession> session, string_view start_path, string_view file, uint64_t offset, bool upload) :
168168
m_Session(std::move(session)),
169-
m_CurrentPath("/")
169+
m_CurrentPath("/"),
170+
m_Offset(offset)
170171
{
171172
m_States.emplace("CWD"s, make_unique<SCwdState>(x_GetData(), start_path));
172173
m_States.emplace("NLST"s, make_unique<SNlstState>(x_GetData()));
@@ -175,16 +176,30 @@ SRWFsm::SRWFsm(shared_ptr<SSession> session, string_view start_path) :
175176
m_States.emplace("MLST"s, make_unique<SMlstState>(x_GetData()));
176177
m_States.emplace("PWD"s, make_unique<SPwdState>(x_GetData()));
177178
m_States.emplace("CDUP"s, make_unique<SCdupState>(x_GetData()));
178-
m_States.emplace("RETR"s, make_unique<SRetrState>(x_GetData()));
179179
m_States.emplace("SIZE"s, make_unique<SSizeState>(x_GetData()));
180180
m_States.emplace("REST"s, make_unique<SRestState>(x_GetData()));
181-
m_States.emplace("STOR"s, make_unique<SWrtrState>(x_GetData(), SWrtrState::eStor));
182181
m_States.emplace("APPE"s, make_unique<SWrtrState>(x_GetData(), SWrtrState::eAppe));
183182
m_States.emplace("MKD"s, make_unique<SMkdState>(x_GetData()));
184183
m_States.emplace("RMD"s, make_unique<SRmdState>(x_GetData()));
185184
m_States.emplace("DELE"s, make_unique<SDeleState>(x_GetData()));
186185
m_States.emplace("REN"s, make_unique<SRenState>(x_GetData()));
187186
m_States.emplace("MDTM"s, make_unique<SMdtmState>(x_GetData()));
187+
188+
auto retr = make_unique<SRetrState>(x_GetData());
189+
auto stor = make_unique<SWrtrState>(x_GetData(), SWrtrState::eStor);
190+
191+
if (!file.empty()) {
192+
if (upload) {
193+
stor->Reset(file);
194+
m_CurrentState = stor.get();
195+
} else {
196+
retr->Reset(file);
197+
m_CurrentState = retr.get();
198+
}
199+
}
200+
201+
m_States.emplace("RETR"s, std::move(retr));
202+
m_States.emplace("STOR"s, std::move(stor));
188203
}
189204

190205
ERW_Result SRWFsm::Read(void* buf, size_t count, size_t* bytes_read)
@@ -263,9 +278,11 @@ CSFTP_Session::CSFTP_Session(const string& host, const string& user, const strin
263278
}
264279

265280

266-
CSFTP_Stream::CSFTP_Stream(CSFTP_Session session,
267-
string_view path) :
268-
CRWStream(new NSftp::SRWFsm(static_pointer_cast<NSftp::SSession>(session.m_Impl), std::move(path)), 0, nullptr, CRWStreambuf::fOwnAll)
281+
CSFTP_Stream::CSFTP_Stream(const CSFTP_Session& session, string_view path,
282+
string_view file, uint64_t offset, bool upload) :
283+
CRWStream(
284+
new NSftp::SRWFsm(static_pointer_cast<NSftp::SSession>(session.m_Impl), path, file, offset, upload),
285+
0, nullptr, CRWStreambuf::fOwnAll)
269286
{
270287
}
271288

src/connect/ncbi_sftp_impl.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,7 @@ struct SRenState : SStringReplyState
915915

916916
struct SRWFsm : IState
917917
{
918-
SRWFsm(shared_ptr<SSession> session, string_view start_path);
918+
SRWFsm(shared_ptr<SSession> session, string_view start_path, string_view file, uint64_t offset, bool upload);
919919

920920
ERW_Result Read(void* buf, size_t count, size_t* bytes_read = 0) override;
921921
ERW_Result Write(const void* buf, size_t count, size_t* bytes_written = 0) override;
@@ -927,7 +927,7 @@ struct SRWFsm : IState
927927
map<string, unique_ptr<IState>, PNocase> m_States;
928928
IState* m_CurrentState = nullptr;
929929
TPath m_CurrentPath;
930-
uint64_t m_Offset = 0;
930+
uint64_t m_Offset;
931931
string m_Buffer;
932932
};
933933

src/connect/test/test_ncbi_sftp.cpp

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,25 @@ struct SGlobalFixture
9191

9292
static bool IsSFTP() { return type == SFTP; }
9393

94-
static unique_ptr<iostream> CreateStream(const string& path)
94+
static unique_ptr<iostream> CreateStream(const string& path, const string& file = {}, size_t offset = 0, bool upload = false)
9595
{
9696
if (auto sftp_session = get_if<SFTP>(&session)) {
97-
return make_unique<CSFTP_Stream>(*sftp_session, path);
97+
if (file.empty()) {
98+
return make_unique<CSFTP_Stream>(*sftp_session, path);
99+
} else if (upload) {
100+
return make_unique<CSFTP_UploadStream>(*sftp_session, file, offset, path);
101+
} else {
102+
return make_unique<CSFTP_DownloadStream>(*sftp_session, file, offset, path);
103+
}
98104

99105
} else if (auto cred = get_if<FTP>(&session)) {
100-
return make_unique<CConn_FtpStream>("ftp-private.ncbi.nlm.nih.gov", cred->first, cred->second, path);
106+
if (file.empty()) {
107+
return make_unique<CConn_FtpStream>("ftp-private.ncbi.nlm.nih.gov", cred->first, cred->second, path);
108+
} else if (upload) {
109+
return make_unique<CConn_FTPUploadStream>("ftp-private.ncbi.nlm.nih.gov", cred->first, cred->second, file, path, 0, 0, offset);
110+
} else {
111+
return make_unique<CConn_FTPDownloadStream>("ftp-private.ncbi.nlm.nih.gov", file, cred->first, cred->second, path, 0, 0, nullptr, offset);
112+
}
101113

102114
} else {
103115
BOOST_FAIL("Unknown stream type requested");
@@ -126,35 +138,49 @@ struct SDefaultDirFixture
126138
}
127139

128140
template <class... TArgs>
129-
void Test(string_view command, TArgs&&... args)
141+
void Test(iostream& s, string_view command, TArgs&&... args)
130142
{
131143
BOOST_TEST_INFO_SCOPE(command);
132-
stream << command << endl;
133-
x_Test(std::forward<TArgs>(args)...);
134-
stream.clear();
144+
s << command << endl;
145+
x_Test(s, std::forward<TArgs>(args)...);
146+
s.clear();
147+
}
148+
149+
template <class... TArgs>
150+
void Test(string_view command, TArgs&&... args)
151+
{
152+
Test(stream, command, std::forward<TArgs>(args)...);
153+
}
154+
155+
template <class... TArgs>
156+
void TestNoCommand(iostream& s, TArgs&&... args)
157+
{
158+
BOOST_TEST_INFO_SCOPE("No command");
159+
x_Test(s, std::forward<TArgs>(args)...);
160+
s.clear();
135161
}
136162

137163
private:
138-
void x_Test()
164+
void x_Test(iostream& s)
139165
{
140-
BOOST_CHECK(!getline(stream, line));
141-
BOOST_CHECK_EQUAL(stream.rdstate(), ios_base::failbit | ios_base::eofbit);
166+
BOOST_CHECK(!getline(s, line));
167+
BOOST_CHECK_EQUAL(s.rdstate(), ios_base::failbit | ios_base::eofbit);
142168
}
143169

144-
void x_Test(string_view expected)
170+
void x_Test(iostream& s, string_view expected)
145171
{
146172
BOOST_TEST_INFO_SCOPE("With expected=" << expected);
147-
BOOST_CHECK(getline(stream, line));
173+
BOOST_CHECK(getline(s, line));
148174
BOOST_CHECK_EQUAL(line, expected);
149-
BOOST_CHECK(!getline(stream, line));
150-
BOOST_CHECK_EQUAL(stream.rdstate(), ios_base::failbit | ios_base::eofbit);
175+
BOOST_CHECK(!getline(s, line));
176+
BOOST_CHECK_EQUAL(s.rdstate(), ios_base::failbit | ios_base::eofbit);
151177
}
152178

153-
void x_Test(set<string> expected)
179+
void x_Test(iostream& s, set<string> expected)
154180
{
155181
set<string> actual;
156182

157-
while (getline(stream, line)) {
183+
while (getline(s, line)) {
158184
if (line.back() == '\r') {
159185
line.replace(line.size() - 1, 1, "\\r"sv);
160186
}
@@ -163,20 +189,20 @@ struct SDefaultDirFixture
163189
}
164190

165191
BOOST_CHECK_EQUAL_COLLECTIONS(actual.begin(), actual.end(), expected.begin(), expected.end());
166-
BOOST_CHECK_EQUAL(stream.rdstate(), ios_base::failbit | ios_base::eofbit);
192+
BOOST_CHECK_EQUAL(s.rdstate(), ios_base::failbit | ios_base::eofbit);
167193
}
168194

169195
template <class TExpected>
170-
void x_Test(array<TExpected, 2> expected)
196+
void x_Test(iostream& s, array<TExpected, 2> expected)
171197
{
172-
x_Test(expected[SGlobalFixture::IsSFTP() ? 0 : 1]);
198+
x_Test(s, expected[SGlobalFixture::IsSFTP() ? 0 : 1]);
173199
}
174200

175-
void x_Test(string_view data, string_view expected)
201+
void x_Test(iostream& s, string_view data, string_view expected)
176202
{
177203
BOOST_TEST_INFO_SCOPE("With data=" << data);
178-
stream << data;
179-
x_Test(expected);
204+
s << data;
205+
x_Test(s, expected);
180206
}
181207
};
182208

@@ -229,9 +255,11 @@ BOOST_AUTO_TEST_CASE(FilesAndDirs)
229255
Test("RETR file1", "00000000000000000000");
230256
Test("STOR file1", "111111111", "9");
231257
Test("RETR file1", "111111111");
232-
Test("REST 4", "350");
233-
Test("STOR file1", "2222", "4");
234-
Test("RETR file1", "111122221");
258+
259+
auto stor = SGlobalFixture::CreateStream(default_path, "file1", 4, true);
260+
TestNoCommand(*stor, "2222", "4");
261+
Test(*stor, "RETR file1", "111122221");
262+
235263
Test("REST 8", "350");
236264
Test("STOR file1", "33", "2");
237265
Test("RETR file1", "1111222233");
@@ -243,8 +271,12 @@ BOOST_AUTO_TEST_CASE(FilesAndDirs)
243271
Test("RETR file2", "1111222233444");
244272
Test("APPE file2", "5", "1");
245273
Test("RETR file2", "11112222334445");
246-
Test("REST 5", "350");
247-
Test("APPE file2", "66", "2");
274+
275+
auto retr = SGlobalFixture::CreateStream(default_path, "file2", 8, false);
276+
TestNoCommand(*retr, "334445");
277+
Test(*retr, "REST 5", "350");
278+
Test(*retr, "APPE file2", "66", "2");
279+
248280
Test("RETR file2", "11112662334445");
249281
Test("REST 9", "350");
250282
Test("APPE file2", "77", "2");

0 commit comments

Comments
 (0)