├── 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 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------