├── ic_launcher-web.png
├── libs
└── android-support-v4.jar
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ └── ic_launcher.png
├── drawable-xxhdpi
│ └── ic_launcher.png
├── values
│ ├── strings.xml
│ ├── dimens.xml
│ └── styles.xml
├── values-sw600dp
│ └── dimens.xml
├── menu
│ └── simple_dynamo.xml
├── values-sw720dp-land
│ └── dimens.xml
├── values-v11
│ └── styles.xml
├── values-v14
│ └── styles.xml
└── layout
│ └── activity_simple_dynamo.xml
├── .settings
└── org.eclipse.jdt.core.prefs
├── gen
└── edu
│ └── buffalo
│ └── cse
│ └── cse486586
│ └── simpledynamo
│ ├── BuildConfig.java
│ └── R.java
├── README.md
├── src
└── edu
│ └── buffalo
│ └── cse
│ └── cse486586
│ └── simpledynamo
│ ├── VersionObject.java
│ ├── SimpleDynamoActivity.java
│ ├── MessageBody.java
│ └── SimpleDynamoProvider.java
├── .classpath
├── project.properties
├── proguard-project.txt
├── .project
└── AndroidManifest.xml
/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/router/SimpleDynamo/master/ic_launcher-web.png
--------------------------------------------------------------------------------
/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/router/SimpleDynamo/master/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/router/SimpleDynamo/master/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/router/SimpleDynamo/master/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/router/SimpleDynamo/master/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/router/SimpleDynamo/master/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SimpleDynamo
5 | Settings
6 |
7 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
3 | org.eclipse.jdt.core.compiler.compliance=1.6
4 | org.eclipse.jdt.core.compiler.source=1.6
5 |
--------------------------------------------------------------------------------
/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
--------------------------------------------------------------------------------
/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/gen/edu/buffalo/cse/cse486586/simpledynamo/BuildConfig.java:
--------------------------------------------------------------------------------
1 | /** Automatically generated file. DO NOT MODIFY */
2 | package edu.buffalo.cse.cse486586.simpledynamo;
3 |
4 | public final class BuildConfig {
5 | public final static boolean DEBUG = true;
6 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SimpleDynamo
2 | ============
3 |
4 | A distributed key-value store on the same lines as Amazon Dynamo, following chord protocol. It has functionalities such as concurrent updates, deletes and look-ups using quorum replication. Failures and consistency issues are managed by object versioning.
5 |
--------------------------------------------------------------------------------
/res/menu/simple_dynamo.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/res/values-sw720dp-land/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | 128dp
8 |
9 |
--------------------------------------------------------------------------------
/src/edu/buffalo/cse/cse486586/simpledynamo/VersionObject.java:
--------------------------------------------------------------------------------
1 | package edu.buffalo.cse.cse486586.simpledynamo;
2 |
3 | import java.io.Serializable;
4 |
5 | public class VersionObject implements Serializable {
6 | public int versionNumber;
7 | public String value;
8 | public VersionObject(int number,String str)
9 | {
10 | versionNumber=number;
11 | value=str;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-19
15 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/src/edu/buffalo/cse/cse486586/simpledynamo/SimpleDynamoActivity.java:
--------------------------------------------------------------------------------
1 | package edu.buffalo.cse.cse486586.simpledynamo;
2 |
3 | import android.os.Bundle;
4 | import android.app.Activity;
5 | import android.text.method.ScrollingMovementMethod;
6 | import android.view.Menu;
7 | import android.widget.TextView;
8 |
9 | public class SimpleDynamoActivity extends Activity {
10 |
11 | @Override
12 | protected void onCreate(Bundle savedInstanceState) {
13 | super.onCreate(savedInstanceState);
14 | setContentView(R.layout.activity_simple_dynamo);
15 |
16 | TextView tv = (TextView) findViewById(R.id.textView1);
17 | tv.setMovementMethod(new ScrollingMovementMethod());
18 | }
19 |
20 | @Override
21 | public boolean onCreateOptionsMenu(Menu menu) {
22 | // Inflate the menu; this adds items to the action bar if it is present.
23 | getMenuInflater().inflate(R.menu.simple_dynamo, menu);
24 | return true;
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | SimpleDynamo
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/res/layout/activity_simple_dynamo.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
23 |
--------------------------------------------------------------------------------
/src/edu/buffalo/cse/cse486586/simpledynamo/MessageBody.java:
--------------------------------------------------------------------------------
1 | package edu.buffalo.cse.cse486586.simpledynamo;
2 |
3 | import java.io.Serializable;
4 | import java.util.ArrayList;
5 | import java.util.Arrays;
6 | import java.util.HashMap;
7 | import java.util.TreeSet;
8 |
9 | public class MessageBody implements Serializable{
10 |
11 | public String messageType;
12 | public ArrayList parameters;
13 | public HashMap keyValuePairs;
14 | public HashMap keyVersionPairs;
15 | public ArrayList nodeSet;
16 | public String sender;
17 |
18 | public MessageBody(String messageType,ArrayList parameters, HashMapvalues, HashMap versions)
19 | {
20 | this.messageType=messageType;
21 | this.parameters=parameters;
22 | if(versions==null)
23 | versions=new HashMap();
24 | if(values==null)
25 | values=new HashMap();
26 |
27 | this.keyValuePairs=values;
28 | this.keyVersionPairs=versions;
29 |
30 |
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/gen/edu/buffalo/cse/cse486586/simpledynamo/R.java:
--------------------------------------------------------------------------------
1 | /* AUTO-GENERATED FILE. DO NOT MODIFY.
2 | *
3 | * This class was automatically generated by the
4 | * aapt tool from the resource data it found. It
5 | * should not be modified by hand.
6 | */
7 |
8 | package edu.buffalo.cse.cse486586.simpledynamo;
9 |
10 | public final class R {
11 | public static final class attr {
12 | }
13 | public static final class dimen {
14 | /** Default screen margins, per the Android Design guidelines.
15 |
16 | Customize dimensions originally defined in res/values/dimens.xml (such as
17 | screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
18 |
19 | */
20 | public static final int activity_horizontal_margin=0x7f040000;
21 | public static final int activity_vertical_margin=0x7f040001;
22 | }
23 | public static final class drawable {
24 | public static final int ic_launcher=0x7f020000;
25 | }
26 | public static final class id {
27 | public static final int action_settings=0x7f080001;
28 | public static final int textView1=0x7f080000;
29 | }
30 | public static final class layout {
31 | public static final int activity_simple_dynamo=0x7f030000;
32 | }
33 | public static final class menu {
34 | public static final int simple_dynamo=0x7f070000;
35 | }
36 | public static final class string {
37 | public static final int action_settings=0x7f050001;
38 | public static final int app_name=0x7f050000;
39 | }
40 | public static final class style {
41 | /**
42 | Base application theme, dependent on API level. This theme is replaced
43 | by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
44 |
45 |
46 | Theme customizations available in newer API levels can go in
47 | res/values-vXX/styles.xml, while customizations related to
48 | backward-compatibility can go here.
49 |
50 |
51 | Base application theme for API 11+. This theme completely replaces
52 | AppBaseTheme from res/values/styles.xml on API 11+ devices.
53 |
54 | API 11 theme customizations can go here.
55 |
56 | Base application theme for API 14+. This theme completely replaces
57 | AppBaseTheme from BOTH res/values/styles.xml and
58 | res/values-v11/styles.xml on API 14+ devices.
59 |
60 | API 14 theme customizations can go here.
61 | */
62 | public static final int AppBaseTheme=0x7f060000;
63 | /** Application theme.
64 | All customizations that are NOT specific to a particular API-level can go here.
65 | */
66 | public static final int AppTheme=0x7f060001;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/edu/buffalo/cse/cse486586/simpledynamo/SimpleDynamoProvider.java:
--------------------------------------------------------------------------------
1 | package edu.buffalo.cse.cse486586.simpledynamo;
2 |
3 | import java.io.BufferedInputStream;
4 | import java.io.BufferedReader;
5 | import java.io.BufferedWriter;
6 | import java.io.File;
7 | import java.io.FileInputStream;
8 | import java.io.FileOutputStream;
9 | import java.io.FileWriter;
10 | import java.io.IOException;
11 | import java.io.InputStreamReader;
12 | import java.io.ObjectInputStream;
13 | import java.io.ObjectOutputStream;
14 | import java.net.InetSocketAddress;
15 | import java.net.ServerSocket;
16 | import java.net.Socket;
17 | import java.net.SocketAddress;
18 | import java.net.UnknownHostException;
19 | import java.security.MessageDigest;
20 | import java.security.NoSuchAlgorithmException;
21 | import java.util.ArrayList;
22 | import java.util.Collections;
23 | import java.util.Comparator;
24 | import java.util.Formatter;
25 | import java.util.HashMap;
26 | import java.util.Iterator;
27 | import java.util.List;
28 | import java.util.Map;
29 | import java.util.TreeSet;
30 | import java.util.concurrent.Executors;
31 |
32 | import android.content.ContentProvider;
33 | import android.content.ContentValues;
34 | import android.content.Context;
35 | import android.database.Cursor;
36 | import android.database.MatrixCursor;
37 | import android.net.Uri;
38 | import android.os.AsyncTask;
39 | import android.telephony.TelephonyManager;
40 | import android.util.Log;
41 |
42 | public class SimpleDynamoProvider extends ContentProvider {
43 |
44 | //Members
45 | private String myPortStr;
46 | private int myPort;
47 | public int AVDNumber;
48 | private String currentNodeHash;
49 | public final int SERVER_PORT=10000;
50 | public final String[] ports={"11108","11112","11116","11120","11124"};
51 | public final String[] nodeSet={"5562","5556","5554","5558","5560"};
52 | public final int nodeCount=5;
53 | private static final String AUTHORITY="edu.buffalo.cse.cse486_586.simpledht.provider";
54 | public static Uri CONTENT_URI=Uri.parse("content://edu.buffalo.cse.cse486_586.simpledht.provider");
55 |
56 | //Members for chord ring information
57 | private String predecessorHash,successorHash;
58 | int predecessor, successor;
59 | //MessageBody incomingMessage;
60 | public String TAG="SimpleDynamo";
61 |
62 | String largestInRing, smallestInRing;
63 | String RequestingAVD; // requesting avd
64 |
65 | MatrixCursor outputCursor;
66 | HashMap outputMap;
67 | int finalDeleteResult;
68 |
69 | //List pendingInserts;
70 | Map pendingInserts;
71 | Map pendingQueries;
72 | Map pendingDeletes;
73 |
74 | Map versions;
75 |
76 | // boolean isStillSearching=false;
77 | //boolean isStillDeleting=false;
78 | boolean isDataSetInitialized=false;
79 | //String keySearched, valueObtained;
80 | boolean firstTime;
81 | int recoveryStatus;
82 | boolean isNeighbourActive;
83 | int insertc,insertr;
84 | int queryc,queryr;
85 | boolean hasCopied;
86 | public int delete(String selection)
87 | {
88 | //while(recoveryStatus>0);
89 | File f=new File(this.getContext().getFilesDir().getAbsoluteFile(),selection);
90 | f.delete();
91 |
92 | return 1;
93 | }
94 | @Override
95 | public int delete(Uri uri, String selection, String[] selectionArgs) {
96 | // TODO Auto-generated method stub
97 | finalDeleteResult=0;
98 | //while(recoveryStatus>0);
99 | boolean returnStatus=true;
100 | if(selection.equals("@"))
101 | {
102 | File[] files=this.getContext().getFilesDir().listFiles();
103 | for(int i=0;iparam=new ArrayList();
131 | param.add("*");
132 | param.add(String.valueOf(AVDNumber));
133 | param.add(String.valueOf(returnStatus==true?1:0));
134 | new ClientThread(new MessageBody("DeleteKey",param,null,null),String.valueOf(successor*2)).start();
135 | //isStillDeleting=true;
136 |
137 | //pendingDeletes.add("*");
138 | handleRequest("*", "add",pendingDeletes);
139 | while(pendingDeletes.containsKey("*"));
140 | }
141 | else //single node , return result
142 | {
143 | return (returnStatus==true)?0:1;
144 | }
145 |
146 | }
147 | else // single file
148 | {
149 |
150 | int coordinator=Integer.parseInt(nodeForKey(selection));
151 |
152 | if(coordinator==AVDNumber)
153 | {
154 | File f=new File(this.getContext().getFilesDir().getAbsoluteFile(),selection);
155 | f.delete();
156 |
157 | }
158 | else
159 | {
160 | ArrayListparam=new ArrayList();
161 | param.add(selection);
162 | param.add(String.valueOf(AVDNumber));
163 | new ClientThread(new MessageBody("DeleteKey",param,null,null),String.valueOf(coordinator*2)).start();
164 | //isStillDeleting=true;
165 |
166 | handleRequest(selection,"add", pendingDeletes);
167 | }
168 |
169 | ArrayListparam=new ArrayList();
170 | param.add(selection);
171 | param.add(String.valueOf(AVDNumber));
172 |
173 | String succ=successorForNode(String.valueOf(coordinator));
174 | //logToFile("Sending delete "+selection+" to replica: "+succ);
175 | int destPort=2*Integer.parseInt(succ);
176 | MessageBody deleteMessage=new MessageBody("DeleteKey", param, null,null);
177 | //SimpleDynamoProvider.this.logToFile(deleteMessage);
178 | new ClientThread(deleteMessage, String.valueOf(destPort)).start();
179 | String key=new String(selection);
180 | handleRequest(key, "add", pendingDeletes);
181 |
182 | succ=successorForNode(succ);
183 | //logToFile("Sending "+selection+" to replica: "+succ);
184 | destPort=2*Integer.parseInt(succ);
185 | deleteMessage=new MessageBody("DeleteKey", param, null,null);
186 | //SimpleDynamoProvider.this.logToFile(deleteMessage);
187 | new ClientThread(deleteMessage, String.valueOf(destPort)).start();
188 | handleRequest(key, "add", pendingDeletes);
189 |
190 | while(pendingDeletes.containsKey(selection) && pendingDeletes.get(selection)>1);
191 | logToFile("RETURNING FROM DELETE"+selection);
192 | }
193 |
194 |
195 | return 1;//finalDeleteResult;
196 | }
197 |
198 | @Override
199 | public String getType(Uri uri) {
200 | // TODO Auto-generated method stub
201 | return null;
202 | }
203 |
204 | public void insert(String key,VersionObject obj)
205 | {
206 | try
207 | {
208 | File f=new File(this.getContext().getFilesDir().getAbsoluteFile(),key);
209 | String value="";
210 | if(f.exists())
211 | {
212 | FileInputStream inputStream=new FileInputStream(f);
213 |
214 | BufferedReader buf= new BufferedReader(new InputStreamReader(new BufferedInputStream(inputStream)));
215 | String line="";
216 | while((line=buf.readLine())!=null)
217 | value+=line;
218 |
219 | buf.close();
220 | inputStream.close();
221 | value=value.trim();
222 |
223 | }
224 | int versionNumber=obj.versionNumber;
225 | String finalValue=obj.value;
226 | if(value.length()>0)
227 | {
228 | String[] comp=value.split(":");
229 | versionNumber+=Integer.parseInt(comp[0]);
230 | finalValue=comp[1];
231 | }
232 |
233 | String writevalue=String.valueOf(versionNumber)+":"+finalValue;
234 | FileOutputStream outputStream = new FileOutputStream(f);//openFileOutput(filename, Context.MODE_PRIVATE);
235 | outputStream.write(writevalue.getBytes());
236 | outputStream.close();
237 | }
238 | catch(Exception e)
239 | {
240 | e.printStackTrace();
241 | }
242 | }
243 | @Override
244 | public Uri insert(Uri uri, ContentValues values) {
245 |
246 | // TODO Auto-generated method stub
247 | //while(recoveryStatus>0);
248 |
249 | logToFile("INSERTCALLED:"+String.valueOf(++insertc));
250 | Log.v("insert", values.toString());
251 | String filename=values.getAsString("key");
252 | String value=values.getAsString("value");
253 | int repCount=2; // for first time call the value should be 2
254 | if(values.containsKey("repCount"))
255 | repCount=Integer.parseInt(values.getAsString("repCount"));
256 |
257 | if(firstTime)
258 | {
259 | firstTime=false;
260 | String logStr="predhash: "+predecessorHash+" succHash: "+successorHash+"largest: "+largestInRing+"smallest: "+smallestInRing+" pred:"+String.valueOf(predecessor)+" succ:"+String.valueOf(successor);
261 | SimpleDynamoProvider.this.logToFile(logStr);
262 | }
263 |
264 | CONTENT_URI=uri;
265 |
266 | String coordinator=nodeForKey(filename);
267 |
268 | logToFile("key: "+filename+" node:"+coordinator+"repcount"+String.valueOf(repCount));
269 | // if(nodeForKey.equals(String.valueOf(AVDNumber))|| repCount<2)
270 | // {
271 | // try
272 | // {
273 | // File f=new File(this.getContext().getFilesDir().getAbsoluteFile(),filename);
274 | //
275 | // if(!f.exists())
276 | // f.createNewFile();
277 | // FileOutputStream outputStream = new FileOutputStream(f);//openFileOutput(filename, Context.MODE_PRIVATE);
278 | // outputStream.write(value.getBytes());
279 | // outputStream.close();
280 | // }
281 | // catch (Exception e)
282 | // {
283 | // logToFile("Unable to write\n");
284 | // Log.e("SimpleDhtActivity", "File write failed");
285 | // }
286 | //
287 | // if(repCount>0)
288 | // {
289 | // logToFile("Sending "+filename+" to next: "+String.valueOf(successor));
290 | // ArrayList param=new ArrayList();
291 | // param.add(filename);
292 | // param.add(value);
293 | // param.add(String.valueOf(repCount-1));
294 | // Log.d(TAG,"key "+filename+ "going over the n/w" );
295 | // int succPort=2*successor;
296 | //
297 | // MessageBody insertMessage=new MessageBody("InsertKeyReplica", param, null);
298 | // SimpleDynamoProvider.this.logToFile(insertMessage);
299 | // new ClientThread(insertMessage, String.valueOf(succPort)).start();
300 | // //if(pendingInserts.contains(filename)) // case of original sender being a replica
301 | // //pendingInserts.remove(filename);
302 | // }
303 | //
304 | //
305 | // }
306 | // else //send message to the key's coordinator
307 | // {
308 | // logToFile("Sending "+filename+" to coord: "+nodeForKey);
309 | // ArrayList param=new ArrayList();
310 | // param.add(String.valueOf(AVDNumber));
311 | // param.add(filename);
312 | // param.add(value);
313 | // param.add(String.valueOf(repCount));
314 | // Log.d(TAG,"key "+filename+ "going over the n/w" );
315 | // int succPort=2*Integer.parseInt(nodeForKey);
316 | //
317 | // logToFile("sending to port "+String.valueOf(succPort)+"----->");
318 | // MessageBody insertMessage=new MessageBody("InsertKeyCoord", param, null);
319 | // SimpleDynamoProvider.this.logToFile(insertMessage);
320 | // new ClientThread(insertMessage, String.valueOf(succPort)).start();
321 | // String key=new String(filename);
322 | // pendingInserts.add(key);
323 | //
324 | //
325 | // while(pendingInserts.containsKey(key));
326 | // }
327 |
328 | if(coordinator.equals(String.valueOf(AVDNumber))|| repCount==0) //current node is the coordinator or it is one of the replicas / coord that needs to be written
329 | {
330 | // Check for version, increase by 1 and update to file
331 | try
332 | {
333 | File f=new File(this.getContext().getFilesDir().getAbsoluteFile(),filename);
334 | int versionNumber=-1;
335 | if(!f.exists())
336 | {
337 | f.createNewFile();
338 | versionNumber=0;
339 | }
340 | else
341 | {
342 | //get old version
343 |
344 | FileInputStream inputStream=new FileInputStream(f);
345 | BufferedReader buf= new BufferedReader(new InputStreamReader(new BufferedInputStream(inputStream)));
346 | String valueread="",line="";
347 | while((line=buf.readLine())!=null)
348 | valueread+=line;
349 |
350 | buf.close();
351 |
352 | valueread=valueread.trim();
353 | String[] comp=valueread.split(":");
354 | versionNumber=Integer.parseInt(comp[0]);
355 | inputStream.close();
356 | }
357 |
358 | versionNumber++;
359 | String writevalue=String.valueOf(versionNumber)+":"+value;
360 |
361 | FileOutputStream outputStream = new FileOutputStream(f);//openFileOutput(filename, Context.MODE_PRIVATE);
362 | outputStream.write(writevalue.getBytes());
363 | outputStream.close();
364 |
365 | }
366 | catch (Exception e)
367 | {
368 | logToFile("Unable to write\n");
369 | Log.e("SimpleDhtActivity", "File write failed");
370 | }
371 |
372 | }
373 | else // send message to coord
374 | {
375 | logToFile("Sending "+filename+" to coord: "+coordinator);
376 | ArrayList param=new ArrayList();
377 | param.add(String.valueOf(AVDNumber));
378 | param.add(filename);
379 | param.add(value);
380 | param.add("0");
381 | Log.d(TAG,"key "+filename+ "going over the n/w" );
382 | int coordPort=2*Integer.parseInt(coordinator);
383 |
384 | //logToFile("sending to port "+String.valueOf(coordPort)+"----->");
385 | MessageBody insertMessage=new MessageBody("InsertKey", param, null,null);
386 | //SimpleDynamoProvider.this.logToFile(insertMessage);
387 | new ClientThread(insertMessage, String.valueOf(coordPort)).start();
388 | String key=new String(filename);
389 | //pendingInserts.add(key);
390 | handleRequest(key, "add", pendingInserts);
391 |
392 | }
393 |
394 | if(repCount==2) // for the original caller only
395 | {
396 | //send to the 2 replicas
397 |
398 | ArrayList param=new ArrayList();
399 | param.add(String.valueOf(AVDNumber));
400 | param.add(filename);
401 | param.add(value);
402 | param.add("0");
403 |
404 |
405 | String succ=successorForNode(coordinator);
406 | logToFile("Sending "+filename+" to replica: "+succ);
407 | int destPort=2*Integer.parseInt(succ);
408 | MessageBody insertMessage=new MessageBody("InsertKey", param, null,null);
409 | //SimpleDynamoProvider.this.logToFile(insertMessage);
410 | new ClientThread(insertMessage, String.valueOf(destPort)).start();
411 | String key=new String(filename);
412 | handleRequest(key, "add", pendingInserts);
413 |
414 | succ=successorForNode(succ);
415 | logToFile("Sending "+filename+" to replica: "+succ);
416 | destPort=2*Integer.parseInt(succ);
417 | insertMessage=new MessageBody("InsertKey", param, null,null);
418 | //SimpleDynamoProvider.this.logToFile(insertMessage);
419 | new ClientThread(insertMessage, String.valueOf(destPort)).start();
420 | handleRequest(key, "add", pendingInserts);
421 |
422 | while(pendingInserts.containsKey(key) && pendingInserts.get(key)>1);
423 |
424 | }
425 |
426 | logToFile("INSERT RETURNED:"+String.valueOf(++insertr));
427 | logToFile("Insert returning "+filename);
428 |
429 |
430 |
431 | return uri;
432 | }
433 |
434 | @Override
435 | public boolean onCreate() {
436 | // TODO Auto-generated method stub
437 |
438 | //Flush the contents of the persistent storage . The following code needs to be commented since on relaunch after failure, we need the old data to build the merkel trees to compare.
439 | insertc=insertr=0;
440 | queryc=queryr=0;
441 | String[] cols={"key","value"};
442 | outputCursor=new MatrixCursor(cols);
443 | File rootDir=this.getContext().getFilesDir();
444 | if(rootDir.isDirectory()) {
445 | String[] children = rootDir.list();
446 | for (int i = 0; i < children.length; i++) {
447 | if(children[i].equals("logfile"))
448 | continue;
449 |
450 | new File(rootDir, children[i]).delete();
451 | }
452 | }
453 |
454 | recoveryStatus=0;
455 |
456 |
457 |
458 |
459 | // pendingInserts=Collections.synchronizedMap(new HashMap());//Collections.synchronizedList(new ArrayList());
460 | // pendingDeletes=Collections.synchronizedMap(new HashMap());//new ArrayList();
461 | // pendingQueries=Collections.synchronizedMap(new HashMap());//new ArrayList();
462 | // versions=Collections.synchronizedMap(new HashMap());
463 |
464 |
465 | pendingInserts=new HashMap();//Collections.synchronizedMap();//Collections.synchronizedList(new ArrayList());
466 | pendingDeletes=new HashMap();//Collections.synchronizedMap(new HashMap());//new ArrayList();
467 | pendingQueries=new HashMap();//Collections.synchronizedMap(new HashMap());//new ArrayList();
468 | versions=new HashMap();//Collections.synchronizedMap(new HashMap());
469 | firstTime=true;
470 | //logToFile(new MessageBody("logtest", null, null,null));
471 |
472 | getAVDDetails();
473 | TAG=TAG+String.valueOf(AVDNumber);
474 | //setup the sever
475 | try {
476 | ServerSocket serverSocket = new ServerSocket(SERVER_PORT);
477 | new ServerTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, serverSocket);
478 | } catch (IOException e) {
479 | //Log.d("abcd", "Can't create a ServerSocket");
480 | logToFile("Unable to create socket");
481 | return false;
482 | }
483 |
484 | try
485 | {
486 | currentNodeHash=genHash(String.valueOf(AVDNumber));
487 | }
488 | catch(NoSuchAlgorithmException e)
489 | {
490 | e.printStackTrace();
491 | }
492 |
493 | setupRing();
494 | if(isRecoveryNeeded())
495 | {
496 | //recoveryStatus=2;
497 | activateRecovery();
498 |
499 | }
500 | return false;
501 | }
502 |
503 |
504 | public HashMap query(String selection)
505 | {
506 |
507 | if(selection.equals("@v")) //get all keys/values with versions
508 | {
509 |
510 | HashMapallFilesDump=new HashMap();
511 | try
512 | {
513 | File[] files=this.getContext().getFilesDir().listFiles();
514 | for(int i=0;i0);
545 | try
546 | {
547 |
548 | File f=new File(this.getContext().getFilesDir().getAbsoluteFile(),selection);
549 | String value="";
550 | if(f.exists())
551 | {
552 | FileInputStream inputStream=new FileInputStream(f);
553 |
554 | BufferedReader buf= new BufferedReader(new InputStreamReader(new BufferedInputStream(inputStream)));
555 | String line="";
556 | while((line=buf.readLine())!=null)
557 | value+=line;
558 |
559 | buf.close();
560 | inputStream.close();
561 | value=value.trim();
562 | }
563 | else
564 | value="-1:##";
565 | String[] comp=value.split(":");
566 | HashMap result=new HashMap();
567 | result.put(selection,new VersionObject(Integer.parseInt(comp[0]),comp[1]));
568 |
569 | return result;
570 | // String[] row={selection,value};
571 | //
572 | // result.addRow(row);
573 | // return result;
574 | }
575 | catch(Exception e)
576 | {
577 | e.printStackTrace();
578 | }
579 |
580 | }
581 | return null;
582 | }
583 |
584 |
585 | @Override
586 | public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {
587 | // TODO Auto-generated method stub
588 | Log.v("query", selection);
589 | logToFile("QUERYCALLED:"+String.valueOf(++queryc));
590 |
591 | //while(recoveryStatus>0);
592 | try {
593 |
594 | String[] cols={"key","value"};
595 |
596 | // MatrixCursor result=new MatrixCursor(cols);
597 | if(selection.equals("@")) // in case of * query or incase of a local @ query
598 | {
599 |
600 | MatrixCursor result=new MatrixCursor(cols);
601 | File[] files=this.getContext().getFilesDir().listFiles();
602 | for(int i=0;i localOutput=new HashMap();
631 | File[] files=this.getContext().getFilesDir().listFiles();
632 | for(int i=0;iparam=new ArrayList();
657 | param.add("*");
658 | param.add(String.valueOf(AVDNumber));
659 |
660 |
661 |
662 | int tempsucc=successor;
663 | if(!isNeighbourActive())
664 | {
665 | tempsucc=Integer.parseInt(successorForNode(String.valueOf(successor)));
666 | }
667 | new ClientThread(new MessageBody("SearchKey",param,localOutput,null),String.valueOf(tempsucc*2)).start();
668 | //isStillSearching=true;
669 | //synchronized (this) {
670 | handleRequest("*","add",pendingQueries);
671 | while(pendingQueries.containsKey("*") && pendingQueries.get("*")>0);
672 | logToFile("QUERYRETURNED:"+String.valueOf(++queryr));
673 | logToFile("DONE HERE .. RETURNING"+outputCursor.getCount());
674 | return outputCursor;
675 | //}
676 |
677 | }
678 | // else // hashmap to cursor conversion //only one node in the system // SHOULD NEVER HAPPEN
679 | // {
680 | // MatrixCursor result=new MatrixCursor(cols);
681 | // Iteratorit =localOutput.keySet().iterator();
682 | // while(it.hasNext())
683 | // {
684 | // String[] value=new String[2];
685 | // value[0]=it.next();
686 | // value[1]=localOutput.get(value[0]);
687 | // value[1]=value[1].trim();
688 | // result.addRow(value);
689 | //
690 | // }
691 | // return result;
692 | // }
693 | //
694 | }
695 | else // single file searched for
696 | {
697 |
698 | int coordinator=Integer.parseInt(nodeForKey(selection));
699 | //
700 | if(coordinator!=AVDNumber)
701 | {
702 | // Get node for key
703 | //Log.d(TAG,"File not found"+f.toString());
704 | ArrayListparam=new ArrayList();
705 | param.add(selection);
706 | param.add(String.valueOf(AVDNumber));
707 | new ClientThread(new MessageBody("SearchKey",param,null,null),String.valueOf(coordinator*2)).start();
708 | //isStillSearching=true;
709 | String key=new String(selection);
710 | handleRequest(key, "add",pendingQueries);
711 | }
712 | else
713 | {
714 | logToFile("coord=self");
715 | MatrixCursor result=new MatrixCursor(cols);
716 | File f=new File(this.getContext().getFilesDir().getAbsoluteFile(),selection);
717 | FileInputStream inputStream=new FileInputStream(f);
718 |
719 | BufferedReader buf= new BufferedReader(new InputStreamReader(new BufferedInputStream(inputStream)));
720 | String value="",line="";
721 | while((line=buf.readLine())!=null)
722 | value+=line;
723 |
724 | buf.close();
725 | inputStream.close();
726 | value=value.trim();
727 | String[] comp=value.split(":");
728 |
729 | updateVersions(selection, new VersionObject(Integer.parseInt(comp[0]),comp[1]));
730 | // String[] row={selection,value};
731 | //
732 | // result.addRow(row);
733 | // return result;
734 | }
735 |
736 | //send to the 2 replicas
737 |
738 | ArrayList param=new ArrayList();
739 | param.add(selection);
740 | param.add(String.valueOf(AVDNumber));
741 |
742 | String succ=successorForNode(String.valueOf(coordinator));
743 | logToFile("querying "+selection+" from replica: "+succ);
744 | int destPort=2*Integer.parseInt(succ);
745 | MessageBody queryMessage=new MessageBody("SearchKey", param, null,null);
746 | SimpleDynamoProvider.this.logToFile(queryMessage);
747 | new ClientThread(queryMessage, String.valueOf(destPort)).start();
748 | handleRequest(selection, "add", pendingQueries);
749 |
750 | succ=successorForNode(succ);
751 | logToFile("querying "+selection+" from replica: "+succ);
752 | destPort=2*Integer.parseInt(succ);
753 | queryMessage=new MessageBody("SearchKey", param, null,null);
754 | SimpleDynamoProvider.this.logToFile(queryMessage);
755 | new ClientThread(queryMessage, String.valueOf(destPort)).start();
756 | handleRequest(selection, "add", pendingQueries);
757 |
758 | while(pendingQueries.containsKey(selection) && pendingQueries.get(selection) > 1 );
759 |
760 | HashMap finalMap=new HashMap(outputMap);
761 | hasCopied=true;
762 |
763 | MatrixCursor finalOutput=new MatrixCursor(cols);
764 | String[] value=new String[2];
765 | value[0]=selection;
766 | value[1]=versions.get(selection).value;
767 | finalOutput.addRow(value);
768 | //logToFile("QUERYRETURNED:"+String.valueOf(++queryr)+"RETURNING "+selection);
769 | return finalOutput;
770 | }
771 | //synchronized (SimpleDhtProvider.class) {
772 |
773 | //}
774 |
775 |
776 | } catch (Exception e) {
777 | Log.e("SimpleDynamoProvider", "Unable to read file.");
778 | logToFile("query: exception ---->"+e.getClass());
779 | };
780 |
781 | logToFile("RETURNING EMPTY CURSR: "+selection);
782 | return null;// this.query(uri, projection, selection, selectionArgs, sortOrder);
783 | }
784 |
785 | @Override
786 | public int update(Uri uri, ContentValues values, String selection,
787 | String[] selectionArgs) {
788 | // TODO Auto-generated method stub
789 | return 0;
790 | }
791 |
792 | private String genHash(String input) throws NoSuchAlgorithmException {
793 | MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
794 | byte[] sha1Hash = sha1.digest(input.getBytes());
795 | Formatter formatter = new Formatter();
796 | for (byte b : sha1Hash) {
797 | formatter.format("%02x", b);
798 | }
799 | return formatter.toString();
800 | }
801 |
802 | private void handleSearchResultSingle(String key,HashMapresult)
803 | {
804 |
805 | if(pendingQueries.get(key)==2)
806 | {
807 | logToFile("building cursor"+key);
808 | handleRequest(key, "remove", pendingQueries);
809 | outputMap=result;
810 | hasCopied=false;
811 | while(!hasCopied);
812 | //logToFile("building cursor --- DONE----");
813 | }
814 | else
815 | handleRequest(key, "remove", pendingQueries);
816 |
817 | logToFile("returning after handling"+key);
818 |
819 | }
820 |
821 |
822 |
823 | private void handleSearchResult(String key,HashMapresult)
824 | {
825 | //logToFile("handleSearchResult"+key);
826 | String[] cols={"key","value"};
827 | outputCursor=new MatrixCursor(cols);
828 | Iterator it=result.keySet().iterator();
829 | while(it.hasNext())
830 | {
831 | String[] value=new String[2];
832 | value[0]=it.next();
833 | value[1]=result.get(value[0]).trim();
834 | outputCursor.addRow(value);
835 |
836 | }
837 | handleRequest("*", "delete", pendingQueries);
838 | //logToFile("returning cursor+ "+String.valueOf(outputCursor.getCount()));
839 | }
840 | public void handleRequest(String key,String type,MapoperationMap)
841 | {
842 |
843 | //logToFile("loggin request"+key+"----->"+type+operationMap.keySet().toString());
844 | int value=operationMap.containsKey(key)?operationMap.get(key):0;
845 | if(type.equals("add"))
846 | value++;
847 | else
848 | value--;
849 |
850 | //if(value>0)
851 | operationMap.put(key, value);
852 | // else if(operationMap.containsKey(key))
853 | // operationMap.remove(key);
854 |
855 | //logToFile("returnging from handlerequest"+key);
856 | //logToFile(operationMap.entrySet().toString());
857 |
858 | }
859 |
860 | public synchronized void updateVersions(String key,VersionObject vOb)
861 | {
862 |
863 | if(!versions.containsKey(key) || vOb.versionNumber>versions.get(key).versionNumber)
864 | {
865 | //logToFile("updating versions for:"+key+" with "+String.valueOf(vOb.versionNumber));
866 | versions.put(key, vOb);
867 | }
868 |
869 | //logToFile("VERSIONS:"+versions.entrySet().toString());
870 |
871 | }
872 |
873 | //MessageHandler
874 |
875 | public class MessageHandler implements Runnable
876 | {
877 | MessageBody incomingMessage;
878 |
879 | public MessageHandler(MessageBody inc)
880 | {
881 | incomingMessage=inc;
882 |
883 | }
884 |
885 | public void run()
886 | {
887 |
888 | if (incomingMessage.messageType.equals("InsertKey"))
889 | {
890 | // key value pair to Insert
891 |
892 | String key=String.valueOf(incomingMessage.parameters.get(1));
893 | String value=String.valueOf(incomingMessage.parameters.get(2));
894 | String repCount=String.valueOf(incomingMessage.parameters.get(3));
895 | //logToFile("Recv: "+incomingMessage.parameters.toString());
896 | //code for insertion
897 | ContentValues keyValueToInsert = new ContentValues();
898 | // inserting <”key-to-insert”, “value-to-insert”>
899 | keyValueToInsert.put("key", key);
900 | keyValueToInsert.put("value", value);
901 | keyValueToInsert.put("repCount", repCount);
902 | Uri newUri = SimpleDynamoProvider.this.insert(CONTENT_URI,keyValueToInsert);
903 | int senderPort=2*Integer.parseInt(String.valueOf(incomingMessage.parameters.get(0)));
904 | ArrayList param=new ArrayList();
905 | param.add(key);
906 | MessageBody sentMessage=new MessageBody("InsertComplete",param,null,null);
907 | new ClientThread(sentMessage,String.valueOf(senderPort)).start();
908 | //logToFile(sentMessage);
909 |
910 | }
911 | else if (incomingMessage.messageType.equals("InsertComplete"))
912 | {
913 | //pendingInserts.remove(incomingMessage.parameters.get(0));
914 | handleRequest(String.valueOf(incomingMessage.parameters.get(0)), "delete", pendingInserts);
915 | //logToFile("done here , returning");
916 | }
917 | else if (incomingMessage.messageType.equals("SearchKey"))
918 | {// Query for a particular key has arrived
919 |
920 | String searchKey=String.valueOf(incomingMessage.parameters.get(0));
921 | String sender=String.valueOf(incomingMessage.parameters.get(1));
922 |
923 | if(searchKey.equals("*")) // results accumulatred tme to send back
924 | {
925 | Cursor resultCursor;
926 | if(sender.equals(String.valueOf(AVDNumber)))
927 | {
928 | //logToFile("total result obtained now sending back\n");
929 | MessageBody mssgSent=new MessageBody("SearchResult",incomingMessage.parameters,incomingMessage.keyValuePairs,null);
930 | //logToFile(mssgSent);
931 | new ClientThread(mssgSent,String.valueOf(2*AVDNumber)).start();
932 |
933 | }
934 | else
935 | {
936 | resultCursor=SimpleDynamoProvider.this.query(CONTENT_URI, null,"@", null, null);
937 | while(resultCursor.moveToNext())
938 | incomingMessage.keyValuePairs.put(resultCursor.getString(0), resultCursor.getString(1));
939 |
940 | ArrayList param=new ArrayList();
941 | param.add(searchKey);
942 | param.add(sender);
943 |
944 | int tempsucc=successor;
945 | if(!isNeighbourActive())
946 | {
947 | tempsucc=Integer.parseInt(successorForNode(String.valueOf(successor)));
948 | }
949 | int succPort=2*tempsucc;
950 | MessageBody sentMessage=new MessageBody("SearchKey",param,incomingMessage.keyValuePairs,null);
951 | //logToFile(sentMessage);
952 | new ClientThread(sentMessage,String.valueOf(succPort)).start();
953 | }
954 | }
955 | else // single file searched for
956 | {
957 | //if(isKeyOnCurrentNode(searchKey)) // will always be true // keyHash.compareTo(predecessorHash)>0 && keyHash.compareTo(currentNodeHash)<=0)
958 | //{
959 | HashMap result=SimpleDynamoProvider.this.query(searchKey);
960 |
961 | //while(resultCursor.moveToNext())
962 | //incomingMessage.keyValuePairs.put(resultCursor.getString(0), resultCursor.getString(1));
963 |
964 | int senderPort=2*Integer.parseInt(sender);
965 | ArrayList param=new ArrayList();
966 | param.add(searchKey);
967 |
968 | new ClientThread(new MessageBody("SearchResult",param,null,result),String.valueOf(senderPort)).start();
969 |
970 | //}
971 | // else // will never be triggered in direct routing
972 | // {
973 | // int succPort=2*successor;
974 | // ArrayList param=new ArrayList();
975 | // param.add(searchKey);
976 | // param.add(sender);
977 | // new ClientThread(new MessageBody("SearchKey",incomingMessage.parameters,incomingMessage.keyValuePairs),String.valueOf(succPort)).start();
978 | //
979 | // }
980 |
981 |
982 | }
983 |
984 |
985 |
986 | }
987 | else if (incomingMessage.messageType.equals("SearchResult"))
988 | {
989 | // value found for the sent key
990 |
991 | String searchKey=String.valueOf(incomingMessage.parameters.get(0));
992 | if(searchKey.equals("*"))
993 | {
994 | HashMapresult=new HashMap(incomingMessage.keyValuePairs);
995 | handleSearchResult(new String(),result);
996 |
997 | }
998 | else
999 | {
1000 | updateVersions(searchKey,incomingMessage.keyVersionPairs.get(searchKey));
1001 | HashMapresult=new HashMap(incomingMessage.keyVersionPairs);
1002 | handleSearchResultSingle(new String(searchKey),result);
1003 |
1004 | }
1005 |
1006 | }
1007 | else if(incomingMessage.messageType.equals("DeleteKey"))
1008 | {
1009 | // Query for a particular key has arrived
1010 |
1011 |
1012 |
1013 | String deleteKey=String.valueOf(incomingMessage.parameters.get(0));
1014 | String sender=String.valueOf(incomingMessage.parameters.get(1));
1015 |
1016 | if(deleteKey.equals("*"))
1017 | {
1018 |
1019 | if(sender.equals(String.valueOf(AVDNumber)))
1020 | {
1021 | //logToFile("total result obtained now sending back\n");
1022 | MessageBody mssgSent=new MessageBody("DeleteResult",incomingMessage.parameters,null,null);
1023 | //logToFile(mssgSent);
1024 | new ClientThread(mssgSent,String.valueOf(2*AVDNumber)).start();
1025 |
1026 | }
1027 | else
1028 | {
1029 | int res=SimpleDynamoProvider.this.delete(CONTENT_URI, "@", null);
1030 |
1031 | int oldResult=Integer.parseInt(String.valueOf(incomingMessage.parameters.get(2)));
1032 | res=oldResult&res;
1033 |
1034 |
1035 | int succPort=2*successor;
1036 | ArrayList param=new ArrayList();
1037 | param.add(deleteKey);
1038 | param.add(sender);
1039 | param.add(String.valueOf(res));
1040 |
1041 | MessageBody sentMessage=new MessageBody("DeleteKey",param,null,null);
1042 | //logToFile(sentMessage);
1043 | new ClientThread(sentMessage,String.valueOf(succPort)).start();
1044 | }
1045 | }
1046 | else // single file searched for
1047 | {
1048 | //if(isKeyOnCurrentNode(deleteKey))// keyHash.compareTo(predecessorHash)>0 && keyHash.compareTo(currentNodeHash)<=0)
1049 |
1050 | int res=SimpleDynamoProvider.this.delete(deleteKey);
1051 | int senderPort=2*Integer.parseInt(sender);
1052 | ArrayList param=new ArrayList();
1053 | param.add(deleteKey);
1054 | param.add(sender);
1055 | param.add(String.valueOf(res));
1056 | new ClientThread(new MessageBody("DeleteResult",param,null,null),String.valueOf(senderPort)).start();
1057 |
1058 | //
1059 | // else // should never be called
1060 | // {
1061 | // int succPort=2*successor;
1062 | // ArrayList param=new ArrayList();
1063 | // param.add(deleteKey);
1064 | // param.add(sender);
1065 | // new ClientThread(new MessageBody("DeleteKey",incomingMessage.parameters,null,null),String.valueOf(succPort)).start();
1066 | //
1067 | // }
1068 | //
1069 |
1070 | }
1071 |
1072 | }
1073 | else if(incomingMessage.messageType.equals("DeleteResult"))
1074 | {
1075 |
1076 | finalDeleteResult=Integer.parseInt(String.valueOf(incomingMessage.parameters.get(2)));
1077 |
1078 | //logToFile("Value recevied");
1079 | //logToFile(outputCursor.toString());
1080 |
1081 | //isStillDeleting=false;
1082 | // pendingDeletes.remove(incomingMessage.parameters.get(0));
1083 | handleRequest(String.valueOf(incomingMessage.parameters.get(0)), "remove", pendingDeletes);
1084 |
1085 | }
1086 | else if (incomingMessage.messageType.equals("RecoverSelf"))
1087 | {
1088 | HashMap localResult=SimpleDynamoProvider.this.query("@v");
1089 | ArrayList param=new ArrayList();
1090 | param.add("Self");
1091 | int senderPort=Integer.parseInt(incomingMessage.parameters.get(0))*2;
1092 | new ClientThread(new MessageBody("RecoverResult",param,null,localResult),String.valueOf(senderPort)).start();
1093 | }
1094 | else if (incomingMessage.messageType.equals("RecoverReplica"))
1095 | {
1096 | HashMap localResult=SimpleDynamoProvider.this.query("@v");
1097 | ArrayList param=new ArrayList();
1098 | param.add("Replica");
1099 | int senderPort=Integer.parseInt(incomingMessage.parameters.get(0))*2;
1100 | new ClientThread(new MessageBody("RecoverResult",param,null,localResult),String.valueOf(senderPort)).start();
1101 |
1102 |
1103 | }
1104 | else if (incomingMessage.messageType.equals("RecoverResult"))
1105 | {
1106 | recoveryStatus++;
1107 | SimpleDynamoProvider.this.recover(incomingMessage.parameters.get(0),incomingMessage.keyVersionPairs);
1108 | }
1109 | else if (incomingMessage.messageType.equals("PollNeighbourRequest"))
1110 | {
1111 | int sender=Integer.parseInt(incomingMessage.sender);
1112 | int destPort=sender*2;
1113 | new ClientThread(new MessageBody("PollNeighbourReply",new ArrayList(),null,null),String.valueOf(destPort)).start();
1114 | }
1115 | else if (incomingMessage.messageType.equals("PollNeighbourReply"))
1116 | {
1117 | isNeighbourActive=true;
1118 | }
1119 |
1120 | }
1121 |
1122 |
1123 | }
1124 |
1125 |
1126 |
1127 | //Socket Commincation Intefaces
1128 |
1129 | private class ServerTask extends AsyncTask {
1130 |
1131 | @Override
1132 | protected Void doInBackground(ServerSocket... sockets) {
1133 | ServerSocket serverSocket = sockets[0];
1134 |
1135 | try
1136 | {
1137 | while(true) {
1138 | Socket serverSock=serverSocket.accept();
1139 | ObjectInputStream oStream=new ObjectInputStream(serverSock.getInputStream());
1140 | MessageBody m=(MessageBody)oStream.readObject();
1141 | SimpleDynamoProvider.this.logToFile("Incoming message----->");
1142 | SimpleDynamoProvider.this.logToFile(m);
1143 | //Executors.newSingleThreadExecutor().execute(new MessageHandler(m));
1144 | new MessageHandler(m).run();
1145 | //Executors.newSingleThreadExecutor().execute(new MessageHandler(m));
1146 |
1147 | oStream.close();
1148 | //serverSock.close();
1149 | }
1150 |
1151 | }
1152 | catch(Exception e)
1153 | {
1154 | //logToFile("In reading ***"+e.getClass()+e.getStackTrace().toString());
1155 | //Log.d(TAG, e.getStackTrace().toString());
1156 | //System.out.println(e);
1157 | }
1158 | return null;
1159 | }
1160 |
1161 |
1162 | }
1163 | public class ClientThread extends Thread
1164 | {
1165 | private MessageBody mssg;
1166 | private String port;
1167 | public ClientThread(MessageBody m,String port)
1168 | {
1169 | mssg=m;
1170 | this.port=port;
1171 | }
1172 | public void run()
1173 | {
1174 |
1175 | try {
1176 | mssg.sender=String.valueOf(SimpleDynamoProvider.this.AVDNumber);
1177 | int portNum=Integer.parseInt(port);
1178 | //SimpleDynamoProvider.this.logToFile("OUTGOING MESSAGE TO PORT : ******"+ String.valueOf(portNum));
1179 | //SimpleDynamoProvider.this.logToFile(mssg);
1180 | Log.d(TAG,"Trying with port:"+String.valueOf(port)+"with mssg"+mssg);
1181 | SocketAddress destAddr= new InetSocketAddress("10.0.2.2", portNum);
1182 |
1183 | Socket socket = new Socket();//InetAddress.getByAddress(new byte[]{10, 0, 2, 2}),portNum);
1184 | socket.connect(destAddr);
1185 |
1186 | ObjectOutputStream output=new ObjectOutputStream(socket.getOutputStream());
1187 | SimpleDynamoProvider.this.logToFile("outgoing message----->port:"+port);
1188 | SimpleDynamoProvider.this.logToFile(mssg);
1189 |
1190 | //output.writeBytes(mssg);
1191 | output.writeObject(mssg);
1192 | output.close();
1193 | socket.close();
1194 | } catch (UnknownHostException e) {
1195 | SimpleDynamoProvider.this.logToFile("ClientTask UnknownHostException");
1196 | isNeighbourActive=false;
1197 | // Log.d(TAG, "ClientTask UnknownHostException");
1198 | } catch (IOException e) {
1199 | SimpleDynamoProvider.this.logToFile("ClientTask socket IOException .. connecting to "+port);
1200 | isNeighbourActive=false;
1201 | //Log.d(TAG, "ClientTask socket IOException");
1202 | }
1203 |
1204 |
1205 |
1206 | }
1207 | }
1208 |
1209 | public void getAVDDetails()
1210 | {
1211 | TelephonyManager tel = (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
1212 | String rt=tel.getLine1Number();
1213 | String portStr = rt.substring(tel.getLine1Number().length() - 4);
1214 | myPortStr = String.valueOf((Integer.parseInt(portStr) * 2));
1215 | //AVDNumber=Arrays.asList(ports).indexOf(myPortStr);
1216 | AVDNumber=Integer.parseInt(myPortStr)/2;
1217 | }
1218 | public void logToFile(MessageBody m)
1219 | {
1220 | //
1221 | // try
1222 | // {
1223 | // File f=new File(this.getContext().getFilesDir().getAbsoluteFile(),"logfile");
1224 | // String value=m.sender+"------------->"+m.messageType+"------>"+(m.parameters!=null ? m.parameters.toString():" ")+"------->"+((m.nodeSet!=null)?m.nodeSet.toString():" ")+"------>"+((m.keyValuePairs!=null)?m.keyValuePairs:" ")+((m.keyVersionPairs!=null)?m.keyVersionPairs.toString():" ")+"\n";
1225 | // if(!f.exists())
1226 | // f.createNewFile();
1227 | //
1228 | //
1229 | // FileWriter fileWritter = new FileWriter(f.getAbsolutePath(),true);
1230 | // BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
1231 | // bufferWritter.write(value);
1232 | // bufferWritter.close();
1233 | //// FileOutputStream outputStream = new FileOutputStream(f);//openFileOutput(filename, Context.MODE_PRIVATE);
1234 | //// outputStream.write(value.getBytes());
1235 | //// outputStream.close();
1236 | // }
1237 | // catch(IOException e)
1238 | // {
1239 | // e.printStackTrace();
1240 | // }
1241 |
1242 | }
1243 |
1244 | public void logToFile(String m)
1245 | {
1246 | try
1247 | {
1248 | File f=new File(this.getContext().getFilesDir().getAbsoluteFile(),"logfile");
1249 | String value=m+"\n";
1250 | if(!f.exists())
1251 | f.createNewFile();
1252 |
1253 |
1254 | FileWriter fileWritter = new FileWriter(f.getAbsolutePath(),true);
1255 | BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
1256 | bufferWritter.write(value);
1257 | bufferWritter.close();
1258 | // FileOutputStream outputStream = new FileOutputStream(f);//openFileOutput(filename, Context.MODE_PRIVATE);
1259 | // outputStream.write(value.getBytes());
1260 | // outputStream.close();
1261 | }
1262 |
1263 | catch(IOException e)
1264 | {
1265 | e.printStackTrace();
1266 | }
1267 |
1268 | }
1269 |
1270 |
1271 | private boolean isKeyOnNode(String key,String nodeHash,String predNodeHash)
1272 | {
1273 | try
1274 | {
1275 | String keyHashString=genHash(key);
1276 |
1277 | return (keyHashString.compareTo(nodeHash)<=0 && keyHashString.compareTo(predNodeHash)>0) || (nodeHash.equals(smallestInRing)&&(keyHashString.compareTo(nodeHash)<=0 || keyHashString.compareTo(predNodeHash)>0));
1278 | }
1279 | catch(NoSuchAlgorithmException e)
1280 | {
1281 | e.printStackTrace();
1282 | }
1283 |
1284 | return false;
1285 | }
1286 | public boolean isKeyOnCurrentNode(String key)
1287 | {
1288 |
1289 | return isKeyOnNode(key, currentNodeHash,predecessorHash);
1290 | }
1291 |
1292 | private String nodeForKey(String key)
1293 | {
1294 | try
1295 | {
1296 | String predHash=genHash(nodeSet[4]); //jugadd hard coded count
1297 | for(String s:nodeSet)
1298 | {
1299 | String nodeHash=genHash(s);
1300 | if(isKeyOnNode(key,nodeHash,predHash)==true)
1301 | return s;
1302 | predHash=nodeHash;
1303 | }
1304 | }
1305 | catch(NoSuchAlgorithmException e)
1306 | {
1307 | e.printStackTrace();
1308 | }
1309 | return "";
1310 | }
1311 |
1312 | private String predecessorForNode(String nodenumber)
1313 | {
1314 | int index=0;
1315 | String pred;
1316 | for(;index param=new ArrayList();
1386 | // param.add(String.valueOf(AVDNumber));
1387 | // MessageBody splitReqMssg=new MessageBody("SplitRequest", param,new HashMap());
1388 | // new ClientThread(splitReqMssg,String.valueOf(2*successor)).start();
1389 | // }
1390 | }
1391 | catch(NoSuchAlgorithmException ex)
1392 | {
1393 | ex.printStackTrace();
1394 | }
1395 |
1396 |
1397 | }
1398 | private boolean isRecoveryNeeded()
1399 | {
1400 |
1401 | // if(AVDNumber==5554)
1402 | // {
1403 | //
1404 | // File f=new File(this.getContext().getFilesDir().getAbsoluteFile(),"logfile");
1405 | // return f.exists();
1406 | // }
1407 |
1408 | return true;//isNeighbourActive();
1409 |
1410 |
1411 | }
1412 | private void activateRecovery()
1413 | {
1414 | logToFile("Recovery in progress");
1415 | String succ=successorForNode(String.valueOf(AVDNumber));
1416 | String pred=predecessorForNode(String.valueOf(AVDNumber));
1417 | String prepred=predecessorForNode(pred);
1418 |
1419 | ArrayList param=new ArrayList();
1420 | param.add(String.valueOf(AVDNumber));
1421 |
1422 | int destPort=Integer.parseInt(succ)*2;
1423 | MessageBody selfMessage=new MessageBody("RecoverSelf",param, null, null);
1424 | new ClientThread(selfMessage,String.valueOf(destPort)).start();
1425 |
1426 | destPort=Integer.parseInt(pred)*2;
1427 | MessageBody repMessage=new MessageBody("RecoverReplica",param, null, null);
1428 | new ClientThread(repMessage,String.valueOf(destPort)).start();
1429 |
1430 | // destPort=Integer.parseInt(prepred)*2;
1431 | // repMessage=new MessageBody("RecoverReplica",param, null, null);
1432 | // new ClientThread(repMessage,String.valueOf(destPort)).start();
1433 |
1434 | }
1435 | private void recover(String type,HashMapdata)
1436 | {
1437 | logToFile("RECOVERING");
1438 | if(type.equals("Self"))
1439 | {
1440 | String selfStr=String.valueOf(AVDNumber);
1441 | for(String key:data.keySet())
1442 | {
1443 |
1444 | if(nodeForKey(key).equals(selfStr))
1445 | {
1446 | VersionObject obj=data.get(key);
1447 | insert(key,obj);
1448 | }
1449 | }
1450 |
1451 | recoveryStatus--;
1452 | }
1453 | else
1454 | {
1455 | String selfStr=String.valueOf(AVDNumber);
1456 | String pred=predecessorForNode(selfStr);
1457 | String prepred=predecessorForNode(pred);
1458 | for(String key:data.keySet())
1459 | {
1460 | VersionObject obj=data.get(key);
1461 | if(nodeForKey(key).equals(pred) || nodeForKey(key).equals(prepred))
1462 | {
1463 | insert(key,obj);
1464 | }
1465 | }
1466 |
1467 | recoveryStatus--;
1468 |
1469 |
1470 | }
1471 |
1472 |
1473 |
1474 | }
1475 | public boolean isNeighbourActive()
1476 | {
1477 | isNeighbourActive=false;
1478 | new ClientThread(new MessageBody("PollNeighbourRequest",new ArrayList(),null,null),String.valueOf(successor*2)).start();
1479 | try
1480 | {
1481 | Thread.sleep(2);
1482 |
1483 | }
1484 | catch(Exception e)
1485 | {
1486 | e.printStackTrace();
1487 | }
1488 | if(isNeighbourActive)
1489 | logToFile(String.valueOf(successor)+" is active");
1490 | else
1491 | logToFile(String.valueOf(successor)+" is inactive");
1492 | return isNeighbourActive;
1493 | }
1494 |
1495 | }
1496 |
1497 |
1498 |
--------------------------------------------------------------------------------