Project

General

Profile

Revision 2

Upload Project

View differences:

src/chunk/Chunk.java
1
package chunk;
2

  
3
import java.io.File;
4
import java.io.FileOutputStream;
5
import java.io.RandomAccessFile;
6
import java.io.UnsupportedEncodingException;
7
import java.security.MessageDigest;
8
import java.security.NoSuchAlgorithmException;
9

  
10
import javax.xml.bind.DatatypeConverter;
11

  
12
public class Chunk {
13
    public static final int CHUNK_MAX_SIZE = 64000;
14

  
15
    private int chunkNo;
16
    private String fileID;
17

  
18
    private int repDegree;
19

  
20
    private byte[] data;
21

  
22
    public Chunk(String fileID, int chunkNo, int repDegree, byte[] data) {
23
        this.chunkNo = chunkNo;
24
        this.fileID = fileID;
25
        this.data = data;
26
        this.repDegree = repDegree;
27
    }
28

  
29
    /**
30
     * @return The chunk's file ID
31
     */
32
    public String getFileID() {
33
        return fileID;
34
    }
35

  
36
    /**
37
     * @return The chunk number
38
     */
39
    public int getChunkNo() {
40
        return chunkNo;
41
    }
42

  
43
    /**
44
     * @return The chunk replication degree
45
     */
46
    public int getRepDegree() {
47
        return repDegree;
48
    }
49

  
50
    /**
51
     * @return The chunk data byte array
52
     */
53
    public byte[] getData() {
54
        return data;
55
    }
56

  
57
    public static Chunk[] splitFile(String path, int repDegree) {
58
        File file = new File(path);
59
        return splitFile(file, repDegree);
60
    }
61

  
62
    public static int getNumberOfFileChunks(File file) {
63
        long nFileBytes = file.length();
64
        return (int) ((nFileBytes - 1) / CHUNK_MAX_SIZE + 1);
65
    }
66

  
67
    public static Chunk[] splitFile(File file, int repDegree) {
68
        if (!file.isFile()) {
69
            return null;
70
        }
71
        long nFileBytes = file.length();
72
        int nChunks = getNumberOfFileChunks(file);
73
        Chunk[] chunks = new Chunk[nChunks];
74
        String fileId = generateFileId(file);
75
        try (RandomAccessFile data = new RandomAccessFile(file, "r")) {
76
            int nReadBytes = 0;
77
            for (int i = 0; i < nChunks; i++) {
78
                int nBytesToRead;
79
                int nBytesMissing = (int) (nFileBytes - nReadBytes);
80
                if (nBytesMissing < CHUNK_MAX_SIZE) {
81
                    nBytesToRead = nBytesMissing;
82
                } else {
83
                    nBytesToRead = CHUNK_MAX_SIZE;
84
                }
85
                byte[] newData = new byte[nBytesToRead];
86
                data.readFully(newData);
87
                Chunk newChunk = new Chunk(generateFileId(file), i + 1, repDegree, newData);
88
                chunks[i] = newChunk;
89
                nReadBytes += CHUNK_MAX_SIZE;
90
            }
91
        } catch (Exception e) {
92
            e.printStackTrace();
93
        }
94
        return chunks;
95
    }
96

  
97
    public static String generateFileId(File file) {
98
        MessageDigest digest;
99
        try {
100
            digest = MessageDigest.getInstance("SHA-256");
101
        } catch (NoSuchAlgorithmException e) {
102
            e.printStackTrace();
103
            return null;
104
        }
105
        String toEncode = file.getName() + Long.toString(file.length());
106
        byte[] encodedhash;
107
        try {
108
            encodedhash = digest.digest(toEncode.getBytes("UTF-8"));
109
            return DatatypeConverter.printBase64Binary(encodedhash);
110
        } catch (UnsupportedEncodingException e) {
111
            e.printStackTrace();
112
        }
113
        return "invalid";
114
    }
115

  
116
    public static void sortChunkArray(Chunk[] chunks) {
117
        for (int i = 0; i < chunks.length; i++) {
118
            Chunk currChunk = chunks[i];
119
            int nCurrChunk = currChunk.getChunkNo();
120
            if (nCurrChunk != i + 1) {
121
                Chunk tempChunk = chunks[i];
122
                chunks[i] = chunks[nCurrChunk - 1];
123
                chunks[nCurrChunk - 1] = tempChunk;
124
            }
125
        }
126
    }
127

  
128
    public static void restoreFile(Chunk[] chunks, String filePath) {
129
        sortChunkArray(chunks);
130
        try (FileOutputStream fos = new FileOutputStream(filePath)) {
131
            for (int i = 0; i < chunks.length; i++) {
132
                fos.write(chunks[i].getData());
133
            }
134
        } catch (Exception e) {
135
            e.printStackTrace();
136
        }
137
    }
138

  
139
    @Override
140
    public boolean equals(Object obj) {
141
        if (obj == null) {
142
            return false;
143
        }
144
        final Chunk c = (Chunk) obj;
145
        return (c.chunkNo == chunkNo && c.fileID.equals(fileID) && c.repDegree == repDegree);
146
    }
147
}
compile.bat
1
javac .\src\utils\*.java .\src\chunk\*.java .\src\disk\*.java .\src\message\*.java .\src\peer\*.java .\src\peer\channels\*.java .\src\peer\protocols\backup\*.java .\src\peer\protocols\reclaim\*.java .\src\peer\protocols\restore\*.java .\src\peer\protocols\delete\*.java .\src\client\*.java -d .\bin
src/client/TestApp.java
1
package client;
2

  
3
import utils.Utils;
4

  
5
import java.lang.Integer;
6
import java.rmi.NotBoundException;
7
import java.rmi.RemoteException;
8
import java.rmi.registry.LocateRegistry;
9
import java.rmi.registry.Registry;
10

  
11
import peer.PeerInterface;
12

  
13
import java.lang.Float;
14

  
15
/**
16
 * TestApp
17
 */
18
public class TestApp {
19

  
20
    private String peer_ap;
21
    private String operation;
22
    private String filePath;
23
    private float diskSpace;
24
    private int replicationDeg;
25
    private PeerInterface pInterface;
26

  
27
    public static void main(String[] args){
28
        TestApp app = new TestApp(args);
29
        app.processRequest();
30
    }
31

  
32
    public TestApp(String[] args) {
33
        if (!handleInputs(args)) {
34
            usage();
35
            return;
36
        }
37

  
38
        connect();
39
    }
40

  
41
    public void processRequest(){
42
        switch (operation) {
43
            case "BACKUP":
44
                System.out.println("BACKUP:\n\tFile: " + filePath + "\n\tReplication Degree: " + replicationDeg);
45
                try {
46
                    pInterface.backup(filePath, replicationDeg);
47
                } catch (RemoteException e) {
48
                    System.out.println("BACKUP ERROR!");
49
                    e.printStackTrace();
50
                }
51
                System.out.println("BACKUP SUCCESSFUL!");
52
                break;
53
            case "RESTORE":
54
                System.out.println("RESTORE:\n\tFile: " + filePath);
55
                try {
56
                    pInterface.restore(filePath);
57
                } catch (RemoteException e) {
58
                    System.out.println("RESTORE ERROR!");
59
                    e.printStackTrace();
60
                }
61
                System.out.println("RESTORE SUCCESSFUL!");
62
                break;
63
            case "DELETE":
64
                System.out.println("DELETE:\n\tFile: " + filePath);
65
                try {
66
                    pInterface.delete(filePath);
67
                } catch (RemoteException e) {
68
                    System.out.println("DELETE ERROR!");
69
                    e.printStackTrace();
70
                }
71
                System.out.println("DELETE SUCCESSFUL!");
72
                break;
73
            case "RECLAIM":
74
                System.out.println("RECLAIM:\n\tDisk Space: " + diskSpace);
75
                try {
76
                    pInterface.reclaim(diskSpace);
77
                } catch (RemoteException e) {
78
                    System.out.println("RECLAIM ERROR!");
79
                    e.printStackTrace();
80
                }
81
                System.out.println("RECLAIM SUCCESSFUL!");
82
                break;
83
            case "STATE":
84
                System.out.println("STATE:");
85
                try {
86
                    pInterface.state();
87
                } catch (RemoteException e) {
88
                    System.out.println("STATE ERROR!");
89
                    e.printStackTrace();
90
                }
91
                System.out.println("STATE SUCCESSFUL!");
92
                    break;
93
            default:
94
                break;
95
            }
96
    }
97
        
98
    
99

  
100
    private boolean handleInputs(String[] args) {
101
        if (args.length < 2) {
102
            System.out.println("Error: Invalid number of arguments!");
103
            return false;
104
        }
105

  
106
        this.peer_ap = args[0];
107
        
108
        this.operation = args[1].toUpperCase();
109
        switch (operation) {
110
        case "BACKUP":
111
            if (args.length != 4) {
112
                System.out.println(operation + " error: Invalid number of arguments!");
113
                return false;
114
            }
115
            if (!Utils.fileExists(args[2])) {
116
                System.out.println(operation + " error: File doesn't exist!");
117
                return false;
118
            }
119
            this.filePath = args[2];
120
            if (!Utils.isInteger(args[3])) {
121
                System.out.println(operation + " error: Replication Degree invalid!");
122
                return false;
123
            }
124
            this.replicationDeg = Integer.parseInt(args[3]);
125
            break;
126
        case "RESTORE":
127
            if (args.length != 3) {
128
                System.out.println(operation + " error: Invalid number of arguments!");
129
                return false;
130
            }
131
            if (!Utils.fileExists(args[2])) {
132
                System.out.println(operation + " error: File doesn't exist!");
133
                return false;
134
            }
135
            this.filePath = args[2];
136
            break;
137
        case "DELETE":
138
            if (args.length != 3) {
139
                System.out.println(operation + " error: Invalid number of arguments!");
140
                return false;
141
            }
142
            if (!Utils.fileExists(args[2])) {
143
                System.out.println(operation + " error: File doesn't exist!");
144
                return false;
145
            }
146
            this.filePath = args[2];
147
            break;
148
        case "RECLAIM":
149
            if (args.length != 3) {
150
                System.out.println(operation + " error: Invalid number of arguments!");
151
                return false;
152
            }
153
            if (!Utils.isFloat(args[2])) {
154
                System.out.println(operation + " error: Maximum amount of disk space invalid!");
155
                return false;
156
            }
157
            this.diskSpace = Float.parseFloat(args[2]);
158
            break;
159
        case "STATE":
160
            if (args.length != 2) {
161
                System.out.println(operation + " error: Invalid number of arguments!");
162
                return false;
163
            }
164
            break;
165
        default:
166
            System.out.println("Error: Invalid operation!");
167
            return false;
168
        }
169
        return true;
170
    }
171

  
172
    private static void usage() {
173
        System.out.println(
174
                "Usage:\n\tjava TestApp <peer_ap> <operation> <opnd_1> <opnd2>\n\t\t<peer_app>: Peer's access point;\n\t\t<operation>: Operation the peer of backup service must execute. It must be one of: BACKUP, RESTORE, DELETE, RECLAIM, STATE;\n\t\t<opnd_1>: Path Name of the file in case of operations BACKUP, RESTORE or DELETE or maximum amount of disk space (in KByte) in case of operation RECLAIM\n\t\t<opnd_2>: Integer that specifies the desired replication degree for operation BACKUP");
175
        return;
176
    }
177

  
178
    public void connect() {
179
        try {
180
            Registry rmiReg = LocateRegistry.getRegistry(Registry.REGISTRY_PORT);
181
            this.pInterface = (PeerInterface) rmiReg.lookup(this.peer_ap);
182
        } catch (RemoteException | NotBoundException e) {
183
            e.printStackTrace();
184
        }
185
    }
186
}
src/disk/ChunkManagement.java
1
package disk;
2

  
3
import java.util.HashMap;
4
import java.util.HashSet;
5
import java.util.Map;
6
import java.util.concurrent.BlockingQueue;
7
import java.util.concurrent.LinkedBlockingDeque;
8

  
9
import chunk.Chunk;
10
import javafx.util.Pair;
11

  
12
/**
13
 * ChunkManagement
14
 */
15
public class ChunkManagement {
16

  
17
	private static ChunkManagement chunkManagementInstance = null;
18

  
19
	private Map<String, Map<Integer, Integer>> storesCounter;
20

  
21
	private BlockingQueue<Chunk> restoreChunks;
22

  
23
	private ChunkManagement() {
24
		storesCounter = new HashMap<String, Map<Integer, Integer>>();
25
		restoreChunks = new LinkedBlockingDeque<Chunk>();
26
	}
27

  
28
	public static ChunkManagement getInstance() {
29
		if (chunkManagementInstance == null) {
30
			chunkManagementInstance = new ChunkManagement();
31
		}
32
		return chunkManagementInstance;
33
	}
34

  
35
	public int getStores(String fileId, int chunkNo) {
36
		if (!storesCounter.containsKey(fileId)){
37
			return 0;
38
		}
39
		if (!storesCounter.get(fileId).containsKey(chunkNo)){
40
			return 0;
41
		}
42
		return storesCounter.get(fileId).get(chunkNo);
43
	}
44

  
45
	public int registerStored(String fileId, int chunkNo) {
46
		if (!storesCounter.containsKey(fileId)) {
47
			storesCounter.put(fileId, new HashMap<Integer, Integer>());
48
		}
49
		if (!storesCounter.get(fileId).containsKey(chunkNo)) {
50
			storesCounter.get(fileId).put(chunkNo, 1);
51
		} else {
52
			int nStores = storesCounter.get(fileId).get(chunkNo);
53
			storesCounter.get(fileId).put(chunkNo, nStores + 1);
54
		}
55
		return storesCounter.get(fileId).get(chunkNo);
56
	}
57

  
58
	public int registerRemoved(String fileId, int chunkNo) {
59
		if (!storesCounter.containsKey(fileId)) {
60
			return 0;
61
		}
62
		if (!storesCounter.get(fileId).containsKey(chunkNo)) {
63
			return 0;
64
		} else {
65
			int nStores = storesCounter.get(fileId).get(chunkNo);
66
			storesCounter.get(fileId).put(chunkNo, nStores - 1);
67
			return storesCounter.get(fileId).get(chunkNo);
68
		}
69
	}
70

  
71
	public void deleteStores(String fileId) {
72
		storesCounter.remove(fileId);
73
	}
74

  
75
	public void addRestoreChunk(Chunk chunk) {
76
		restoreChunks.add(chunk);
77
	}
78

  
79
	/**
80
	 * @return the restoreChunks
81
	 */
82
	public BlockingQueue<Chunk> getRestoreChunks() {
83
		return restoreChunks;
84
	}
85

  
86
}
src/disk/Disk.java
1
package disk;
2

  
3
import chunk.*;
4
import utils.Utils;
5

  
6
import java.io.File;
7
import java.io.FileOutputStream;
8
import java.io.FileInputStream;
9
import java.io.IOException;
10

  
11
/**
12
 * Disk
13
 */
14
public class Disk {
15

  
16
	public static final String fileSeparator = System.getProperty("file.separator");
17
	public static final String filesPath = "." + fileSeparator + "files" + fileSeparator;
18
	public static final String resourcesPath = filesPath + "resources" + fileSeparator;
19
	public static final String defaultDiskLocation = filesPath + "peers" + fileSeparator;
20
	public static final long defaultDiskSize = 10000000; /* Disk size in KBytes */
21

  
22
	private long size; /* Disk size in bytes */
23
	private String diskLocation;
24
	private File directory;
25
	private File backupDirectory, restoredDirectory;
26

  
27
	public void restoreFile(Chunk[] chunks, String fileName) {
28
		Chunk.restoreFile(chunks, getRestoredDirectoryPath() + fileSeparator + fileName);
29
	}
30

  
31
	public Disk(String diskName) {
32
		this(diskName, defaultDiskSize);
33
	}
34

  
35
	public Disk(String diskName, float size) {
36
		this.diskLocation = defaultDiskLocation + diskName;
37
		this.size = (long) (size * 1000);
38
		createDiskDirectory();
39
	}
40

  
41
	/**
42
	 * @return the backupDirectory
43
	 */
44
	public File getBackupDirectory() {
45
		return backupDirectory;
46
	}
47

  
48
	/**
49
	 * @return the defaultDiskLocation
50
	 */
51
	public static String getDefaultDiskLocation() {
52
		return defaultDiskLocation;
53
	}
54

  
55
	/**
56
	 * @return the directory
57
	 */
58
	public File getDirectory() {
59
		return directory;
60
	}
61

  
62
	/**
63
	 * @return the restoredDirectory
64
	 */
65
	public File getRestoredDirectory() {
66
		return restoredDirectory;
67
	}
68

  
69
	public String getRestoredDirectoryPath() {
70
		return restoredDirectory.getAbsolutePath();
71
	}
72

  
73
	public boolean createDiskDirectory() {
74
		directory = new File(this.diskLocation);
75
		directory.mkdirs();
76
		createBackupDirectory();
77
		createRestoredDirectory();
78
		return true;
79
	}
80

  
81
	public boolean createBackupDirectory() {
82
		backupDirectory = new File(this.diskLocation + fileSeparator + "backup");
83
		if (backupDirectory.mkdirs()) {
84
			return true;
85
		}
86
		return false;
87
	}
88

  
89
	public boolean createRestoredDirectory() {
90
		restoredDirectory = new File(this.diskLocation + fileSeparator + "restored");
91
		if (restoredDirectory.mkdirs()) {
92
			return true;
93
		}
94
		return false;
95
	}
96

  
97
	public String getDiskLocation() {
98
		return diskLocation;
99
	}
100

  
101
	public long getSize() {
102
		return size;
103
	}
104

  
105
	public long getOccupiedSpace() {
106
		return folderSize(this.directory);
107
	}
108

  
109
	public long getFreeSpace() {
110
		return size - getOccupiedSpace();
111
	}
112

  
113
	public static long folderSize(File directory) {
114
		long length = 0;
115
		for (File file : directory.listFiles()) {
116
			if (file.isFile())
117
				length += file.length();
118
			else
119
				length += folderSize(file);
120
		}
121
		return length;
122
	}
123

  
124
	public File createFileFolder(String fileId) {
125
		File fileFolder = new File(backupDirectory.getPath() + fileSeparator + fileId);
126
		fileFolder.mkdirs();
127
		return fileFolder;
128
	}
129

  
130
	public boolean storeChunk(Chunk chunk) {
131
		String fileName = chunk.getChunkNo() + "-" + chunk.getRepDegree();
132

  
133
		File folder = createFileFolder(chunk.getFileID());
134

  
135
		File chunkFile = new File(folder.getPath() + fileSeparator + fileName);
136

  
137
		if (chunkFile.exists()) {
138
			return false;
139
		}
140

  
141
		try (FileOutputStream fos = new FileOutputStream(chunkFile)) {
142
			fos.write(chunk.getData());
143
		} catch (Exception e) {
144
			e.printStackTrace();
145
			return false;
146
		}
147

  
148
		return true;
149
	}
150

  
151
	public File[] getFileChunkFiles(String fileId) {
152
		File fileChunkDirectory = getFileChunkDirectory(fileId);
153
		return fileChunkDirectory.listFiles();
154
	}
155

  
156
	public Chunk[] getFileChunks(String fileId) {
157
		File chunkFiles[] = getFileChunkFiles(fileId);
158

  
159
		Chunk[] chunks = new Chunk[chunkFiles.length];
160

  
161
		for (int i = 0; i < chunkFiles.length; i++) {
162
			chunks[i] = parseFileToChunk(fileId, chunkFiles[i]);
163
		}
164

  
165
		return chunks;
166
	}
167

  
168
	public File getChunkFile(String fileId, int chunkId) {
169
		File chunkFiles[] = getFileChunkFiles(fileId);
170
		for (File chunkFile : chunkFiles) {
171
			if (chunkFile.getName().startsWith(chunkId + "-")) {
172
				return chunkFile;
173
			}
174
		}
175
		return null;
176
	}
177

  
178
	public Chunk getChunk(String fileId, int chunkId) {
179
		Chunk[] chunks = getFileChunks(fileId);
180

  
181
		for (Chunk chunk : chunks) {
182
			if (chunk.getChunkNo() == chunkId) {
183
				return chunk;
184
			}
185
		}
186
		return null;
187
	}
188

  
189
	public File getFileChunkDirectory(String fileId) {
190
		return new File(backupDirectory.getPath() + fileSeparator + fileId);
191
	}
192

  
193
	public static Chunk parseFileToChunk(String fileId, File chunkFile) {
194
		String fileName = chunkFile.getName();
195
		String parsedName[] = fileName.split("-");
196

  
197
		int chunkId = Integer.parseInt(parsedName[0]);
198
		int repDegree = Integer.parseInt(parsedName[1]);
199

  
200
		byte[] data = new byte[(int) chunkFile.length()];
201

  
202
		try (FileInputStream fis = new FileInputStream(chunkFile)) {
203
			fis.read(data);
204
		} catch (Exception e) {
205

  
206
		}
207

  
208
		Chunk chunk = new Chunk(fileId, chunkId, repDegree, data);
209

  
210
		return chunk;
211
	}
212

  
213
	public void deleteFileDirectory(String fileId) {
214
		//File fileDir = getFileChunkDirectory(fileId);
215
		/*try {
216
			Utils.deleteDirectoryRecursively(fileDir);
217
		} catch (IOException e) {
218
			e.printStackTrace();
219
			return false;
220
		}
221
		return true;
222
		*/
223
		File fileDir = new File(backupDirectory + "\\" + fileId);
224
		System.out.println("FileDir: \"" + fileDir + "\"");
225
		Utils.deleteDirectoryRecursively(fileDir);
226
	}
227

  
228
	public boolean deleteChunk(String fileId, int chunkId) {
229
		File chunkFile = getChunkFile(fileId, chunkId);
230
		if (!chunkFile.delete()) {
231
			System.out.println("Failed to delete " + chunkFile);
232
			return false;
233
		}
234
		return true;
235
	}
236

  
237
}
src/disk/DiskFailedToInitialize.java
1
package disk;
2

  
3
/**
4
 * DiskFailedToInitialize
5
 */
6
public class DiskFailedToInitialize extends Exception {
7

  
8
	public DiskFailedToInitialize() {
9
		super();
10
	}
11

  
12
}
src/message/InvalidHeaderParameters.java
1
package message;
2

  
3
/**
4
 * InvalidHeaderParameters
5
 */
6
public class InvalidHeaderParameters extends Exception {
7

  
8
	private static final long serialVersionUID = -1129574923771068119L;
9

  
10
		
11
}
src/message/InvalidSenderProtocolVersion.java
1
package message;
2

  
3
public class InvalidSenderProtocolVersion extends Exception {
4

  
5
	private static final long serialVersionUID = -6896672292724504010L;
6

  
7
}
src/message/Message.java
1
package message;
2

  
3
import chunk.Chunk;
4
import peer.Peer;
5

  
6
import java.io.ByteArrayOutputStream;
7
import java.io.IOException;
8

  
9
public class Message {
10

  
11
    public static final int MESSAGE_PACKET_MAX_SIZE = Chunk.CHUNK_MAX_SIZE + MessageHeader.MESSAGE_HEADER_MAX_SIZE;
12

  
13
    private MessageHeader header;
14
    private byte[] body;
15

  
16
    public Message(byte[] data) {
17
        String rawMessage = new String(data);
18
        int index = rawMessage.indexOf(MessageHeader.CRLF) + 4;
19
        byte[] rawHeader = new byte[index+1];
20
        System.arraycopy(data, 0, rawHeader, 0, index - 4);
21
        header = new MessageHeader(new String(rawHeader));
22
        int bodyLength = data.length - index;
23
        body = new byte[bodyLength];
24
        System.arraycopy(data, index, body, 0, bodyLength);
25
    }
26

  
27
    public Message(MessageHeader header, byte[] body) {
28
        this.header = header;
29
        this.body = body;
30
    }
31

  
32
    public byte[] toBytes() throws IOException {
33
        byte[] result;
34
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
35
        bos.write(header.toString().getBytes());
36
        if (body != null)
37
            bos.write(body);
38
        result = bos.toByteArray();
39
        return result;
40
    }
41

  
42
    public MessageHeader getHeader() {
43
        return header;
44
    }
45

  
46
    public byte[] getBody() {
47
        return body;
48
    }
49

  
50
    /*
51
     * public static boolean isValid(String message) { String myString =
52
     * message.substring(0,message.indexOf("\r\n\r\n"));
53
     * 
54
     * return
55
     * myString.matches(".* [0-9].[0-9] [0-9]+ .{32} .{6} [0-9]\r\n\r\n(.*)?"); }
56
     */
57

  
58
    public static Message parsePutChunkMessage(Chunk chunk, Peer peer) {
59
        MessageHeader header = new MessageHeader("PUTCHUNK", peer.getpVersion(), peer.getPeerId(), chunk.getFileID(), chunk.getChunkNo(),
60
                chunk.getRepDegree());
61
        Message message = new Message(header, chunk.getData());
62

  
63
        return message;
64
    }
65

  
66
    public static Message parseStoredMessage(Chunk chunk, Peer peer) {
67
        try {
68
            MessageHeader header = new MessageHeader("STORED", peer.getpVersion(), peer.getPeerId(), chunk.getFileID(), chunk.getChunkNo());
69
            Message message = new Message(header, null);
70
            return message;
71
        } catch (InvalidHeaderParameters e) {
72
            e.printStackTrace();
73
        }
74
        return null;
75
    }
76

  
77
    public static Message parseDeleteMessage(String fileId, Peer peer) {
78
        try {
79
            MessageHeader header = new MessageHeader("DELETE", peer.getpVersion(), peer.getPeerId(), fileId);
80
            Message message = new Message(header, null);
81
            return message;
82
        } catch (InvalidHeaderParameters e) {
83
            e.printStackTrace();
84
        }
85
        return null;
86
    }
87

  
88
    public static Message parseGetChunkMessage(String fileId, int chunkNo, Peer peer) {
89
        try {
90
            MessageHeader header = new MessageHeader("GETCHUNK", peer.getpVersion(), peer.getPeerId(), fileId, chunkNo);
91
            Message message = new Message(header, null);
92
            return message;
93
        } catch (InvalidHeaderParameters e) {
94
            e.printStackTrace();
95
        }
96
        return null;
97
    }
98

  
99
	public static Message parseChunkMessage(Chunk chunk, Peer peer) {
100
		try {
101
            MessageHeader header = new MessageHeader("CHUNK", peer.getpVersion(), peer.getPeerId(), chunk.getFileID(), chunk.getChunkNo());
102
            Message message = new Message(header, chunk.getData());
103
            return message;
104
        } catch (InvalidHeaderParameters e) {
105
            e.printStackTrace();
106
        }
107
        return null;
108
	}
109

  
110
}
src/message/MessageHeader.java
1
package message;
2

  
3
public class MessageHeader {
4

  
5
    public static final String CRLF = "\r\n\r\n";
6
    public static final int MESSAGE_HEADER_MAX_SIZE = 1000;
7

  
8
    private String messageType, version, fileId;
9
    private int senderId, chunkNo, replicaDeg;
10

  
11
    public MessageHeader(String rawHeader) {
12
        System.out.println("Messageheader: " + rawHeader);
13
        String[] sArray = rawHeader.trim().split(" ");
14
        this.messageType = sArray[0];
15
        this.version = sArray[1];
16
        this.senderId = Integer.parseInt(sArray[2]);
17
        this.fileId = sArray[3];
18
        System.out.println("fileid: " + fileId);
19
        if (this.messageType.equals("PUTCHUNK") || this.messageType.equals("STORED")
20
                || this.messageType.equals("GETCHUNK") || this.messageType.equals("REMOVED")
21
                || this.messageType.equals("CHUNK")) {
22
            String cn = sArray[4].replaceAll("[^\\d]", "");
23
            this.chunkNo = Integer.parseInt(cn);
24
        }
25
        if (this.messageType.equals("PUTCHUNK")) {
26
            String rep = sArray[5].replaceAll("[^\\d]", "");
27
            this.replicaDeg = Integer.parseInt(rep);
28
        }
29
    }
30

  
31
    public MessageHeader(String messageType, String version, int senderId, String fileId, int chunkNo)
32
            throws InvalidHeaderParameters {
33
        this.messageType = messageType;
34
        if (this.messageType.equals("PUTCHUNK")) {
35
            throw new InvalidHeaderParameters();
36
        }
37
        this.version = version;
38
        this.senderId = senderId;
39
        this.fileId = fileId;
40
        this.chunkNo = chunkNo;
41
    }
42

  
43
    public MessageHeader(String messageType, String version, int senderId, String fileId, int chunkNo, int replicaDeg) {
44
        this.messageType = messageType;
45
        this.version = version;
46
        this.senderId = senderId;
47
        this.fileId = fileId;
48
        this.chunkNo = chunkNo;
49
        this.replicaDeg = replicaDeg;
50
    }
51

  
52
    public MessageHeader(String messageType, String version, int senderId, String fileId)
53
            throws InvalidHeaderParameters {
54
        this.messageType = messageType;
55
        if (!this.messageType.equals("DELETE")) {
56
            throw new InvalidHeaderParameters();
57
        }
58
        this.version = version;
59
        this.senderId = senderId;
60
        this.fileId = fileId;
61
    }
62

  
63
    public String getMessageType() {
64
        return this.messageType;
65
    }
66

  
67
    public String getVersion() {
68
        return this.version;
69
    }
70

  
71
    public int getSenderId() {
72
        return this.senderId;
73
    }
74

  
75
    public String getFileId() {
76
        return this.fileId;
77
    }
78

  
79
    public int getChunkNo() {
80
        return this.chunkNo;
81
    }
82

  
83
    public int getReplicaDeg() {
84
        return this.replicaDeg;
85
    }
86

  
87
    @Override
88
    public String toString() {
89
        switch (messageType) {
90
        case "GETCHUNK":
91
            return this.messageType + " " + this.version + " " + Integer.toString(this.senderId) + " " + this.fileId
92
                    + " " + Integer.toString(this.chunkNo) + CRLF;
93
        case "PUTCHUNK":
94
            return this.messageType + " " + this.version + " " + Integer.toString(this.senderId) + " " + this.fileId
95
                    + " " + Integer.toString(this.chunkNo) + " " + Integer.toString(this.replicaDeg) + CRLF;
96
        case "STORED":
97
            return this.messageType + " " + this.version + " " + Integer.toString(this.senderId) + " " + this.fileId
98
                    + " " + Integer.toString(this.chunkNo) + CRLF;
99
        case "CHUNK":
100
            return this.messageType + " " + this.version + " " + Integer.toString(this.senderId) + " " + this.fileId
101
                    + " " + Integer.toString(this.chunkNo) + CRLF;
102
        case "DELETE":
103
            return this.messageType + " " + this.version + " " + Integer.toString(this.senderId) + " " + this.fileId
104
                    + CRLF;
105
        case "REMOVED":
106
            return this.messageType + " " + this.version + " " + Integer.toString(this.senderId) + " " + this.fileId
107
                    + " " + Integer.toString(this.chunkNo) + CRLF;
108
        default:
109
            return "";
110

  
111
        }
112
    }
113
}
src/peer/channels/Handler.java
1
package peer.channels;
2

  
3
import java.net.DatagramPacket;
4

  
5
import chunk.Chunk;
6
import disk.ChunkManagement;
7
import peer.Peer;
8
import peer.protocols.backup.Store;
9
import peer.protocols.reclaim.Reclaim;
10
import peer.protocols.restore.GetChunk;
11
import message.*;
12

  
13
public class Handler implements Runnable {
14

  
15
    Peer peer;
16
    DatagramPacket packet;
17
    Message msg;
18
    MessageHeader msgHeader;
19

  
20
    public Handler(Peer peer, DatagramPacket packet) {
21
        this.peer = peer;
22
        this.packet = packet;
23
    }
24

  
25
    public void parsePacket() {
26
        int packetLength = packet.getLength();
27
        byte[] rawData = new byte[packetLength];
28
        byte[] packetData = this.packet.getData();
29
        System.arraycopy(packetData, packet.getOffset(), rawData, 0, packetLength);
30
        this.msg = new Message(rawData);
31
        this.msgHeader = msg.getHeader();
32
    }
33

  
34
    @Override
35
    public void run() {
36

  
37
        parsePacket();
38

  
39
        if (this.peer.getPeerId() != this.msgHeader.getSenderId())
40
            switch (this.msgHeader.getMessageType()) {
41
            case "PUTCHUNK":
42
                handlePUTCHUNK();
43
                break;
44
            case "GETCHUNK":
45
                handleGETCHUNK();
46
                break;
47
            case "CHUNK":
48
                handleCHUNK();
49
                break;
50
            case "DELETE":
51
                handleDELETE();
52
                break;
53
            case "REMOVED":
54
                handleREMOVED();
55
                break;
56
            default:
57
                break;
58
            }
59
    }
60

  
61
    private void handleREMOVED() {
62
        String fileId = this.msgHeader.getFileId();
63
        int chunkNo = this.msgHeader.getChunkNo();
64
        ChunkManagement.getInstance().registerRemoved(fileId, chunkNo);
65

  
66
        Thread t = new Thread(new Reclaim(peer, fileId, chunkNo));
67
        t.start();
68
        try {
69
            t.join();
70
        } catch (InterruptedException e) {
71
            e.printStackTrace();
72
        }
73
    }
74

  
75
    public void handlePUTCHUNK() {
76
        if (this.peer.getDisk().getFreeSpace() < (packet.getLength())) {
77
            System.out.println("Peer " + this.peer.getPeerId() + "- PUTCHUNK request: Not enough space to store chunk");
78
            return;
79
        }
80

  
81
        Chunk chunk = new Chunk(this.msgHeader.getFileId(), this.msgHeader.getChunkNo(), this.msgHeader.getReplicaDeg(),
82
                this.msg.getBody());
83

  
84
        Thread t = new Thread(new Store(peer, chunk));
85
        t.start();
86
        try {
87
            t.join();
88
        } catch (InterruptedException e) {
89
            e.printStackTrace();
90
        }
91

  
92
    }
93

  
94
    public void handleGETCHUNK() {
95
        String fileId = this.msgHeader.getFileId();
96
        int chunkNo = this.msgHeader.getChunkNo();
97
        Thread t = new Thread(new GetChunk(peer, fileId, chunkNo));
98
        t.start();
99
        try {
100
            t.join();
101
        } catch (InterruptedException e) {
102
            e.printStackTrace();
103
        }
104
    }
105

  
106
    public void handleCHUNK() {
107
        Chunk chunk = new Chunk(this.msgHeader.getFileId(), this.msgHeader.getChunkNo(), this.msgHeader.getReplicaDeg(),
108
                this.msg.getBody());
109

  
110
        ChunkManagement.getInstance().addRestoreChunk(chunk);
111
    }
112

  
113
    public void handleDELETE() {
114
        String fileID = msgHeader.getFileId();
115
        this.peer.getDisk().deleteFileDirectory(fileID);
116
        ChunkManagement.getInstance().deleteStores(fileID);
117
    }
118
}
src/peer/channels/Listener.java
1
package peer.channels;
2

  
3
import peer.Peer;
4
import peer.channels.Handler;
5

  
6
import java.io.IOException;
7
import java.net.InetAddress;
8
import java.net.MulticastSocket;
9
import java.net.UnknownHostException;
10

  
11
import message.Message;
12

  
13
import java.net.DatagramPacket;
14

  
15
public class Listener implements Runnable {
16

  
17
    private MulticastSocket socket;
18
    private InetAddress address;
19
    private int port;
20

  
21
    private Peer peer;
22

  
23
    public Listener(Peer peer, String address, int port) {
24
        try {
25
            this.address = InetAddress.getByName(address);
26
        } catch (UnknownHostException e) {
27
            e.printStackTrace();
28
        }
29
        this.port = port;
30
        this.peer = peer;
31
    }
32

  
33
    @Override
34
    public void run() {
35
        try {
36
            this.socket = new MulticastSocket(port);
37
            socket.setTimeToLive(1);
38
            socket.joinGroup(address);
39
        } catch (IOException e) {
40
            e.printStackTrace();
41
            System.exit(1);
42
        }
43

  
44
        while (true) {
45
            byte[] buf = new byte[Message.MESSAGE_PACKET_MAX_SIZE];
46

  
47
            DatagramPacket packet = new DatagramPacket(buf, buf.length);
48
            try {
49
                socket.receive(packet);
50
            } catch (IOException e) {
51
                e.printStackTrace();
52
            }
53
            System.out.println("MC Listener: Packet Received!");
54
            Thread handler = new Thread(new Handler(peer, packet));
55
            handler.start();
56
            try {
57
                handler.join();
58
            } catch (InterruptedException e) {
59
                e.printStackTrace();
60
            }
61
        }
62
        
63
    }
64

  
65
    /**
66
     * @return the socket
67
     */
68
    public MulticastSocket getSocket() {
69
        return socket;
70
    }
71

  
72
    /**
73
     * @return the address
74
     */
75
    public InetAddress getAddress() {
76
        return address;
77
    }
78

  
79
    /**
80
     * @return the port
81
     */
82
    public int getPort() {
83
        return port;
84
    }
85

  
86
    /**
87
     * @return the peer
88
     */
89
    public Peer getPeer() {
90
        return peer;
91
    }
92
}
93

  
src/peer/channels/Sender.java
1
package peer.channels;
2

  
3
import java.net.InetAddress;
4

  
5
/**
6
 * Sender
7
 */
8
public interface Sender {
9

  
10
	public void send(byte[] message);
11

  
12
	public void init(InetAddress address, int port);
13

  
14
	public void destroy();
15
}
src/peer/channels/SenderTCP.java
1
package peer.channels;
2

  
3
import java.io.IOException;
4
import java.net.InetAddress;
5
import java.net.Socket;
6

  
7
/**
8
 * SenderTCP
9
 */
10
public class SenderTCP implements Sender {
11

  
12
	private Socket socket;
13

  
14
	public SenderTCP() {
15
		
16
	}
17

  
18
	@Override
19
	public void send(byte[] message) {
20
		
21
	}
22

  
23
	@Override
24
	public void init(InetAddress address, int port) {
25
		try {
26
			socket = new Socket(address, port);
27
		} catch (IOException e) {
28
			e.printStackTrace();
29
		}
30
	}
31

  
32
	@Override
33
	public void destroy() {
34

  
35
	}
36

  
37
	
38
}
src/peer/channels/SenderUDP.java
1
package peer.channels;
2

  
3
import java.io.IOException;
4
import java.net.DatagramPacket;
5
import java.net.DatagramSocket;
6
import java.net.InetAddress;
7
import java.net.SocketException;
8

  
9
/**
10
 * SenderUDP
11
 */
12
public class SenderUDP implements Sender {
13

  
14
	private DatagramSocket socket;
15

  
16
	public SenderUDP() {
17
	}
18

  
19
	@Override
20
	public void send(byte[] message) {
21
		DatagramPacket packet = new DatagramPacket(message, message.length);
22
		try {
23
			socket.send(packet);
24
		} catch (IOException e) {
25
			e.printStackTrace();
26
		}
27
	}
28

  
29
	@Override
30
	public void init(InetAddress address, int port) {
31
		try {
32
			socket = new DatagramSocket(port, address);
33
		} catch (SocketException e) {
34
			e.printStackTrace();
35
		}
36
	}
37

  
38
	@Override
39
	public void destroy() {
40
		socket.disconnect();
41
	}
42

  
43

  
44

  
45
}
src/peer/protocols/backup/Backup.java
1
package peer.protocols.backup;
2

  
3
import java.io.File;
4

  
5
import chunk.Chunk;
6
import peer.Peer;
7

  
8
/**
9
 * Backup
10
 */
11
public class Backup implements Runnable {
12

  
13
	private Peer peer;
14
	private File file;
15
	private int repDegree;
16

  
17
	public Backup(Peer peer, String path, int repDegree) {
18
		file = new 	File(path);
19
		this.peer = peer;
20
		this.repDegree = repDegree;
21
	}
22

  
23
	public void backupFile() {
24
		Chunk[] chunks = Chunk.splitFile(file, repDegree);
25
		for (int i = 0;i<chunks.length;i++){
26
			BackupChunk backupChunk = new BackupChunk(peer, chunks[i]);
27
			Thread bThread = new Thread(backupChunk);
28
			bThread.start();
29
		}
30
	}
31

  
32
	@Override
33
	public void run() {
34
		backupFile();
35
	}
36
}
src/peer/protocols/backup/BackupChunk.java
1
package peer.protocols.backup;
2

  
3
import java.io.IOException;
4

  
5
import chunk.Chunk;
6
import disk.ChunkManagement;
7
import message.Message;
8
import peer.Peer;
9

  
10
/**
11
 * BackupChunk
12
 */
13
public class BackupChunk implements Runnable {
14

  
15
	public static final int backupTries = 10;
16

  
17
	private Chunk chunk;
18
	private Peer peer;
19

  
20
	public BackupChunk(Peer peer, Chunk chunk) {
21
		this.chunk = chunk;
22
		this.peer = peer;
23
	}
24

  
25
	public void sendPutChunk() {
26
		Message message = Message.parsePutChunkMessage(chunk, peer);
27
		try {
28
			peer.sendToMdb(message);
29
		} catch (IOException e) {
30
			e.printStackTrace();
31
		}
32
	}
33

  
34
	public boolean backupChunk() {
35
		sendPutChunk();
36
		try {
37
			Thread.sleep(400);
38
		} catch (InterruptedException e) {
39
			e.printStackTrace();
40
		}
41
		if (ChunkManagement.getInstance().getStores(chunk.getFileID(), chunk.getChunkNo()) >= chunk.getRepDegree()) {
42
			return true;
43
		}
44
		return false;
45
	}
46

  
47
	@Override
48
	public void run() {
49
		try {
50
			Thread.sleep(400 * chunk.getChunkNo());
51
		} catch (InterruptedException e) {
52
			// TODO Auto-generated catch block
53
			e.printStackTrace();
54
		}
55
		boolean done = false;
56
		int tries = 0;
57
		while(!done) {
58
			done = backupChunk();
59
			if (!done) {
60
				tries++;
61
				if (tries > backupTries) {
62
					break;
63
				}
64
			}
65
		}
66
	}
67
}
src/peer/protocols/backup/Store.java
1
package peer.protocols.backup;
2

  
3
import java.io.IOException;
4

  
5
import chunk.Chunk;
6
import disk.ChunkManagement;
7
import message.Message;
8
import peer.Peer;
9

  
10
/**
11
 * Store
12
 */
13
public class Store implements Runnable {
14

  
15
	private Peer peer;
16
	private Chunk chunk;
17

  
18
	public Store(Peer peer, Chunk chunk) {
19
		this.peer = peer;
20
		this.chunk = chunk;
21
	}
22

  
23
	public void sendStored() {
24
		Message storedMessage = Message.parseStoredMessage(chunk, peer);
25
		try {
26
			peer.sendToMc(storedMessage);
27
		} catch (IOException e) {
28
			e.printStackTrace();
29
		}
30
	}
31

  
32
	public boolean storeChunk() {
33
		try {
34
			Thread.sleep((long) (Math.random() * 400 + 1));
35
		} catch (InterruptedException e) {
36
			e.printStackTrace();
37
		}
38
		if (ChunkManagement.getInstance().getStores(chunk.getFileID(), chunk.getChunkNo()) < chunk.getRepDegree()) {
39
			if (peer.getDisk().storeChunk(chunk)) {
40
				sendStored();
41
				return true;
42
			}
43
		}
44
		return false;
45
	}
46

  
47
	@Override
48
	public void run() {
49
		storeChunk();
50
	}
51

  
52
}
src/peer/protocols/delete/Delete.java
1
package peer.protocols.delete;
2

  
3
import java.io.File;
4
import java.io.IOException;
5

  
6
import chunk.Chunk;
7
import message.Message;
8
import peer.Peer;
9

  
10
/**
11
 * Delete
12
 */
13
public class Delete implements Runnable {
14

  
15
	private Peer peer;
16
	private String fileId;
17

  
18
	public Delete(Peer peer, String fileId) {
19
		this.peer = peer;
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff