From cbf564fd94573945b49caa5a89d4d989ce3ba80c Mon Sep 17 00:00:00 2001
From: srsdanny <seres.dani@gmail.com>
Date: Mon, 29 Feb 2016 19:10:12 +0100
Subject: [PATCH] keepalive upload working

---
 program/Source/cloud/CloudAccessLayer.cpp    | 37 +++++----
 program/Source/cloud/CloudAdapter.cpp        |  5 ++
 program/Source/cloud/CloudAdapter.h          | 10 ++-
 program/Source/cloud/DropboxAdapter.cpp      | 66 ++++++++--------
 program/Source/cloud/DropboxAdapter.h        |  6 +-
 program/Source/cloud/ExampleCloudAdapter.cpp |  7 +-
 program/Source/cloud/ExampleCloudAdapter.h   |  6 +-
 program/Source/cloud/FTPAdapter.cpp          | 83 +++++++++++---------
 program/Source/cloud/FTPAdapter.h            |  6 +-
 program/Source/cloud/LocalCloudAdapter.cpp   | 41 +++++-----
 program/Source/cloud/LocalCloudAdapter.h     |  6 +-
 program/Source/cloud/OneDriveAdapter.cpp     | 58 ++++++++------
 program/Source/cloud/OneDriveAdapter.h       |  6 +-
 13 files changed, 186 insertions(+), 151 deletions(-)

diff --git a/program/Source/cloud/CloudAccessLayer.cpp b/program/Source/cloud/CloudAccessLayer.cpp
index 2ccc7dc7..74e59e5d 100644
--- a/program/Source/cloud/CloudAccessLayer.cpp
+++ b/program/Source/cloud/CloudAccessLayer.cpp
@@ -2,6 +2,10 @@
 #include "../logger/Logger.h"
 #include "../app/Application.h"
 #include "CloudException.h"
+#include "Poco/RunnableAdapter.h"
+#include "Poco/Thread.h"
+#include <map>
+#include <vector>
 
 using namespace std;
 
@@ -23,26 +27,31 @@ bool CloudAccessLayer::upload(const FileDescriptor& fileDescriptor) const
 		cerr << "Nincs fragment a file-ban" << endl;
 		return false;
 	}
-	
-	/*try {
-		
-		if (fragments.size() == 0){
-			throw CloudException("Nincs fragment a file-ban");
-		}
-	}
-	catch (CloudException fx) {
-		cerr << fx.what() << endl;
-		return false;
-	}*/
 
-	bool succesful = true;
+	/*bool success = true;
 	for (Fragment f : fragments)
 	{
 		if (!app.cm.getCloudAdapter(f.getCloudId())->upload(f)){
-			succesful = false;
+			success = false;
 		}
+	}*/
+
+	bool success = true;
+	map<string, vector<CloudFile>> cidFragMap;
+
+	for (auto& f : fragments)
+	{
+		cidFragMap[f.getCloudId()].push_back(f);
 	}
-	return succesful;
+
+	for (auto& i : cidFragMap)
+	{
+		if (!app.cm.getCloudAdapter(i.first)->upload(i.second)){
+			success = false;
+		}
+	}
+
+	return success;
 }
 
 bool CloudAccessLayer::upload(fileModel::LockFile lockFile) {
diff --git a/program/Source/cloud/CloudAdapter.cpp b/program/Source/cloud/CloudAdapter.cpp
index d61d48b4..12e60533 100644
--- a/program/Source/cloud/CloudAdapter.cpp
+++ b/program/Source/cloud/CloudAdapter.cpp
@@ -11,3 +11,8 @@ CloudAdapter::CloudAdapter(string _cloudID){
 	LOG_ENTER_EXIT;
 	cloudID = _cloudID;
 }
+
+bool CloudAdapter::upload(CloudFile cloudFile)
+{
+	return upload(vector<CloudFile>{cloudFile});
+}
diff --git a/program/Source/cloud/CloudAdapter.h b/program/Source/cloud/CloudAdapter.h
index 54ae9c46..9368cc39 100644
--- a/program/Source/cloud/CloudAdapter.h
+++ b/program/Source/cloud/CloudAdapter.h
@@ -4,6 +4,7 @@
 #include "../fileModel/CloudFile.h"
 #include "../fileModel/Fragment.h"
 #include <memory>
+#include <vector>
 
 /**
  * CloudAdapter class
@@ -41,7 +42,14 @@ public:
 	 * @param cloudFile file to upload
 	 * @return successful
 	 */
-	virtual bool upload(CloudFile cloudFile) = 0;
+	virtual bool upload(CloudFile cloudFile);
+
+	/**
+	* Uploads multiple files to the cloud
+	* @param cloudFiles files to upload
+	* @return successful
+	*/
+	virtual bool upload(std::vector<CloudFile> cloudFileList) = 0;
 	
 	/**
 	 * Downloads a file from the cloud
diff --git a/program/Source/cloud/DropboxAdapter.cpp b/program/Source/cloud/DropboxAdapter.cpp
index cc881f20..a8627a43 100644
--- a/program/Source/cloud/DropboxAdapter.cpp
+++ b/program/Source/cloud/DropboxAdapter.cpp
@@ -22,56 +22,52 @@ using namespace std;
 
 DropboxAdapter::DropboxAdapter(string _cloudID) : RestAdapter(_cloudID) { LOG_ENTER_EXIT; }
 
-bool DropboxAdapter::upload(CloudFile cloudFile) {
+bool DropboxAdapter::upload(vector<CloudFile> cloudFileList) {
 	LOG_ENTER_EXIT;
 
 	auto context = getContext();
 
-	// Get file
-	auto localFile(fragFolder + cloudFile.getCloudFileID());
-	ifstream in(localFile, ios::in | ios::ate | ios::binary);
-
-	if (!in.good()) 
-		return false; // If file can't be opened
-
-	// Get file size
-	streampos begin, end;
-	end = in.tellg();
-	in.seekg(0, ios::beg);
-	begin = in.tellg();
-	auto fileSize = end - begin;
-
 	// Prepare for upload
-	auto requestPath(uploadApiPath + cloudFile.getCloudFileID());
 	HTTPSClientSession session(contentHost, HTTPSClientSession::HTTPS_PORT, context);
-	HTTPRequest request(HTTPRequest::HTTP_PUT, requestPath, HTTPMessage::HTTP_1_1);
+	HTTPRequest request(HTTPRequest::HTTP_PUT, "", HTTPMessage::HTTP_1_1);
 	HTTPResponse response;
 	signHeader(request);
-	request.setContentLength(fileSize);
+	request.setKeepAlive(true);
 
-	// Do upload
-	try
+	for (auto& cloudFile : cloudFileList)
 	{
-		auto& rs = session.sendRequest(request);
+		auto localFile(fragFolder + cloudFile.getCloudFileID());
+		ifstream in(localFile, ios::binary);
 
-		StreamCopier::copyStream(in, rs);
+		if (!in)
+			return false; // If file can't be opened
 
-		auto& responseStream = session.receiveResponse(response);
-		if (response.getStatus() != HTTPResponse::HTTP_OK)
+		request.setContentLength(file_size(localFile));
+		request.setURI(uploadApiPath + cloudFile.getCloudFileID());
+
+		// Do upload
+		try
 		{
-			StreamCopier::copyStream(responseStream, cerr);
+			auto& rs = session.sendRequest(request);
+
+			StreamCopier::copyStream(in, rs);
+
+			auto& responseStream = session.receiveResponse(response);
+			if (response.getStatus() != HTTPResponse::HTTP_OK)
+			{
+				StreamCopier::copyStream(responseStream, cerr);
+				return false;
+			}
+		}
+		catch (Exception& e)
+		{
+			cerr << e.message() << endl;
 			return false;
 		}
+
+		in.close();
+		remove(localFile.c_str());
 	}
-	catch (Exception& e)
-	{
-		cerr << e.message() << endl;
-		return false;
-	}
-	
-	// delete local fragmant
-	in.close();
-	//remove(localFile.c_str());
 
 	return true;
 }
@@ -191,7 +187,7 @@ bool DropboxAdapter::auth() {
 	}
 
 	auto authResponse = responseVar.extract<JSON::Object::Ptr>();
-	ofstream("token.data", ios::out) << (authResponse->getValue<string>("access_token"));
+	ofstream("dropboxAdapter.token", ios::out) << (authResponse->getValue<string>("access_token"));
 
 	return true;
 }
diff --git a/program/Source/cloud/DropboxAdapter.h b/program/Source/cloud/DropboxAdapter.h
index 5ad3b2d0..47bcab4e 100644
--- a/program/Source/cloud/DropboxAdapter.h
+++ b/program/Source/cloud/DropboxAdapter.h
@@ -34,11 +34,11 @@ public:
 	explicit DropboxAdapter(std::string _cloudID = "dropboxAdapter");
 
 	/**
-	* Uploads a file to the cloud
-	* @param cloudFile file to upload
+	* Uploads multiple files to the cloud
+	* @param cloudFiles files to upload
 	* @return successful
 	*/
-	bool upload(CloudFile cloudFile) override;
+	bool upload(std::vector<CloudFile> cloudFileList) override;
 
 	/**
 	* Downloads a file from the cloud
diff --git a/program/Source/cloud/ExampleCloudAdapter.cpp b/program/Source/cloud/ExampleCloudAdapter.cpp
index 3e64722a..b999609c 100644
--- a/program/Source/cloud/ExampleCloudAdapter.cpp
+++ b/program/Source/cloud/ExampleCloudAdapter.cpp
@@ -9,9 +9,12 @@ using namespace std;
 
 ExampleCloudAdapter::ExampleCloudAdapter(string _cloudID) : CloudAdapter(_cloudID) { LOG_ENTER_EXIT; }
 
-bool ExampleCloudAdapter::upload(CloudFile cloudFile) {
+bool ExampleCloudAdapter::upload(vector<CloudFile> cloudFileList) {
 	LOG_ENTER_EXIT;
-	cout << "Example upload technique" << endl;
+	for (auto& cloudFile : cloudFileList)
+	{
+		cout << "Example upload technique" << endl;
+	}
 	return true;
 }
 
diff --git a/program/Source/cloud/ExampleCloudAdapter.h b/program/Source/cloud/ExampleCloudAdapter.h
index 1d1cf4a5..feae4299 100644
--- a/program/Source/cloud/ExampleCloudAdapter.h
+++ b/program/Source/cloud/ExampleCloudAdapter.h
@@ -17,11 +17,11 @@ public:
 	ExampleCloudAdapter(std::string _cloudID);
 
 	/**
-	* Uploads a file to the cloud
-	* @param cloudFile file to upload
+	* Uploads multiple files to the cloud
+	* @param cloudFiles files to upload
 	* @return successful
 	*/
-	bool upload(CloudFile cloudFile);
+	bool upload(std::vector<CloudFile> cloudFileList) override;
 
 	/**
 	* Downloads a file from the cloud
diff --git a/program/Source/cloud/FTPAdapter.cpp b/program/Source/cloud/FTPAdapter.cpp
index af6796d4..d1e51812 100644
--- a/program/Source/cloud/FTPAdapter.cpp
+++ b/program/Source/cloud/FTPAdapter.cpp
@@ -22,63 +22,68 @@ const string FTPAdapter::ROOT = "htdocs/";
 
 FTPAdapter::FTPAdapter(string _cloudID) : CloudAdapter(_cloudID) { LOG_ENTER_EXIT; }
 
-bool FTPAdapter::upload(CloudFile cloudFile) {
+bool FTPAdapter::upload(vector<CloudFile> cloudFileList) {
 	LOG_ENTER_EXIT;
 
-	// Get file
-	auto localFile(fragFolder + cloudFile.getCloudFileID());
-	ifstream in(localFile, ios::in | ios::binary);
-
-	if (!in)
-		return false; // If file can't be opened
-
-	Path filePath(ROOT + cloudFile.getCloudFileID());
 	FTPClientSession session(HOST, FTPClientSession::FTP_PORT, USERNAME, PASSWORD);
+	session.setFileType(FTPClientSession::TYPE_BINARY);
 
-	try
+	for (auto& cloudFile : cloudFileList)
 	{
-		for (auto i = 0; i < filePath.depth(); i++)
+		try
 		{
-			string dirName(filePath.directory(i));
+			// Get file
+			auto localFile(fragFolder + cloudFile.getCloudFileID());
+			ifstream in(localFile, ios::in | ios::binary);
 
-			try
-			{
-				session.setWorkingDirectory(dirName);
-			}
-			catch (FTPException&)
+			if (!in)
+				return false; // If file can't be opened
+
+			Path filePath(ROOT + cloudFile.getCloudFileID());
+
+			session.setWorkingDirectory("/.");
+
+			for (auto i = 0; i < filePath.depth(); i++)
 			{
-				// Directory doesn't exist, try to create it
+				string dirName(filePath.directory(i));
+
 				try
 				{
-					session.createDirectory(dirName);
 					session.setWorkingDirectory(dirName);
 				}
-				catch (FTPException& ex)
+				catch (FTPException&)
 				{
-					// Error creating directory
-					cerr << ex.message() << endl;
-					return 1;
+					// Directory doesn't exist, try to create it
+					try
+					{
+						session.createDirectory(dirName);
+						session.setWorkingDirectory(dirName);
+					}
+					catch (FTPException& ex)
+					{
+						// Error creating directory
+						cerr << ex.message() << endl;
+						return 1;
+					}
 				}
 			}
-		}
-
-		session.setFileType(FTPClientSession::TYPE_BINARY);
-		auto& os = session.beginUpload(filePath.getFileName());
-		StreamCopier::copyStream(in, os);
-		session.endUpload();
 
-		// delete local fragmant
-		in.close();
-		remove(localFile.c_str());
+			auto& os = session.beginUpload(filePath.getFileName());
+			StreamCopier::copyStream(in, os);
+			session.endUpload();
 
-
-		return true;
-	}
-	catch (FTPException& e)
-	{
-		cerr << "error: " << e.message() << endl;
-		return false;
+			// delete local fragmant
+			in.close();
+			remove(localFile.c_str());
+		}
+		catch (FTPException& e)
+		{
+			cerr << "error: " << e.message() << endl;
+			return false; // Unexpected error, return
+		}
 	}
+
+	return true;
 }
 
 shared_ptr<Fragment> FTPAdapter::download(CloudFile cloudFile) {
diff --git a/program/Source/cloud/FTPAdapter.h b/program/Source/cloud/FTPAdapter.h
index cb1d9abb..ac0161fd 100644
--- a/program/Source/cloud/FTPAdapter.h
+++ b/program/Source/cloud/FTPAdapter.h
@@ -19,11 +19,11 @@ public:
 	explicit FTPAdapter(std::string _cloudID = "FTPAdapter");
 
 	/**
-	* Uploads a file to the cloud
-	* @param cloudFile file to upload
+	* Uploads multiple files to the cloud
+	* @param cloudFiles files to upload
 	* @return successful
 	*/
-	bool upload(CloudFile cloudFile) override;
+	bool upload(std::vector<CloudFile> cloudFileList) override;
 
 	/**
 	* Downloads a file from the cloud
diff --git a/program/Source/cloud/LocalCloudAdapter.cpp b/program/Source/cloud/LocalCloudAdapter.cpp
index 8b1a73bf..e4e6a2d2 100644
--- a/program/Source/cloud/LocalCloudAdapter.cpp
+++ b/program/Source/cloud/LocalCloudAdapter.cpp
@@ -13,30 +13,33 @@ using namespace boost::filesystem;
 
 LocalCloudAdapter::LocalCloudAdapter(string _cloudID) : CloudAdapter(_cloudID) { LOG_ENTER_EXIT; }
 
-bool LocalCloudAdapter::upload(CloudFile cloudFile) {
+bool LocalCloudAdapter::upload(vector<CloudFile> cloudFileList) {
 	LOG_ENTER_EXIT;
 
-	path cloudLocation = cloudFolder + cloudFile.getCloudFileID();
-	path cloudParentDir = cloudLocation.parent_path();
-
-	if (!exists(cloudParentDir))
+	for (auto& cloudFile : cloudFileList)
 	{
-		create_directories(cloudParentDir);
+		path cloudLocation = cloudFolder + cloudFile.getCloudFileID();
+		path cloudParentDir = cloudLocation.parent_path();
+
+		if (!exists(cloudParentDir))
+		{
+			create_directories(cloudParentDir);
+		}
+
+		//upload file
+		ifstream src(fragFolder + cloudFile.getCloudFileID(), std::ios::binary);
+		ofstream dst(cloudFolder + cloudFile.getCloudFileID(), std::ios::binary);
+		dst << src.rdbuf();
+
+		src.close();
+		dst.close();
+
+		//delete temp
+		string spath = fragFolder + cloudFile.getCloudFileID();
+		const char* path = spath.c_str();
+		int res = remove(path);
 	}
 
-	//upload file
-	ifstream src(fragFolder + cloudFile.getCloudFileID(), std::ios::binary);
-	ofstream dst(cloudFolder + cloudFile.getCloudFileID(), std::ios::binary);
-	dst << src.rdbuf();
-
-	src.close();
-	dst.close();
-
-	//delete temp
-	string spath = fragFolder + cloudFile.getCloudFileID();
-	const char* path = spath.c_str();
-	int res = remove(path);
-
 	return true;
 }
 
diff --git a/program/Source/cloud/LocalCloudAdapter.h b/program/Source/cloud/LocalCloudAdapter.h
index 97d20c21..f596f01c 100644
--- a/program/Source/cloud/LocalCloudAdapter.h
+++ b/program/Source/cloud/LocalCloudAdapter.h
@@ -17,11 +17,11 @@ public:
 	LocalCloudAdapter(std::string _cloudID = "localAdapter");
 
 	/**
-	* Uploads a file to the cloud
-	* @param cloudFile file to upload
+	* Uploads multiple files to the cloud
+	* @param cloudFiles files to upload
 	* @return successful
 	*/
-	bool upload(CloudFile cloudFile);
+	bool upload(std::vector<CloudFile> cloudFileList) override;
 
 	/**
 	* Downloads a file from the cloud
diff --git a/program/Source/cloud/OneDriveAdapter.cpp b/program/Source/cloud/OneDriveAdapter.cpp
index b157ecc2..132b6dcf 100644
--- a/program/Source/cloud/OneDriveAdapter.cpp
+++ b/program/Source/cloud/OneDriveAdapter.cpp
@@ -30,49 +30,55 @@ OneDriveAdapter::OneDriveAdapter(string _cloudID) : RestAdapter(_cloudID)
 	HTTPSStreamFactory::registerFactory();
 }
 
-bool OneDriveAdapter::upload(CloudFile cloudFile) {
+bool OneDriveAdapter::upload(vector<CloudFile> cloudFileList) {
 	LOG_ENTER_EXIT;
 
 	auto context = getContext();
 
-	// Get file
-	auto localFile(fragFolder + cloudFile.getCloudFileID());
-
-	if (!exists(localFile))
-		return false; // If file can't be opened
-
 	// Prepare for upload
-	auto requestPath(appRoot + cloudFile.getCloudFileID() + content);
 	HTTPSClientSession session(apiHost, HTTPSClientSession::HTTPS_PORT, context);
-	HTTPRequest request(HTTPRequest::HTTP_PUT, requestPath, HTTPMessage::HTTP_1_1);
+	HTTPRequest request(HTTPRequest::HTTP_PUT, "", HTTPMessage::HTTP_1_1);
 	HTTPResponse response;
 	signHeader(request);
-	request.setContentLength(file_size(localFile));
 
-	// Do upload
-	try
+	for (auto& cloudFile : cloudFileList)
 	{
-		ifstream in(localFile, ios::binary);
-		auto& rs = session.sendRequest(request);
+		// Get file
+		auto localFile(fragFolder + cloudFile.getCloudFileID());
+
+		if (!exists(localFile))
+			return false; // If file can't be opened
 
-		StreamCopier::copyStream(in, rs);
+		request.setContentLength(file_size(localFile));
+		request.setURI(appRoot + cloudFile.getCloudFileID() + content);
 
-		auto& responseStream = session.receiveResponse(response);
-		if (response.getStatus() != HTTPResponse::HTTP_CREATED &&
-			response.getStatus() != HTTPResponse::HTTP_OK)
+		// Do upload
+		try
 		{
-			StreamCopier::copyStream(responseStream, cerr);
+			ifstream in(localFile, ios::binary);
+			auto& rs = session.sendRequest(request);
+
+			StreamCopier::copyStream(in, rs);
+
+			auto& responseStream = session.receiveResponse(response);
+			if (response.getStatus() != HTTPResponse::HTTP_CREATED &&
+				response.getStatus() != HTTPResponse::HTTP_OK)
+			{
+				StreamCopier::copyStream(responseStream, cerr);
+				return false;
+			}
+		}
+		catch (Exception& e)
+		{
+			cerr << e.message() << endl;
 			return false;
 		}
-	}
-	catch (Exception& e)
-	{
-		cerr << e.message() << endl;
-		return false;
+
+		// delete local fragmant
+		remove(localFile.c_str());
 	}
 
-	// delete local fragmant
-	//remove(localFile.c_str());
+	
 
 	return true;
 }
diff --git a/program/Source/cloud/OneDriveAdapter.h b/program/Source/cloud/OneDriveAdapter.h
index f91f0290..89918412 100644
--- a/program/Source/cloud/OneDriveAdapter.h
+++ b/program/Source/cloud/OneDriveAdapter.h
@@ -31,11 +31,11 @@ public:
 	explicit OneDriveAdapter(std::string _cloudID = "oneDriveAdapter");
 
 	/**
-	* Uploads a file to the cloud
-	* @param cloudFile file to upload
+	* Uploads multiple files to the cloud
+	* @param cloudFiles files to upload
 	* @return successful
 	*/
-	bool upload(CloudFile cloudFile) override;
+	bool upload(std::vector<CloudFile> cloudFileList) override;
 
 	/**
 	* Downloads a file from the cloud
-- 
GitLab