From df9de38617a62ddc980f9030caecce7fd941ac92 Mon Sep 17 00:00:00 2001
From: afederici <ajf5@illinois.edu>
Date: Tue, 24 Nov 2020 16:33:57 -0600
Subject: [PATCH] added file merging

---
 Wc                 | Bin 191080 -> 191272 bytes
 inc/FileObject.h   |   2 +-
 inc/MessageTypes.h |   4 ++
 inc/Node.h         |   6 +-
 inc/TcpSocket.h    |   8 ++-
 mappers/wc.cpp     |   2 +-
 src/FileObject.cpp |   7 ++-
 src/Node.cpp       | 121 ++++++++++++++++++++++----------------
 src/TcpSocket.cpp  | 142 ++++++++++++++++++++++++++++++++++-----------
 src/TestBench.cpp  |   2 +-
 src/Threads.cpp    |  14 +++--
 src/Utils.cpp      |   2 +-
 src/main.cpp       |   2 +-
 13 files changed, 209 insertions(+), 103 deletions(-)

diff --git a/Wc b/Wc
index 3c1fead01a06843bfc0429b84a8b5916a3292d22..c7dcfbb588800efe9e9e4acf9f0bba8e307328d6 100755
GIT binary patch
delta 26935
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
b@9Nt9s+>;KbgPsazVpXTX><D1IsE?sM1&bW

delta 26759
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

diff --git a/inc/FileObject.h b/inc/FileObject.h
index ca0be72..cc4eb6e 100644
--- a/inc/FileObject.h
+++ b/inc/FileObject.h
@@ -16,7 +16,7 @@
 using namespace std;
 
 string getMostRecentFile(string readfile);
-void cleanupTmpFiles();
+void cleanupTmpFiles(string match);
 
 class FileObject {
 public:
diff --git a/inc/MessageTypes.h b/inc/MessageTypes.h
index e3deb01..63368e5 100644
--- a/inc/MessageTypes.h
+++ b/inc/MessageTypes.h
@@ -30,6 +30,10 @@ enum MessageType {
 	MAPLEACK,
 	CHUNK, //send to nodes so they have information about what kind of get request to send
 	CHUNKACK, //after append ack received, send this back to master to know when things are Done
+	MERGE,
+	STARTMERGE,
+	MERGECOMPLETE,
+	MERGEFAIL
 };
 
 enum PayloadType {
diff --git a/inc/Node.h b/inc/Node.h
index 7d8d123..b43e94b 100644
--- a/inc/Node.h
+++ b/inc/Node.h
@@ -5,13 +5,14 @@
 #include <string>
 #include <vector>
 #include <map>
+#include <set>
 #include <pthread.h>
 #include <time.h>
 #include <signal.h>
 #include <unistd.h>
 #include <dirent.h>
 #include <sys/types.h>
-
+#include <fstream>
 #include <stdio.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -83,7 +84,8 @@ public:
 	map<string, tuple<bool, bool, bool>> pendingRequestSent; //?
 
 	//master properties for MAPLEJUICE
-	map<string, vector<tuple<string, string, string>>> mapleProcessing; //ip -> [ (file, chunk_start, originIP) ]
+	map<string, vector<tuple<string, string>>> mapleProcessing; //ip -> [ (file, chunk_start) ]
+	map<string, set<tuple<string,string>>> workerTasks; //above is static, this removes tasks when done
 	map<string, tuple<long int, int>> fileSizes; //used so master can partition in the map phase tuple is (bytes, lines)
 	HashRing *mapleRing;
 	map<string, vector<tuple<string, string>>> mapleSending; //originIP -> (file, chunk_start);
diff --git a/inc/TcpSocket.h b/inc/TcpSocket.h
index 69c9a2b..076f8aa 100644
--- a/inc/TcpSocket.h
+++ b/inc/TcpSocket.h
@@ -51,15 +51,19 @@ public:
 	queue<string> regMessages;//other messages added here
 	queue<string> pendSendMessages;//keeps messages for the tcp client to send
 	queue<string> mapleMessages; //keeps track of sending
+	queue<string> mergeMessages; //keeps track of sending
 
 	void bindServer(string port);
-	void sendFile(string ip, string port, string localfilename, string sdfsfilename, string remoteLocalfilename, string overwrite);
+	void sendFile(string ip, string port, FILE * fp, int size);
+	void putFile(string ip, string port, string localfilename, string sdfsfilename, string remoteLocalfilename);
+	void putDirectory(string ip, string port); //put everything in tmp directory
 	void sendLines(string ip, string port, string execFile, string localFile, string prefix, int start, int end);
 	void sendMessage(string ip, string port, string message);
 	int messageHandler(int sockfd, string payloadMessage, string returnID);
 	int createConnection(string ip, string port);
 	TcpSocket();
 private:
-	string getFileMetadata(int size, string checksum, string sdfsfilename, string localfilename, string remoteLocalfilename, string overwrite);
+	string getFileMetadata(int size, string checksum, string sdfsfilename, string localfilename, string remoteLocalfilename);
+	string getDirMetadata();
 };
 #endif //TCPSOCKET_H
diff --git a/mappers/wc.cpp b/mappers/wc.cpp
index 6a8535e..e8b2d6e 100644
--- a/mappers/wc.cpp
+++ b/mappers/wc.cpp
@@ -9,7 +9,7 @@ int main(int argc, char **argv) {
     while (std::getline(file, str))
     {
         for (size_t i = 0; i < str.size(); i++) {
-            if (str[i] == '.' || str[i] == ',' || str[i] == '?' || str[i] == ';' || str[i] == '!') str[i] = ' ';
+            if (str[i] == '.' || str[i] == ',' || str[i] == '?' || str[i] == ';' || str[i] == '!' || str[i] == '-') str[i] = ' ';
         }
         std::transform(str.begin(), str.end(), str.begin(), ::tolower);
         std::vector<std::string> temp = splitString(str, delim);
diff --git a/src/FileObject.cpp b/src/FileObject.cpp
index 5042a49..209f5df 100644
--- a/src/FileObject.cpp
+++ b/src/FileObject.cpp
@@ -28,20 +28,20 @@ string getMostRecentFile(string readfile){
     DIR *dp = nullptr;
     int matchLen = readfile.size();
     vector<string> fileVersions;
-    if ((dp = opendir(".")) == nullptr) { cout << "tmp directory error " << endl; return ""; }
+    if ((dp = opendir(".")) == nullptr) { cout << "temp directory error " << endl; closedir(dp); return ""; }
     while ((entry = readdir(dp))){
         if (strncmp(entry->d_name, readfile.c_str(), matchLen) == 0){
             fileVersions.push_back(entry->d_name);
         }
     }
     sort(fileVersions.begin(), fileVersions.end());
+    closedir(dp);
     return fileVersions[fileVersions.size()-1];
 }
 
-void cleanupTmpFiles(){
+void cleanupTmpFiles(string match){
     struct dirent *entry = nullptr;
     DIR *dp = nullptr;
-    string match = "tmp-";
     int matchLen = match.size();
     if ((dp = opendir(".")) == nullptr) { cout << "tmp directory error " << endl;}
     while ((entry = readdir(dp))){
@@ -49,4 +49,5 @@ void cleanupTmpFiles(){
             remove(entry->d_name);
         }
     }
+    closedir(dp);
 }
diff --git a/src/Node.cpp b/src/Node.cpp
index d603037..2905d03 100644
--- a/src/Node.cpp
+++ b/src/Node.cpp
@@ -178,7 +178,9 @@ int Node::failureDetection(){
 
 					auto vecCopy(mapleProcessing[get<0>(keyTuple)]);
 					mapleProcessing[get<0>(mapleNodes[0])] = vecCopy;
+					for (auto el : vecCopy) workerTasks[get<0>(mapleNodes[0])].insert(el);
 					mapleProcessing.erase(get<0>(keyTuple));
+					workerTasks.erase(get<0>(keyTuple));
 
 					for (auto &e : mapleSending[get<0>(keyTuple)]){
 						vector<int> temp = randItems(1, fileList[get<0>(e)]);
@@ -810,15 +812,16 @@ void Node::handleTcpMessage()
 		// cout << "Has " << msg.type << " with " << msg.payload << endl;
 		switch (msg.type) {
 			case JUICESTART: {
-				if (mapleProcessing.size()) {tcpServent->regMessages.push(msg.toString()); break;}
-				//TODO
+				if (workerTasks.size()) {tcpServent->regMessages.push(msg.toString()); break;}
+				//TODO JUICESTART
+				//tell all nodes they can delete tmp files.
 			}
 			case MAPLESTART: {
 				//leader only function
 				//currently running something, dont start a new phase
-				if (mapleProcessing.size()) {tcpServent->regMessages.push(msg.toString()); cout << "[MAPLE] already mapling" << endl; break;}
+				if (workerTasks.size()) {tcpServent->regMessages.push(msg.toString()); cout << "[MAPLE] already mapling" << endl; break;}
 				cout << "[MAPLE] Leader starting new Maple phase" << endl;
-				cleanupTmpFiles();
+				cleanupTmpFiles("tmp-");
 				if (inMsg.size() >= 4){
 					string mapleExe = inMsg[0], num_maples = inMsg[1], sdfsPre = inMsg[2], sdfs_dir = inMsg[3] + "-";
 					int workers = stoi(num_maples);
@@ -860,7 +863,8 @@ void Node::handleTcpMessage()
 							vector<int> temp = randItems(1, fileList[file]);
 							string sender = hashRing->getValue(temp[0]); //because files are part of sdfs anyone can be the sender
 							string processor = mapleRing->getValue(id); //processor is a maple worker
-							mapleProcessing[processor].push_back(make_tuple(file, to_string(start), sender));
+							mapleProcessing[processor].push_back(make_tuple(file, to_string(start)));
+							workerTasks[processor].insert(make_tuple(file, to_string(start)));
 							cout << "[MAPLE] assign file " << file << " at " << to_string(start) << " to " << processor << endl;
 							mapleSending[sender].push_back(make_tuple(file, to_string(start)));
 							string maplemsg = sender + "::" + processor + "::" +mapleExe + "::" + s + "::" + sdfsPre;
@@ -896,7 +900,7 @@ void Node::handleTcpMessage()
 					int dataPipe[2];
 					if (pipe(dataPipe)){ fprintf (stderr, "Pipe failed.\n"); break; }
 					pid_t pid = fork();
-					if (pid){ //parent process, DONT need to waitpid because of signal handler set up
+					if (pid){
 					  close(dataPipe[1]);
 					  handlePipe(dataPipe[0]);
 					} else if (pid < 0) {
@@ -912,37 +916,6 @@ void Node::handleTcpMessage()
 					int status;
 					waitpid(pid, &status, 0);
 					close(dataPipe[0]);close(dataPipe[1]);
-					//go thorugh and process things from datapipe
-					//if processing success, send out TCP MAPLEACK
-					string match = "tmp-";
-					int matchLen = match.size();
-					struct dirent *entry = nullptr;
-					DIR *dp = nullptr;
-					if ((dp = opendir(".")) == nullptr) { cout << "tmp directory error " << match << endl; break; }
-					while ((entry = readdir(dp))){
-						//cout << "[FILES] found " << entry->d_name << " looking to match " << to_string(matchLen) << " chars from " << match << endl;
-					    if (strncmp(entry->d_name, match.c_str(), matchLen) == 0){
-							vector<string> tempVec = splitString(entry->d_name, "-");
-							if (tempVec.size() != 2) continue; //temp keys in form tmp-key
-							string keyFile = inMsg[5] + "-" + tempVec[tempVec.size()-1];
-							cout << "[CHUNKACK] transform from: " << entry->d_name << " to " << keyFile << endl;
-
-							/* TODO
-							* Need to change up how key comnbining works (also need master to keep track of all keys it sees for the next phase)
-							* 1) Master keeps track of the status of processing node assignments
-							* 2) on failure, instead of partial re-mapping, the entire node's assignments get redone
-							* 3) No longer merge temp files after assignment, instead just send the MAPLEACK
-							* 4) When the master marks all of a nodes assignments as done, send a message telling it to start merging
-							* 4b) may need to modify from PUT to a dedicated merge message
-							* 5) on success, notify the master and only then can the master remove the worker node from map of remaining tasks
-							*/
-							Messages outMsg(DNS, nodeInformation.ip + "::" + to_string(hashRingPosition) + "::" + keyFile + "::" + entry->d_name + "::" + to_string(-1) + "::" + to_string(-1) + "::" + keyFile + "::" + "0");
-
-							//cout << "[PUT] Got localfilename: " << entry->d_name << " with sdfsfilename: " << target << endl;
-							tcpServent->sendMessage(leaderIP, TCPPORT, outMsg.toString());
-						}
-					}
-					closedir(dp);
 					string ackStr = inMsg[0] + "::" + inMsg[4] + "::" + inMsg[2]; //IP, file, chunk
 					Messages ackMsg(MAPLEACK, ackStr);
 					tcpServent->sendMessage(leaderIP, TCPPORT, ackMsg.toString());
@@ -964,17 +937,65 @@ void Node::handleTcpMessage()
 			}
 
 			case MAPLEACK: {
-				vector<tuple<string,string,string>> temp;
-				for (auto &e : mapleProcessing[inMsg[0]]){
+				vector<tuple<string,string>> temp;
+				for (auto &e : workerTasks[inMsg[0]]){
 					if (get<0>(e).compare(inMsg[1]) == 0){
 						if (get<1>(e).compare(inMsg[2]) == 0){
-							continue;
+							temp.push_back(e);
 						}
 					}
-					temp.push_back(e);
 				}
-				if (temp.size()) mapleProcessing[inMsg[0]] = temp;
-				else mapleProcessing.erase(inMsg[0]);
+				for (auto &e : temp) workerTasks[inMsg[0]].erase(e);
+				if (!workerTasks[inMsg[0]].size()) {
+					Messages outMsg(STARTMERGE, "");
+					this->tcpServent->sendMessage(inMsg[0], TCPPORT, outMsg.toString());
+				}
+				break;
+			}
+
+			case STARTMERGE: {
+				string sendMsg = hashRing->getValue(leaderPosition) + "::" + TCPPORT;
+				this->tcpServent->mergeMessages.push(sendMsg);
+			}
+
+			case MERGECOMPLETE: {
+				workerTasks.erase(inMsg[0]);
+				mapleProcessing.erase(inMsg[0]);
+				//actually merge files in
+				struct dirent *entry = nullptr;
+			    DIR *dp = nullptr;
+				string match = "tmp-" + inMsg[0] + "-";
+			    int matchLen = match.size();
+			    if ((dp = opendir(".")) == nullptr) { cout << "tmp directory error " << endl;}
+				cout << "[MERGECOMPLETE] processing files matching " << match << " and replacing with prefix: " << sdfsPre << endl;
+			    while ((entry = readdir(dp))){
+			        if (strncmp(entry->d_name, match.c_str(), matchLen) == 0){
+			            string entryName(entry->d_name);
+						string mapleOutput = sdfsPre + "-" + entryName.substr(matchLen);
+						ofstream keyFile;
+						keyFile.open(mapleOutput, ios::app);
+						ifstream toMerge(entry->d_name);
+						if (!toMerge.is_open() || !keyFile.is_open()) {
+							cout << "bad file permissions for " << entry->d_name << " and/or " << mapleOutput << endl;
+							break;
+						}
+						keyFile << toMerge.rdbuf();
+						keyFile.close();
+			        }
+			    }
+
+				if (!mapleProcessing.size()) { //start replication of key files
+
+				}
+
+				break;
+			}
+
+			//because TCP if we get a fail, we know that the node failed
+			//so re-requesting the files to merge will be taken care of in failureDetection()
+			case MERGEFAIL: {
+				string tmpFiles = "tmp-" + inMsg[0] + "-";
+				cleanupTmpFiles(tmpFiles);
 				break;
 			}
 
@@ -1047,7 +1068,7 @@ void Node::handleTcpMessage()
 				if(isLeader){
 					// Check hashring, get positions and send out DNS ANS
 					isBlackout = true;
-					if(inMsg.size() >= 8){
+					if(inMsg.size() >= 7){
 						string inMsgIP = inMsg[0];
 						int nodePosition = stoi(inMsg[1]);
 						string sdfsfilename = inMsg[2];
@@ -1055,7 +1076,6 @@ void Node::handleTcpMessage()
 						long int size = stol(inMsg[4]);
 						int lines = stoi(inMsg[5]);
 						string overwriteFilename = inMsg[6];
-						string overwrite = inMsg[7];
 						//cout << "[DNS] Got " << "inMsgIP: " << inMsgIP << ", sdfsfilename: " << sdfsfilename;
 						//cout << ", localfilename: " << localfilename << ", pos: " << nodePosition << endl;
 						// update fileList, client itself is one of the replicas
@@ -1082,7 +1102,7 @@ void Node::handleTcpMessage()
 						pendingRequests[sdfsfilename] = tuple<int, int, int>(closestNode, pred, succ);
 						pendingRequestSent[sdfsfilename] = tuple<int, int, int>(true, false, false);
 						pendingSenderRequests[sdfsfilename] = tuple<string, string, string>(inMsgIP, "", "");
-						Messages outMsg(DNSANS, to_string(closestNode) + "::" + localfilename + "::" + sdfsfilename + "::" + overwriteFilename + "::" + overwrite);
+						Messages outMsg(DNSANS, to_string(closestNode) + "::" + localfilename + "::" + sdfsfilename + "::" + overwriteFilename);
 						this->tcpServent->sendMessage(inMsgIP, TCPPORT, outMsg.toString());
 					}
 				}
@@ -1091,14 +1111,14 @@ void Node::handleTcpMessage()
 			}
 			case DNSANS:{
 				// Read the answer and send a PUT msg to dest
-				if(inMsg.size() >= 5){
+				if(inMsg.size() >= 4){
 					int nodePosition = stoi(inMsg[0]);
 					// since we do not keep files in hashRing, the value itself is IPaddress, not NODE:IP_Address
 					string nodeIP = hashRing->getValue(nodePosition);
 					//cout << "nodeIP " << nodeIP << endl;
 					//cout << "[DNSANS] " << "we will put sdfsfilename: " << inMsg[2] << " to nodeIP: " << nodeIP;
 					//cout << " using localfilename: " << inMsg[1] << endl;
-					string sendMsg = nodeIP+"::"+inMsg[1]+"::"+inMsg[2]+"::"+inMsg[3]+"::"+inMsg[4];
+					string sendMsg = nodeIP+"::"+inMsg[1]+"::"+inMsg[2]+"::"+inMsg[3];
 					this->tcpServent->pendSendMessages.push(sendMsg);
 				}
 				break;
@@ -1113,7 +1133,7 @@ void Node::handleTcpMessage()
 					string localfilename = this->localFilelist[sdfsfilename];
 					cout << "[REREPLICATEGET] Got a request of sdfsfilename " << sdfsfilename << " to nodeIP " << nodeIP << endl;
 					cout << "[REREPLICATEGET] Put localfilename " << localfilename << " to nodeIP " << nodeIP << endl;
-					string sendMsg = nodeIP+"::"+localfilename+"::"+sdfsfilename+"::"+remoteLocalfilename+"::"+"1";
+					string sendMsg = nodeIP+"::"+localfilename+"::"+sdfsfilename+"::"+remoteLocalfilename;
 					this->tcpServent->pendSendMessages.push(sendMsg);
 				}
 				break;
@@ -1128,9 +1148,8 @@ void Node::handleTcpMessage()
 					string localfilename = this->localFilelist[sdfsfilename];
 					cout << "[REREPLICATE] Got a request of sdfsfilename " << sdfsfilename << " to nodeIP " << nodeIP << endl;
 					cout << "[REREPLICATE] Put localfilename " << localfilename << " to nodeIP " << nodeIP << endl;
-					string sendMsg = nodeIP+"::"+localfilename+"::"+sdfsfilename+"::"+"::"+"1";
+					string sendMsg = nodeIP+"::"+localfilename+"::"+sdfsfilename+"::";
 					this->tcpServent->pendSendMessages.push(sendMsg);
-					//this->tcpServent->sendFile(nodeIP, TCPPORT, localfilename, sdfsfilename, "");
 				}
 				break;
 			}
diff --git a/src/TcpSocket.cpp b/src/TcpSocket.cpp
index 22b1d8d..c923da1 100644
--- a/src/TcpSocket.cpp
+++ b/src/TcpSocket.cpp
@@ -85,39 +85,89 @@ void TcpSocket::bindServer(string port)
 }
 
 string TcpSocket::getFileMetadata(int size, string checksum,
-	string sdfsfilename, string localfilename, string remoteLocalfilename, string overwrite)
+	string sdfsfilename, string localfilename, string remoteLocalfilename)
 {
 	// format: size,checksum,sdfsfilename
-	string msg = to_string(size) + "," + checksum + "," + sdfsfilename+","+localfilename+","+remoteLocalfilename+","+overwrite;
+	string msg = to_string(size) + "," + checksum + "," + sdfsfilename+","+localfilename+","+remoteLocalfilename;
 	return msg;
 }
 
-void TcpSocket::sendFile(string ip, string port,
-	string localfilename, string sdfsfilename, string remoteLocalfilename, string overwrite)
+string TcpSocket::getDirMetadata()
 {
-	int numbytes, sockfd;
-	char buf[DEFAULT_TCP_BLKSIZE];
-	FILE *fp;
-	int size = 0, sendSize = 0;
-	bzero(buf, sizeof(buf));
-	if ((sockfd = createConnection(ip, port)) == -1) return;
-	fp = fopen(localfilename.c_str(), "rb");
+	struct dirent *entry = nullptr;
+    DIR *dp = nullptr;
+	FILE * fp;
+    string match = "tmp-";
+    int matchLen = match.size();
+	vector<string> split;
+	int size = 0;
+	string msg;
+    if ((dp = opendir(".")) == nullptr) { cout << "tmp directory error " << endl;}
+    while ((entry = readdir(dp))){
+        if (strncmp(entry->d_name, match.c_str(), matchLen) == 0){
+			split.clear();
+            split = splitString(entry->d_name, "-");
+			if (split.size() > 2) continue;
+			fp = fopen(entry->d_name, "rb");
+			if (fp == NULL) {
+				printf("Could not open file to send.");
+				continue;
+			}
+			fseek(fp, 0, SEEK_END);
+			size = ftell(fp);
+			fseek(fp, 0, SEEK_SET);
+			if (msg.size()) msg += ",";
+			msg += split[1];
+			msg += to_string(size);
+			fclose(fp);
+        }
+    }
+	closedir(dp);
+	return msg;
+}
+
+void TcpSocket::putDirectory(string ip, string port) {
+	string toSend = getDirMetadata();
+	if (!toSend.size()) return;
+	Messages msg(MERGE, toSend);
+	sendMessage(ip, port, msg.toString());
+	vector<string> toProcess = splitString(toSend, ",");
+	FILE * fp;
+	int index = 0;
+	while (index < toProcess.size() - 1){
+		fp = fopen(toProcess[index].c_str(), "rb");
+		if (fp == NULL) {
+			printf("Could not open file to send.");
+			continue;
+		}
+		sendFile(ip, port, fp, stoi(toProcess[index+1]));
+		fclose(fp);
+		index += 2;
+	}
+}
+
+
+void TcpSocket::putFile(string ip, string port, string localfilename, string sdfsfilename, string remoteLocalfilename){
+	FILE *fp = fopen(localfilename.c_str(), "rb");
 	if (fp == NULL) {
 		printf("Could not open file to send.");
 		return;
 	}
 	fseek(fp, 0, SEEK_END);
-	size = ftell(fp);
+	int size = ftell(fp);
 	fseek(fp, 0, SEEK_SET);
-
-	// send bytes and filename first
 	FileObject f(localfilename);
-	Messages msg(PUT, getFileMetadata(size, f.checksum, sdfsfilename, localfilename, remoteLocalfilename, overwrite));
-	string payload = msg.toString();
-	if (send(sockfd, payload.c_str(), strlen(payload.c_str()), 0) == -1) {
-		perror("send");
-	}
+	Messages msg(PUT, getFileMetadata(size, f.checksum, sdfsfilename, localfilename, remoteLocalfilename));
+	sendMessage(ip, port, msg.toString());
+	sendFile(ip, port, fp, size);
+}
+
+void TcpSocket::sendFile(string ip, string port, FILE * fp, int size) {
 	sleep(1);
+	int numbytes, sockfd, sendSize;
+	if ((sockfd = createConnection(ip, port)) == -1) return;
+	char buf[DEFAULT_TCP_BLKSIZE];
+	bzero(buf, sizeof(buf));
 	while (!feof(fp) && size > 0) {
 		sendSize = (size < DEFAULT_TCP_BLKSIZE) ? size : DEFAULT_TCP_BLKSIZE;
 		bzero(buf, sizeof(buf));
@@ -214,7 +264,8 @@ int TcpSocket::createConnection(string ip, string port){
 
 int TcpSocket::messageHandler(int sockfd, string payloadMessage, string returnIP){
 	char buf[DEFAULT_TCP_BLKSIZE];
-	int numbytes = 0;
+	int numbytes = 0, filesize = 0, byteReceived = 0;
+	FILE *fp;
 	Messages msg(payloadMessage);
 	switch (msg.type) {
 		case ELECTION:
@@ -222,22 +273,45 @@ int TcpSocket::messageHandler(int sockfd, string payloadMessage, string returnIP
 			qMessages.push(payloadMessage);
 			break;
 		}
+		case MERGE: {
+			vector<string> filesAndSizes = splitString(msg.payload, ",");
+			int index = 0;
+			int fail = 0;
+			while (index < filesAndSizes.size() - 1){
+				string filename = "tmp-" + returnIP + "-" + filesAndSizes[index];
+				filesize = stoi(filesAndSizes[index+1]);
+				numbytes = 0;
+				byteReceived = 0;
+				fp = fopen(filename.c_str(), "wb");
+				bzero(buf, sizeof(buf));
+				while ((numbytes=recv(sockfd, buf, DEFAULT_TCP_BLKSIZE, 0)) > 0) {
+					fwrite(buf, sizeof(char), numbytes, fp);
+					byteReceived += numbytes;
+					if (byteReceived >= filesize) {
+						break;
+					}
+					bzero(buf, sizeof(buf));
+				}
+				if (byteReceived < filesize) fail = 1;
+				cout << "we have " << to_string(byteReceived) << " bytes from this connection" << endl;
+				fclose(fp);
+				index += 2;
+			}
+			if (fail) { Messages ack(MERGEFAIL, returnIP + "::"); regMessages.push(ack.toString()); }
+			else { Messages ack(MERGECOMPLETE, returnIP + "::"); regMessages.push(ack.toString()); }
+			break;
+		}
 		case PUT: {
-			FILE *fp;
-			int filesize = 0, byteReceived = 0;
-			string mode = "wb";
-			string sdfsfilename = "", incomingChecksum = "", remoteLocalname = "", overwriteFilename = "", prefix = "", overwrite = "", localfilename = "";
+			string sdfsfilename = "", incomingChecksum = "", remoteLocalname = "", overwriteFilename = "", prefix = "", localfilename = "";
 			// format: size,checksum,sdfsfilename
 			vector<string> fields = splitString(msg.payload, ",");
 			int start = -1;
-			if (fields.size() == 6) {
+			if (fields.size() == 5) {
 				filesize = stoi(fields[0]);
 				incomingChecksum = fields[1];
 				sdfsfilename = fields[2];
 				remoteLocalname = fields[3];
 				overwriteFilename = fields[4];
-				overwrite = fields[5];
-				if ((stoi(overwrite)) == 0) mode = "ab";
 				cout << "[PUT] file is " << sdfsfilename << " with size " << filesize << " and checksum " << incomingChecksum << endl;
 				time_t fileTimestamp;
 				time(&fileTimestamp);
@@ -247,7 +321,8 @@ int TcpSocket::messageHandler(int sockfd, string payloadMessage, string returnIP
 					//cout << "it's GET with filename " << overwriteFilename << endl;
 				}
 				//cout << "backup filename " << localfilename << endl;
-			} else {
+			}
+			if (fields.size() == 6){
 				//size, exec, read, start, tmp, prefix
 				filesize = stoi(fields[0]);
 				localfilename = fields[4]; //tempfile to read from
@@ -257,13 +332,7 @@ int TcpSocket::messageHandler(int sockfd, string payloadMessage, string returnIP
 				prefix = fields[5];
 				cout << "[PUT] bytes: " << filesize << " exec: " << sdfsfilename << ", actual: " << remoteLocalname << ", start: " << to_string(start) << ", temp: " << localfilename  << ", prefix: " << prefix << endl;
 			}
-			fp = fopen(localfilename.c_str(), mode.c_str());
-			if (fp == NULL) {
-				cout << "file error" << endl;
-				close(sockfd);
-				return 1;
-			}
-
+			fp = fopen(localfilename.c_str(), "wb");
 			bzero(buf, sizeof(buf));
 			while ((numbytes=recv(sockfd, buf, DEFAULT_TCP_BLKSIZE, 0)) > 0) {
 				fwrite(buf, sizeof(char), numbytes, fp);
@@ -305,6 +374,9 @@ int TcpSocket::messageHandler(int sockfd, string payloadMessage, string returnIP
 		case MAPLEACK:
 		case CHUNK:
 		case CHUNKACK:
+		case STARTMERGE:
+		case MERGECOMPLETE:
+		case MERGEFAIL:
 		case DNS:{
 			//cout << "["<< messageTypes[msg.type] << "] payloadMessage: " << payloadMessage << endl;
 			regMessages.push(payloadMessage); //handle from queue
diff --git a/src/TestBench.cpp b/src/TestBench.cpp
index 94d1255..93cb1ce 100644
--- a/src/TestBench.cpp
+++ b/src/TestBench.cpp
@@ -118,7 +118,7 @@ void *runTcpClientTEST(void *tcpSocket)
 	// testing to send file
 	for (int i=0; i<2; i++) {
 		sleep(1);
-		tcp->sendFile("127.0.0.1", TCPPORT, "file_example_MP3_700KB.mp3", "file_example_MP3_700KB.mp3", "file_example_MP3_700KB.mp3", "1");
+		tcp->putFile("127.0.0.1", TCPPORT, "file_example_MP3_700KB.mp3", "file_example_MP3_700KB.mp3", "file_example_MP3_700KB.mp3");
 	}
 	pthread_exit(NULL);
 }
diff --git a/src/Threads.cpp b/src/Threads.cpp
index dea6f26..091d391 100644
--- a/src/Threads.cpp
+++ b/src/Threads.cpp
@@ -24,7 +24,7 @@ void *runTcpSender(void *tcpSocket)
 		while (!tcp->mapleMessages.empty()) {
 			vector<string> msgSplit = splitString(tcp->mapleMessages.front(), "::");
 			string removeSender = tcp->mapleMessages.front().substr(msgSplit[0].size() + 2);
-			cout << "[TEST] " << removeSender << endl;
+			//cout << "[TEST] " << removeSender << endl;
 			Messages msg(CHUNK, removeSender);
 			//processor, exec, file, start, prefix
 			tcp->sendMessage(msgSplit[0], TCPPORT, msg.toString());
@@ -32,9 +32,8 @@ void *runTcpSender(void *tcpSocket)
 		}
 		while (!tcp->pendSendMessages.empty()) {
 			vector<string> msgSplit = splitString(tcp->pendSendMessages.front(), "::");
-			if (msgSplit.size() >= 5) {
-				string nodeIP = msgSplit[0], localfilename = msgSplit[1], overwrite = msgSplit[4];
-				string sdfsfilename = msgSplit[2], remoteLocalfilename = msgSplit[3];
+			if (msgSplit.size() >= 4) {
+				string nodeIP = msgSplit[0], localfilename = msgSplit[1], sdfsfilename = msgSplit[2], remoteLocalfilename = msgSplit[3];
 				cout << "[DOSEND] nodeIP " << nodeIP << ", localfilename " << localfilename;
 				cout << ", sdfsfilename " << sdfsfilename << ", remoteLocalfilename " << remoteLocalfilename << endl;
 				if (msgSplit.size() == 6){
@@ -44,10 +43,15 @@ void *runTcpSender(void *tcpSocket)
 					cout << "[CHUNK] sending : " << sdfsfilename << " from " << msgSplit[3] << " to " << msgSplit[5] << endl;
 					tcp->sendLines(nodeIP, TCPPORT, localfilename, sdfsfilename, msgSplit[4], start, end); //exec, file, start, end
 				}
-				else tcp->sendFile(nodeIP, TCPPORT, localfilename, sdfsfilename, remoteLocalfilename, overwrite);
+				else tcp->putFile(nodeIP, TCPPORT, localfilename, sdfsfilename, remoteLocalfilename);
 			}
 			tcp->pendSendMessages.pop();
 		}
+		while (!tcp->mergeMessages.empty()) {
+			vector<string> msgSplit = splitString(tcp->mergeMessages.front(), "::");
+			tcp->putDirectory(msgSplit[0], msgSplit[1]);
+			tcp->mergeMessages.pop();
+		}
 	}
 	pthread_exit(NULL);
 }
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 2c06f2c..099b7b7 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -54,7 +54,7 @@ void handlePipe(int file) {
 	size_t bufSize = 1024;
 	cout << "[PIPE] sleeping for data. " << endl;
 	sleep(5);
-    FILE *stream = fdopen(file, "r"); FILE *tmp;
+    FILE *stream = fdopen(file, "rb"); FILE *tmp;
     char str[bufSize];
 	const char * delim = ",";
 	int lines = 0;
diff --git a/src/main.cpp b/src/main.cpp
index b11ba4a..87b41b7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -104,7 +104,7 @@ int main(int argc, char *argv[])
 				string line;
 				ifstream myfile(localfilename.c_str());
 				while (getline(myfile, line)) ++number_of_lines;
-				Messages outMsg(DNS, node->nodeInformation.ip + "::" + to_string(node->hashRingPosition) + "::" + sdfsfilename + "::" + localfilename + "::" + to_string(size) + "::" + to_string(number_of_lines) + "::" + "::" + "1");
+				Messages outMsg(DNS, node->nodeInformation.ip + "::" + to_string(node->hashRingPosition) + "::" + sdfsfilename + "::" + localfilename + "::" + to_string(size) + "::" + to_string(number_of_lines) + "::");
 				cout << "[PUT] Got localfilename: " << localfilename << " with sdfsfilename: " << sdfsfilename << endl;
 				node->tcpServent->sendMessage(node->leaderIP, TCPPORT, outMsg.toString());
 			} else {
-- 
GitLab