Project

General

Profile

Statistics
| Revision:

root / src / chord / ChordManager.java

History | View | Annotate | Download (6.19 KB)

1
package chord;
2

    
3
import files.FileHandler;
4
import messages.LookupMessage;
5
import messages.Message;
6
import messages.SucessorMessage;
7
import peer.Peer;
8

    
9
import java.math.BigInteger;
10
import java.net.InetAddress;
11
import java.net.UnknownHostException;
12
import java.security.MessageDigest;
13
import java.security.NoSuchAlgorithmException;
14
import java.util.ArrayList;
15
import java.util.Arrays;
16
import java.util.concurrent.TimeUnit;
17

    
18
public class ChordManager implements Runnable{
19
    private final static int M = 8; //bits
20
    public static BigInteger peerHash;
21
    private static ArrayList<ConnectionInfo> fingerTable = new ArrayList<>(M);
22
    public static ConnectionInfo predecessor = null;
23

    
24
    public ChordManager(){
25
        try {
26
            setChord();
27
        } catch (UnknownHostException e) {
28
            e.printStackTrace();
29
        }
30
    }
31

    
32
    public static ConnectionInfo getPredecessor() {
33
        return predecessor;
34
    }
35

    
36
    public static ArrayList<ConnectionInfo> getFingerTable() {
37
        return fingerTable;
38
    }
39

    
40
    public static int getM(){ return M;}
41

    
42
    /**
43
     * Calls functions to create hash and fill finger table
44
     */
45
    private void setChord() throws UnknownHostException {
46
        String [] params = new String[] {String.valueOf(Peer.port), InetAddress.getLocalHost().getHostAddress()};
47
        ChordManager.peerHash = encrypt(params);
48
        System.out.println("Peer hash = " + peerHash + "\n");
49

    
50
        FileHandler.createDir("backup");
51
        FileHandler.createDir("restored");
52

    
53
        initFingerTable();
54
        printFingerTable();
55

    
56
        FixFingers ff = new FixFingers();
57
        Peer.executor.scheduleAtFixedRate(ff,0,500, TimeUnit.MILLISECONDS);
58
    }
59

    
60
    private void initFingerTable() throws UnknownHostException {
61
        fingerTable.add(new ConnectionInfo(peerHash, InetAddress.getLocalHost().getHostAddress(), Peer.port));
62
    }
63

    
64
    public static void printFingerTable() {
65
        System.out.println("FingerTable");
66

    
67
        for (int i = 0; i < fingerTable.size(); i++)
68
        {
69
            ConnectionInfo finger = fingerTable.get(i);
70
            System.out.println(i + " : " + finger.getHashedKey() + " : " + finger.getIp() + " : " + finger.getPort());
71
        }
72

    
73
    }
74

    
75
    private static long convertToDec(String hex)
76
    {
77
        String digits = "0123456789ABCDEF";
78
        hex = hex.toUpperCase();
79
        long val = 0;
80
        for (int i = 0; i < hex.length(); i++) {
81
            char c = hex.charAt(i);
82
            int d = digits.indexOf(c);
83
            val = 16 * val + d;
84
        }
85
        return val;
86
    }
87
    /**
88
     * Creates hash with size hashSize from server's port
89
     *
90
     * @param params List of parameters to be used for hashing
91
     * @return hash
92
     */
93
    public static BigInteger encrypt(String[] params)
94
    {
95
        String originalString = "";
96
        MessageDigest md = null;
97
        StringBuilder result = new StringBuilder();
98

    
99
        try {
100
            md = MessageDigest.getInstance("SHA-256");
101
        } catch (NoSuchAlgorithmException e) {
102
            System.err.println("Error getting instance of MessageDigest");
103
            System.exit(1);
104
        }
105

    
106
        for(int i = 0; i < params.length; i++) {
107
            originalString += params[i];
108

    
109
            if(i < params.length - 1)
110
                originalString += " ";
111
        }
112

    
113
        md.update(originalString.getBytes());
114
        byte[] hashBytes = md.digest();
115

    
116
        byte[] trimmedHashBytes = Arrays.copyOf(hashBytes, M/8);
117

    
118
        for (byte byt : trimmedHashBytes)
119
            result.append(Integer.toString((byt & 0xff) + 0x100, 16).substring(1));
120

    
121
        long resultLong = convertToDec(result.toString());
122

    
123
        return BigInteger.valueOf(resultLong);
124
    }
125

    
126
    /**
127
     * Calculates the key of the next entry of the fingertable - ( hash + 2^index) mod 2^m
128
     *
129
     * @param hash peer's hash
130
     * @param index finger table's index to be filled
131
     * @param m hash size (bits)
132
     * @return next key's hash
133
     */
134
    public static String calculateNextKey(BigInteger hash, int index, int m)
135
    {
136
        BigInteger add = new BigInteger(String.valueOf((int) Math.pow(2, index)));
137
        BigInteger mod =  new BigInteger(String.valueOf((int) Math.pow(2, m)));
138

    
139
        BigInteger res = hash.add(add).mod(mod);
140
        return res.toString();
141
    }
142

    
143
    public static Message searchSuccessor2(ConnectionInfo senderInfo)
144
    {
145
        BigInteger successorKey = fingerTable.get(0).getHashedKey();
146

    
147
        if(numberInInterval(peerHash, successorKey, senderInfo.getHashedKey()))
148
            return new SucessorMessage(senderInfo.getHashedKey().toString(),new ConnectionInfo(fingerTable.get(0).getHashedKey(),fingerTable.get(0).getIp(),fingerTable.get(0).getPort()),senderInfo.getIp(),senderInfo.getPort());
149

    
150
        else {
151
            for(int i = fingerTable.size()-1; i >= 0; i--){
152

    
153
                if(fingerTable.get(i).getHashedKey() == null)
154
                    continue;
155

    
156
                if(numberInInterval(peerHash, senderInfo.getHashedKey(), fingerTable.get(i).getHashedKey())) {
157
                    if(fingerTable.get(i).getHashedKey().equals(ChordManager.peerHash))
158
                        continue;
159

    
160
                    return new LookupMessage(senderInfo,fingerTable.get(i).getIp(), fingerTable.get(i).getPort());
161
                }
162
            }
163

    
164
            try {
165
                return new SucessorMessage(senderInfo.getHashedKey().toString(),new ConnectionInfo(ChordManager.peerHash, InetAddress.getLocalHost().getHostAddress(), Peer.port),senderInfo.getIp(),senderInfo.getPort());
166
            } catch (UnknownHostException e) {
167
                e.printStackTrace();
168
            }
169
        }
170

    
171
        return null;
172
    }
173

    
174
    public static boolean numberInInterval(BigInteger begin, BigInteger end, BigInteger value)
175
    {
176
        boolean result = false;
177
        int cmp = begin.compareTo(end);
178

    
179
        if(cmp == 1) {
180
            if (value.compareTo(begin) == 1 || value.compareTo(end) == -1)
181
                result = true;
182
        }
183

    
184
        else if (cmp == -1) {
185
            if (value.compareTo(begin) == 1 && value.compareTo(end) == -1)
186
                result = true;
187
        }
188

    
189
        else {
190
            if (value.compareTo(begin) == 0)
191
                result = true;
192
        }
193

    
194
        return result;
195
    }
196

    
197
    @Override
198
    public void run() {
199

    
200
    }
201
}