Project

General

Profile

Revision 3

Update

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
}
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 java.util.Base64;
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 Base64.getEncoder().withoutPadding().encodeToString(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
}
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
    }

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 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
}
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

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

  
16
	private static ChunkManagement chunkManagementInstance = null;
17

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

  
20
	private BlockingQueue<Chunk> restoreChunks;
21

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

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

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

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

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

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

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

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

  
85
}
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
}
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 + fileSeparator + 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

  
1
package disk;
2

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

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

  
12 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
		
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 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
}
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 {
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff