From 69f99016fff7bcd5cea27cb2835a77c3f4587ed2 Mon Sep 17 00:00:00 2001
From: Daniel <dl3g19@soton.ac.uk>
Date: Wed, 14 Apr 2021 19:56:07 +0100
Subject: [PATCH] More threading implemented

---
 Controller$IndexEntry.class | Bin 629 -> 1828 bytes
 Controller$SyncList.class   | Bin 0 -> 1619 bytes
 Controller.class            | Bin 5880 -> 7106 bytes
 Controller.java             | 327 ++++++++++++++++++++++++++----------
 Dstore.class                | Bin 5800 -> 7816 bytes
 Dstore.java                 | 259 ++++++++++++++++------------
 6 files changed, 383 insertions(+), 203 deletions(-)
 create mode 100644 Controller$SyncList.class

diff --git a/Controller$IndexEntry.class b/Controller$IndexEntry.class
index 1a3af9c4b1553341ae7057985d0c3bb2d51cc7fd..d745c8e2de25162b50503edcae6b679006643ab7 100644
GIT binary patch
literal 1828
zcmX^0Z`VEs1_mpJXif$u24;2!79Ivx1~x_pQRn=;lA`>aoYW!}&%Bh>3fH`nqDn>v
zwvvp@Vif~M1|A=T3TrL~4hBwk1}+{3ZU!Dk27#=^vPAuy#JqHU|D>$c<Pt^(Hk-`6
z%o00B24)S-Fpyn*JPiB{0*nkCX_+~x#hF#9j0}vP><mJT48jP5Re~$?l6^9ZOSl*W
z8AL#)i!w6sYam+<F-@F@L4rY&k%6PQB)=#%#i^2!LBI#>iqewI9DR@x)*xG@c^G6s
zw({nc<|d^Uh2#f=)N?S%F)|2(wJK!hDHIgtrx&Fb7lSk?@GvMcC^0gy6_+HIlom5G
z2tkYmdoH-7C^Ih|Y_JLsgDQg>BLffE6vyOjpZw%(RMn86u;yaWV9;b|(BfgxX3$||
z5CpptY@BCaNosm(5hDY8Sz=CUs(%_IgP4Y=CX$6v71rDgdJOvP3<f+5h73lG418cS
z;67z!U`|X)VPp{1K++1eT{8-#*Mx_`l);RVfdvxq%o>`WpeVH9VXy?nA6s62NoHCl
zNToFogAIc%BLiDvN{VAn4kLpk)KIW(&Y%R6T#}ieXRR5<$iNw#nVy$eQd*SC$e;?b
z8>|cz{5B9ivPZ4$tQi?tobyvs85#I}GV@aXAd!-ol#|NHz+IeL;s#F}EE=AgVT=si
z>BxfIi76@I2n0tsZ*WOsa<*?`K?uYEVPuzroL~(yK?7YByTd?AL6#wm7t(;n1l&v3
zj11}+g4m5?WDqD$ErI$ElIR#2IEzzDf}zO@C9a_93giaPbc7lam}THVgeqcWU{6mi
zfuuH61<)90WZ(+UFD*(=1qCJ}13w~n>4B0BBLjzDYH^82esKvqLpUP?7ebzqfyXm1
zFSW=yC$YFVwV08C3%MlVfaOgFMFu7Y4h9AWHU<_@o@QWRU;*Vu21W)u1_lNu273k;
zP_6@uD>5j7X;lU_1_l8EP+`Nsz`(`8$iU4Y%D~9rz`($e$iTwD#K6E{sHMG?fl+Ha
z1G^T}Rt8?J-3)?}+S?g~w=#%nF>hs%(h`#0${??`n}H*8I|KVx2IY+m3=E76jtmS8
zat!PY3=HB7oD32Sd<>EdQVdcI@(j`psths=1`M(ciVRK+&QR-=7?{A;v1v(fW#C1a
z!37poU|?lXWKd*qVK9TLmt|mNU}RumVAa~fz`F)+B^y{!g@KX56>hXY)Mz!WEevAP
zI~de=GUzffgoAiH8H^bjw6-uvEnwi%+QOi`jlmpbH51tRd<@JC3=A3!d<>clstj5T
zZVU_z%nXdGV8h)Rn83m012tS3WSsU+1}oxC)@1<YZ6yYMn8`}esPbT7WbkD0g4%%W
zQ?U(bJ~e`B@n%qD@PYdnB`~ExK7vFDBrwewSQ*S26d8OO{Gfq}P_Mm}K^|Sb6$2}S
zHG?99KSKaiJ+hPJ(Vb++z{n8D5QIgkGP+VH24;p}aOw<U2nEw&3=s?r3_{>Q4P%I8
OU||qs2xEw1U;zLGZEoZM

delta 303
zcmZ3&_mzd~)W2Q(7#J9=7_=sGbt`2hmL=+!mSpDWI~ElsR{CTXmvAu%GH`M-FfoYo
zFo-dTPdq25$iX1V$RJo;l3$dnkeR1YP?Voulv-R2QY6j8Aj2R#S)EaCvJaD)0KbNh
zbADb)QGQNNYLT^O*yIK#>B&!-wHVbW3$SR`Gbl1JF>o+2Ft9K%GVn79FfcGMf-GTR
zWRPQEU|?d9XJ7=G$G{*Uz`)AD29{@J;AT)@U}R8aU|{fIU}j)qU|>+t(%#CzsI{Ge
zU5jZe1FzO@2EoYf48mI(M6`q?wlYX<1nX2{U|<kqU}a!n5N6<H5Mj{eV-RJKWDsMJ
iXAoy#W>5xOsluQNrqviU7#JA17#JCt7}OXv8CU?r+b+`p

diff --git a/Controller$SyncList.class b/Controller$SyncList.class
new file mode 100644
index 0000000000000000000000000000000000000000..3aa93869f34b5831c8f1487af11b00f6e1812c3e
GIT binary patch
literal 1619
zcmX^0Z`VEs1_mnz2Tlei24;2!79Ivx1~x_pVdwn3lA`>aoYW$f;L5yYpUmPCMh3Q$
zjLc#c14afOAB4O$7Xt?aCp!Zd4+A#?4<mzcR$^JAerZW&j=p12QDP-jt4(HJW{Djm
z1G9!^7)S>n4+B4g03!o)VoC}lgQ$iNSX)kFUb?=2QdVkmiM3`FNSzQ5gD`^#BLiDv
zN{VAn4kLpkR4Ld7XOI(<OEUBGpvuK~7{nPQ7#Wz;Q%gX`dTL@C%+4Ui$RLQY&oi$i
zH9fTmWSa~RgDis_BLhouW>qTKv7R7d1s(=Pkg04%sk!-OsURU`kdOcu0~3QPh^5BJ
zAf|z08Prs3kP;1$XEi}ekX!>(0P-gjgEq+FYK#p08pvU*8OF%K;+&t7%E-X)lbM(5
zSDKrYS`?C)l#|NHz#CkWn4ImKSODg;GZ->52q1g~2}O1WV_1}c!!{(ND8C$}ot?py
zkwFBk94#an890M8)AJHbN{dn%8T7FSw~aOypV(PzMlmvIL1e(D!c%|^L=fx-n8)p`
z85y{O^Gl18Q{6H_9^yx&Dm{?P7#TSHQj1GG@{3E@8EhFDxDfJ;3_PBBd8tLtIf=!^
zsl|*89I#}{pvb_)z`?-4z$hR9O3Vxl3|tJ14BQMl42%rA3=9lf3``76AW<#ttqhD>
z+Zot5f>bl;F)%RjF)%YQFt{_YGI%g>GI%mDGVn8KLiNQkFfp(&Ffa&eMfx7n(%#O%
zt8;jbpUz?3{a^`h1|9|m22ezUXeK1%d>L36{1|u`{2BBa7#Ktu82>ZyfHE5sJA))U
zg8>60JA)AeBPf|OFo9i&VUr+{Hia;-FoZJjFoa>+WCFLzjDdlHiNTzKkwKh64eGa8
zuooB@M8JNN-p(L;fI(8{@CJnU_!#&Z7#R2&gupbi_o5kC7-AUs8Dhbf3WL1I5B44-
z+)73USq3?%RS}?)hJk@WKr7Pckk)nvY3;*ne6<hjKthp=ft!JWft!I3Oe0&9#K6Lk
z%)rf%0=7m7WDPe16FUgOgHRE-hvbR(PzD1FLnZ@1Ll)R393E1{oi3D!jIBHd7KVHV
z9)<$2J=oKQfFr2nfd-u%H082sNpE9N*#J+qYz&MH3=D1pj-VnHsuq+BK&hNlOZxzW
z<TeKNHCU93Ge|&{qZqA)VKf5^10>m4Fj#_<j}?P8n6_cC17#%!Mg}GZ8wPs@761o5
B5@!Ga

literal 0
HcmV?d00001

diff --git a/Controller.class b/Controller.class
index 338ca1cac64638e4f4032704a11ffa1948b256ee..ef4ebb6110d7d4a7fe514ac5b4b7d62058a0eb68 100644
GIT binary patch
delta 4722
zcmeyNd&r#Y)W2Q(7#J9=7#k*X&9`*U&nqd)&&f$GQVFiiOZLeuF5zMjW02%wU}cbE
zWZ>8EL8!3S4C7?rV36TqkY$jYcv@aXfssKlE3qt5zqBMXN8cl{IKwxwfQvz%ff=Mu
znTJ7zL3J`8qYSq?g9bZ;CJ%!agZ5-oMr&1Fknwtq4D1@7o}QkXVO$Ix3<f+5h74?s
z46MZ^iA5#s491hEGHP&}GMKS5nDa1LFj!7L!D!5AJ^2r#5w|Ua9Xo?P4}$}P<77)F
zD@NzZB}^(Tu8a)olm9b{Pu|QVWa7@qAPRO{UTTScaB5LmYEf{0a&~G77lRvvC&+#;
zMg|rQu;p$HK0FM*41SY;GAS|!OqOPrW(=Ba&Me0r!Vt>N5XQq0&JZy<f!UrTkRb}B
zGkWrJW?2q@hFB0MZt@vs2@ZdT1RjP&hNQ`Fm{o*Q7#SE9xERtH(%Bg@co;GnvL-9B
zxO3+)<gzp5@i62w6ihB*Q4lI(WMJ{~_w)m)Ea71&Whk4xj76ETV)7{#X~wF_&sgL+
zLKtdz7-|{nCiAlD*H<z$fGlieWRTSG0sAd8U*Es9q@c7UxTGjGG1nRtlI0A|AXP1l
z48jOi;YFDxsYTYBVH^x?j0~)<K|%gOTnyz59Xt%3433NptmPmDAdzk!h8}P<B<JK8
zr-CA;kB6b3VFDw=<lU@R!Tt>0><p6`8HB<1=OpH(>$_GYrxuiC=I3!SOk$YI!!Qk`
zoxh+cGp{7LBr!QVq$n{tm4jghBLg=mEoJ7Frt0bGaWSYf%;I5~%`j)O2b-!y4#PYi
zhWQL-j10_)DJen>3=9i-7#1-so_vPgRg;5ZDG$Rkkg=RasY!`BiFqIcS1>ZL28Z|u
zxq=+Iiicq}!<xy<*o@8AF*0z1#p4~Fy+Lvtco;S^tYKu}C@#q_N_9-m=3v;&$iU*`
z@8|-O-pa$UjbZ!b*KEeNI~f_+f?Poo91Od`Y+wH{u=#s=81{k8U@J<^%`Z#kU^oCW
z!814nWWpgHhQka;CP%Z&nXxk*V`LCO1WrgsQEFm}5CbE_2_A-%45t_wn2SpD7#Unq
zGS=ja+``ddP2kiDPN&wIkT?d1aZqVqUSd*Csx=qGQHC?1_&v+WAP$XRR285!aFoG-
zo8bb(MRtZuJPel^$|kq5%L#x)uJSNkW4O-9z?`01GI<84CNn$3&B@jrQuQGWw|N-u
zFcdH{u&1Y%1mqW$fFkG~55s+s7)NGaNmyb|X(|`P4Tgt2438MR7#X+|Q&NIKA)4Y;
z$<FWumL@Xu^#ee04@q)d438NaI2fKYGKjc>5}ksJziV*3pMOZaYXms-9y7e;VR%&!
zPK4kz1Jdz^hv6+Kx>?h5N{cf<BHf$}HyA$fFnnZ?gGFSDQzbV;4#Q`Vm%cDEh-!Eu
zhnRm-R%&vIHAvex9)|A>Jd6w+X_+~x#hF#9LJUj{KS9as7bAn1hNq{d&*T@J!XAGZ
z8H6CwtB{$eP*9YgUX)r~3^L&#55s>(21W+9;*!LY(qcviA*8qoE-A{)OSk4`$YEsS
zVPs}xnJmqv%EQRU$j;8l!NbVO$TiuAOO2C}jgg0kk(ZHgay6F%w*aFcJEIT}qcEe$
z<YipW93hNiJPfRi;*&pe$qO(uECl(vgNq@Ap__wIX0igeh^!nV1AmY!C_TnI`}+p?
zxQ4iLGhAR);9*o`RGJ*fEw8V_$i&X5%E-VAPD$W0IT%#lJ!Y^IVqgK8d4oX`q(_T~
zQJYa`awUgjJr~0bMm-)zeNco76sMN>mF6a;7KP-4BbI~Fkdc7{l9xjKg&0^Fjd>Ur
zF`8fmHZ%x8hMDm&nlti2l95k-ayAzO6Qd;$qZOkyBLho$VrB`b)b-K~V`sEwWRR-|
zI~AOOJ@ZOZi;7AMN>Wo0B?_Yr!&H!|4m^yGj82RU-07($V5g-xRWdRNX+UGV6jc9!
z>Mm;zMi)i~K5#}?NY2kK$Vn|p<zRGUWZ;8%0~U1bj2@r_D-No?GV}F4{gLc+XP7#<
zn|lvq@MI4jWl=^3zMRC|q?AMzu&F8rj0|cTpbU#ty+AW;7&~Lc<UAe^zBn$%c*X>F
z#zatXB~3oUb0ju}kwM4>Y=S~!i2|cSR(@t)Y6?FaV;UD@I%5VqV<rz{7GpLegAyW0
zGV{vvvs3kbz}EYwmL#SnCYR(FRWdSg=OXjYOn%3cH2D_~?_>vFfyuvkgc+?Tzvq#d
z?7+)9Ig3}uRDgkvpPey}i-ChNpNBD&F^q$;kdc8GRL;e_1^N3bFe)%|Fcvd1a6l3m
zh*vtflUJIhoRNWP@<Co<84g(MfRTaAGcP5z!Zoj?sFIzrhLJ&a@&_JOW_HH9$-I2w
zrm_rj42+Ck3=9lRjNS|^pe6vE@58{&z{tSLpvS<-=*z&skjlWqz{<eDU^saupIp7x
zb_R*94ANS=8RR3kGbnClP}<1Az`)4p$H2g##K6J8z);S>!cf7$$xz9_$56!}%uvlB
z$xy?f%23N-z);7)$>`4*05y3l0~-Sy0|SGH7PHX~1~nTk77%5t#R{VAwAetD8Ov@4
zj!0=4Sy7hl3_4cztdgwT81$Dji2H0}FcGra#$dA%%yI#-HZm|VFfbS}7&91wX<G&-
z1}3o6tQhzh7#Nxu*cqA`_!wFkL>XEcWEt8Sv>7@W3>YRd7&CM+m@srR*f8`k*fR7n
z*fI1oxG_v%aA%mr7|6iDz|Fv1%+6rsS<lYk#L2)2Y6L+%!Dz+63iiaL-3)G#T3Z;{
zw=;P7Xm4Zi_TA0kAGw<$Fj8k5L-2Nn$n6X<e!ANj;)Rm8F{E0tXl-GT-pP>7$e^`_
zfp-yukt7SVkx=0_hT>TaYP%WABX=`Yf^=4IXQ<!K&}79b$tu*kjiJ6B<o~Ya3|v~0
zEIQj5dUdxkOkDndvailIhAE&BnZAv|X8HeSkPD`Of`f;llA(rS5(5K64?_>bBxrE>
zF$gm-Fid0MVVKDv$S{jRg<&>>KEoUaZ-%)H@eK1A(irA5WHT&a$YWT<P|C1`p^{-0
zLk+_+hT3|D6%36GD;YW&Rx$K2tYzqBSjRAtVFNgfj2Kw|Fz~Q5xcy^DWM>FrXYgld
z3}XAwz{bGD&cMOW;Ksnn&M@ge13!r701+T(^)pOhU;-sHMrj5X24)5ZhArCAkeJD!
z4GJY~aI)CJFmorv+<GR4@J$RR+AK!97#1)vY-6y|+QzVCIYTo@&+=^y#WNZBv~;vt
zjJ7eXT+WaS5?zZTx_&uBI7oC8Sd<^EmU$b)mgNi%AmJTI!Yp86O_1;|urQyNPCeM@
zJ<Az{LBjjN!W>#U+ZYalvH>KmxiJVbFfeRp;AYsuAjhzkL5E=*gE7Mn20MnG44w?T
z8A2HLFvK(LW5{CI&rrs2kfD*`5JNA+5r!EIM;R6~9A{X^aDrho!&z{cax$<Ri;9Yg
ziSjdsFfcH%)H5)GBXc#w8c3)y7&EYfLrr)$!_i1B9qnBV#~B#5Go0SWa1P`oNY3N~
zE4jeH&&bLk#K;CQ3u@FxxKS|-Objdx4B${#(%H#yo{3==1ItFOEes&u6()uQ4D~ns
zbhWoJ+}gn~a~s3mZ43`Uc0jx>1}Y^OIT?5vxf%Ev`50sv`5Ckr1;E~5W?<w)v2+{5
zcBuPLGcbdTjVh=$U`rKuGdzye-o{Y9o#Ck!izJKCvuzA7Bw4mG)V~Ii@1SbIPPze7
zu!Z40^G=3OASbGCW4LR^D#@~i;j0-NvN`OM?4qoqY`YkKfD+CNN%n0FuR+8+gdfZp
zco`TNg&BAmMHr+QMHv(s#Te8W#Tm32r5UUkWf*+x8D$wl7?l_j8I>9G8C4ic7*!c6
z8P#B()JE~-K3K>y+Ay$yJ-Hw1aIhz3ksRlz3-+S!Hip-_+Za&&=cg<5dn?0V-7O67
zch)m9GBSWXypxfYkzpo-w<OC>Ms7xi0}Sd`th*UPB6l$IgGz|I+Zjczz`mDcg9anJ
zB)iToMhOOnZH$s2Z$tbp$+nGAYWe?-y26aoTN(Z$ISFKoFrzFq;346@u^wDyfC~FC
z22lnEMok7@MlA+OMr{UpMjZxaMqLJVMneWuMk5AmMpK3uMl*(7MstR0Mhk{EMoWfn
zMk|I1jMfZO8EqJ5Fgh~KXLMm$!|2Meh0%>+C!;&VK1L64Nb)l<tN&$?V`sR*&dBzQ
zArKL&Ao~w99D$~tRt9EJqGNDGa<(rhh<7r|GcxRCRAyxG(}jkVxGprH(yUl?Bw4mG
zsxANjOlKRzYn^QjNGU*$ft`VY(T9PD(U(D=(T~BD(VxMBF@V8_F_6K5F{mEwK0XGf
zzYNms43ELilR-F-fdSM5g1Sx;R55}uD1AZlAsYiD0|R3sLW2MksHTThB}_aF%nV!%
z42;|$FKC1F-%JK2kl%D5ap<R8uf2;=9h`h&NoC`1h8vMu+Zi?dz`AsIGHNn2go7%T
zJzQ2S%x0{jtRT)J24zrLD#{AWC01;bETXKS)N$9pg_Uvn|695sb=w$qkt_sNJHm_x
z;51;xCdsz1-i)2uj6;+|lzkC{j3k>Vhn^XyB&#UrE=D7;t6Df1m;ZkZN`bF+w=tS(
zZD9~--NtCKoPi6ZeH){l?lwkyq-u{@SD4XxE5lz&R$)e0kTtBJOv$>9;oWiu4nN&(
zjGh}Am>CW;oM*ViXv4t3P_NC%%IMCZ!^i}tAtg^6gCYY1!zBh@hRY0+3|APG8Ll#@
zGhAcPX1LCv!*H9yl;IA8Bg1_LPlg8!p$rchQW+jG<TE^AC}nuUP|NU~p^M=K!z6~6
z3~Lx(G3;P?$*_;%4Z~rE4-DrSzA#*3_{4C9;WNWchHnfn8GhF@d|>#;@Ppw$!(T=Q
zMkYoUMpi~9Mm9!fMlMEHaN6)@;L`cWAP-Kv;f%i+H2yPaFmQq^z%+2Jc!QlW9GrB*
z85tQEelW-fvoqST@&9L#W?+UZV_;-wbZ22;VT=T4xG2VG1_n??8p0sPaDy?1fq_Ab
zfsHYifsrwpF_nRtF^4giF$c^q0Fy;vvII<)F;*}zFi0^lGl(&8Fjg|KFx+6^V60+b
NVXS7XWvpkA1OPkmO``w+

delta 3798
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
PWnf{nV{~A2Vvqy?c`jm0

diff --git a/Controller.java b/Controller.java
index d9661c4..cf4f95b 100644
--- a/Controller.java
+++ b/Controller.java
@@ -5,6 +5,7 @@ import java.util.List;
 import java.util.ArrayList;
 import java.util.Map;
 import java.util.HashMap;
+import java.util.Collection;
 
 public class Controller {
 	protected int cport; //Port to listen on
@@ -18,6 +19,7 @@ public class Controller {
 		protected int numberToStore;
 		protected String status;
 		protected Object storeAckLock;
+		protected List<Reloader> clientLoadList;
 		
 		public IndexEntry() {
 			filesize = -1;
@@ -25,6 +27,7 @@ public class Controller {
 			numberToStore = 0;
 			status = "store in progress";
 			storeAckLock = new Object();
+			clientLoadList = new ArrayList<Reloader>();
 		}
 		
 		public synchronized void setFilesize(int filesize) {
@@ -36,7 +39,7 @@ public class Controller {
 		}
 		
 		public void addStoredBy(int dstore) {
-			storedBy.add(new Integer(dstore));
+			storedBy.add(Integer.valueOf(dstore));
 			if(storedBy.size() == numberToStore) storeAckLock.notify();
 		}
 		
@@ -45,6 +48,16 @@ public class Controller {
 			if(storedBy.size() == numberToStore) storeAckLock.notify();
 		}
 		
+		public void removeStoredBy(int dstore) {
+			storedBy.remove(Integer.valueOf(dstore));
+			if(storedBy.size() == 0) storeAckLock.notify();
+		}
+		
+		public void removeStoredBy(List<Integer> dstores) {
+			storedBy.removeAll(dstores);
+			if(storedBy.size() == 0) storeAckLock.notify();
+		}
+		
 		public List<Integer> getStoredBy() {
 			return storedBy;
 		}
@@ -57,13 +70,17 @@ public class Controller {
 			this.status = status;
 		}
 		
-		public synchronized int getStatus() {
+		public synchronized String getStatus() {
 			return status;
 		}
 		
 		public Object getLock() {
 			return storeAckLock;
 		}
+		
+		public List<Reloader> getLoadList() {
+			return clientLoadList;
+		}
 	}
 	
 	protected class SyncList extends ArrayList<Integer> {
@@ -74,47 +91,53 @@ public class Controller {
 		@Override
 		public boolean add(Integer i) {
 			synchronized(this) {
-				super.add(i);
+				return super.add(i);
 			}
 		}
 		
 		@Override
-		public boolean addAll(Collection<Integer> c) {
+		public boolean addAll(Collection<? extends Integer> c) {
 			synchronized(this) {
-				super.addAll(c);
+				return super.addAll(c);
 			}
 		}
 		
 		@Override
 		public Integer get(int i) {
 			synchronized(this) {
-				super.get(i);
+				return super.get(i);
 			}
 		}
 		
 		@Override
 		public int size() {
 			synchronized(this) {
-				super.size();
+				return super.size();
 			}
 		}
 		
-		@Override
-		public boolean remove(int i) {
+		public Integer remove(int i) {
 			synchronized(this) {
-				super.remove(i);
+				return super.remove(i);
 			}
 		}
 		
-		@Override
 		public boolean remove(Integer i) {
 			synchronized(this) {
-				super.remove(i);
+				return super.remove(i);
 			}
 		}
 	}
 	
+	protected class Reloader {
+		public boolean reload;
+		public Reloader() {
+			reload = false;
+		}
+	}
+	
 	protected List<Integer> dstores;
+	protected Map<Integer,String[]> rebalanceMessages;
 	protected Map<String,IndexEntry> index;
 	
 	public Controller(int cport, int rFactor, int timeout, int rebalancePeriod) {
@@ -179,6 +202,7 @@ public class Controller {
 	void handleMessage(String[] message, Socket client) throws Exception {
 		if(message[0].equals("JOIN")) {
 			dstores.add(Integer.parseInt(message[1]));
+			System.out.println("Dstore at " + message[1] + " joined");
 			rebalance();
 		}
 		else if(message[0].equals("STORE")) {
@@ -188,10 +212,10 @@ public class Controller {
 			storeAck(client, message[1]);
 		}
 		else if(message[0].equals("LOAD")) {
-			load(client, message[1], false);
+			load(client, message[1]);
 		}
 		else if(message[0].equals("RELOAD")) {
-			load(client, message[1], true);
+			reload(message[1]);
 		}
 		else if(message[0].equals("REMOVE")) {
 			remove(client, message[1]);
@@ -200,7 +224,13 @@ public class Controller {
 			list(client);
 		}
 		else {
-			//Log error and continue (throw exception?)
+			for(String name : message) {
+				if(!index.containsKey(name)) {
+					//Log error and continue (throw exception?)
+					return;
+				}
+			}
+			receiveDstoreList(client, message);
 		}
 	}
 	
@@ -262,93 +292,206 @@ public class Controller {
 	}
 	
 	void storeAck(Socket client, String filename) throws Exception {
-		if(!index.containsKey(filename)) {
-			//Throw logging exception
-			return;
-		}
-		
-		IndexEntry thisEntry = index.get(filename);
-		thisEntry.addStoredBy(new Integer(client.getPort()));
+		new Thread(() -> {
+			if(!index.containsKey(filename)) {
+				//Throw logging exception
+				return;
+			}
+			
+			IndexEntry thisEntry = index.get(filename);
+			thisEntry.addStoredBy(Integer.valueOf(client.getPort()));
+		}).start();
 	}
 	
-	void load(Socket client, String filename, boolean reload) throws Exception {
-		if(!index.containsKey(filename)) {
-			PrintWriter out = new PrintWriter(client.getOutputStream());
-			out.print("ERROR DOES_NOT_EXIST");
-			out.flush();
-			out.close();
-		}
-		
-		//Select a Dstore which contains the file
-		IndexEntry thisEntry = index.get(filename);
-		int thisStore = thisEntry.storedBy.get(0).intValue();
-		int thisSize = thisEntry.filesize;
-		
-		// !!TO DO: RELOAD COMMAND!!
-		
-		//Send LOAD_FROM message
-		PrintWriter out = new PrintWriter(client.getOutputStream());
-		out.print("LOAD_FROM " + thisStore + " " + thisSize);
-		out.flush();
-		out.close();
+	void load(Socket client, String filename) throws Exception {
+		new Thread(() -> {
+			try {
+				if(!index.containsKey(filename)) {
+					PrintWriter out = new PrintWriter(client.getOutputStream());
+					out.print("ERROR DOES_NOT_EXIST");
+					out.flush();
+					out.close();
+					return;
+				}
+				
+				//Select a Dstore which contains the file
+				IndexEntry thisEntry = index.get(filename);
+				int thisStore = thisEntry.storedBy.get(0).intValue();
+				int thisSize = thisEntry.filesize;
+				
+				//Send LOAD_FROM message
+				PrintWriter out = new PrintWriter(client.getOutputStream());
+				out.print("LOAD_FROM " + thisStore + " " + thisSize);
+				out.flush();
+				
+				Reloader reloadLock = new Object();
+				thisEntry.getLoadList().add(reloadLock);
+				int trials = 0;
+				while(true) {
+					reloadLock.wait(10 * timeout);
+					trials ++;
+					if(trials >= rFactor || !reloadLock.reload) break;
+					out.print("LOAD_FROM " + thisEntry.storedBy.get(trials).intValue() + " " + thisSize);
+					out.flush();
+					reloadLock.reload = false;
+				}
+				
+				thisEntry.getLoadList().remove(reloadLock);
+				if(trials >= rFactor && reloadLock.reload) {
+					out.print("ERROR LOAD");
+					out.flush();
+				}
+				
+				out.close();
+			}
+			catch(IOException e) {
+				e.printStackTrace();
+			}
+		}).start();
+	}
+	
+	void reload(String filename) {
+		new Thread(() -> {
+			try {
+				for(Reloader r : index.get(filename).getLoadList()) {
+					r.reload = true;
+					r.notify();
+				}
+			}
+			catch(IOException e) {
+				e.printStackTrace();
+			}
+		}).start();
 	}
 	
 	void remove(Socket client, String filename) throws Exception {
-		if(!index.containsKey(filename)) {
-			PrintWriter clientOut = new PrintWriter(client.getOutputStream());
-			clientOut.print("ERROR DOES_NOT_EXIST");
-			clientOut.flush();
-			clientOut.close();
-		}
-		
-		//Update index to "remove in progress"
-		IndexEntry entry = index.get(filename);
-		entry.status = "remove in progress";
-		
-		//Send REMOVE message to all Dstores storing the file
-		for(Integer dstore : entry.storedBy) {
-			Socket socket = new Socket(InetAddress.getLocalHost(), dstore.intValue());
-			PrintWriter out = new PrintWriter(socket.getOutputStream());
-			out.write("REMOVE " + filename);
-			out.flush();
-			out.close();
-			socket.close();
-		}
-		
-		//Wait for REMOVE_ACKs from all Dstores which were sent the REMOVE message
-		
-		//Update index to "remove complete"
-		entry.status = "remove complete";
-		
-		//Send REMOVE_COMPLETE to client
-		PrintWriter clientOut = new PrintWriter(client.getOutputStream());
-		clientOut.print("REMOVE_COMPLETE");
-		clientOut.flush();
-		clientOut.close();
+		new Thread(() -> {
+			try {
+				if(!index.containsKey(filename)) {
+					PrintWriter clientOut = new PrintWriter(client.getOutputStream());
+					clientOut.print("ERROR DOES_NOT_EXIST");
+					clientOut.flush();
+					clientOut.close();
+					return;
+				}
+				
+				//Update index to "remove in progress"
+				IndexEntry entry = index.get(filename);
+				entry.status = "remove in progress";
+				
+				//Send REMOVE message to all Dstores storing the file
+				for(Integer dstore : entry.storedBy) {
+					Socket socket = new Socket(InetAddress.getLocalHost(), dstore.intValue());
+					PrintWriter out = new PrintWriter(socket.getOutputStream());
+					out.write("REMOVE " + filename);
+					out.flush();
+					out.close();
+					socket.close();
+				}
+				
+				//Wait for REMOVE_ACKs from all Dstores which were sent the REMOVE message
+				try {
+					entry.getLock().wait(timeout);
+				}
+				catch(InterruptedException e) {
+					e.printStackTrace();
+				}
+				
+				if(entry.getStoredBy().size() > 0) {
+					//Log error
+				}
+				
+				//Update index to "remove complete"
+				entry.status = "remove complete";
+				
+				//Send REMOVE_COMPLETE to client
+				PrintWriter clientOut = new PrintWriter(client.getOutputStream());
+				clientOut.print("REMOVE_COMPLETE");
+				clientOut.flush();
+				clientOut.close();
+			}
+			catch(IOException e) {
+				e.printStackTrace();
+			}
+		}).start();
 	}
 	
 	void list(Socket client) throws Exception {
-		//Send file list to client
-		PrintWriter out = new PrintWriter(client.getOutputStream());
-		for(String name : index.keySet()) {
-			out.println(name);
-		}
-		out.flush();
-		out.close();
+		new Thread(() -> {
+			try {
+				//Send file list to client
+				PrintWriter out = new PrintWriter(client.getOutputStream());
+				for(String name : index.keySet()) {
+					out.println(name);
+				}
+				out.flush();
+				out.close();
+			}
+			catch(IOException e) {
+				e.printStackTrace();
+			}
+		}).start();
 	}
 	
 	void rebalance() throws Exception {
-		//Send LIST message to each Dstore and receive their file list
-		
-		//Create a new file allocation so that:
-		  //Each file appears rFactor times
-		  //Each file appears at most once on each datastore
-		  //Files are evenly distributed (Dstores differ in capacity by at most 1, no 2 datastores have identical file lists)
-		
-		//Make a (files to send, files to remove) pair for each Dstore
-		
-		//Send the respective REBALANCE message to each Dstore
-		
-		//Wait for REBALANCE_COMPLETE from all Dstores
+		new Thread(() -> {
+			if(rebalanceMessages != null) return;
+			Map<Integer,String[]> dstoreFiles = new HashMap<Integer,String[]>();
+			rebalanceMessages = dstoreFiles;
+			try {
+				//Send LIST message to each Dstore and receive their file list
+				for(Integer dstore : dstores) {
+					Socket socket = new Socket(InetAddress.getLocalHost(), dstore.intValue());
+					PrintWriter out = new PrintWriter(socket.getOutputStream());
+					out.write("LIST");
+					out.flush();
+					out.close();
+					socket.close();
+				}
+				
+				dstoreFiles.wait(timeout);
+				if(dstoreFiles.size() < dstores.size()) {
+					//Log error
+				}
+				
+				//Create a new file allocation so that:
+				  //Each file appears rFactor times
+				  //Each file appears at most once on each datastore
+				  //Files are evenly distributed (Dstores differ in capacity by at most 1, no 2 datastores have identical file lists)
+				for(Integer i : reshuffle(dstoreFiles.keySet())) {
+					
+				}
+				
+				//Make a (files to send, files to remove) pair for each Dstore
+				
+				//Send the respective REBALANCE message to each Dstore
+				
+				//Wait for REBALANCE_COMPLETE from all Dstores
+			}
+			catch(IOException e) {
+				e.printStackTrace();
+			}
+			finally {
+				rebalanceMessages = null;
+			}
+		}).start();
+	}
+	
+	void receiveDstoreList(Socket client, String[] list) {
+		new Thread(() -> {
+			if(rebalanceMessages == null) return;
+			rebalanceMessages.add(Integer.valueOf(client.getPort()), list);
+			if(rebalanceMessages.size() == dstores.size()) {
+				rebalanceMessages.notify();
+			}
+		}).start();
+	}
+	
+	List<Integer> reshuffle(Collection<Integer> col) {
+		List<Integer> list = new ArrayList<Integer>();
+		for(Integer i : col) {
+			list.add(0, i);
+		}
+		return list;
 	}
 }
diff --git a/Dstore.class b/Dstore.class
index 508e972562b57c9e441796e3b9ff255a2b8d89b9..4e4fda3f3e0789c67909d128772fc154545a4cf4 100644
GIT binary patch
delta 4084
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
Q;9_88EMhESEMt%a0MtyU2mk;8

delta 2385
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

diff --git a/Dstore.java b/Dstore.java
index 7a40e16..ee9a08e 100644
--- a/Dstore.java
+++ b/Dstore.java
@@ -1,5 +1,7 @@
 import java.io.*;
+import java.lang.Runnable;
 import java.nio.file.Files;
+import java.nio.file.Path;
 import java.net.*;
 import java.util.Map;
 import java.util.HashMap;
@@ -88,131 +90,166 @@ public class Dstore {
 	}
 	
 	void store(Socket client, String filename, int filesize, BufferedReader in) throws Exception {
-		//Send ACK message to client
-		PrintWriter out = new PrintWriter(client.getOutputStream());
-		out.print("ACK");
-		out.flush();
-		out.close();
-		
-		FileOutputStream writer = new FileOutputStream(fileFolder + "/" + filename, false);
-		
-		//Receive + write file content from client
-		int byteCount = filesize;
-		while(byteCount > 0) {
-			byte[] nextLine = in.readLine().getBytes();
-			writer.write(nextLine);
-			writer.flush();
-			byteCount -= nextLine.length;
-		}
-		writer.close();
-		
-		//Send STORE_ACK message to the Controller
-		PrintWriter controllerOut = new PrintWriter(new Socket(InetAddress.getLocalHost(), cport).getOutputStream());
-		controllerOut.print("STORE_ACK " + filename);
-		controllerOut.flush();
-		controllerOut.close();
+		new Thread(() -> {
+			try {
+				//Send ACK message to client
+				PrintWriter out = new PrintWriter(client.getOutputStream());
+				out.print("ACK");
+				out.flush();
+				out.close();
+				
+				FileOutputStream writer = new FileOutputStream(fileFolder + "/" + filename, false);
+				
+				//Receive + write file content from client
+				int byteCount = filesize;
+				while(byteCount > 0) {
+					byte[] nextLine = in.readLine().getBytes();
+					writer.write(nextLine);
+					writer.flush();
+					byteCount -= nextLine.length;
+				}
+				writer.close();
+				
+				//Send STORE_ACK message to the Controller
+				PrintWriter controllerOut = new PrintWriter(new Socket(InetAddress.getLocalHost(), cport).getOutputStream());
+				controllerOut.print("STORE_ACK " + filename);
+				controllerOut.flush();
+				controllerOut.close();
+			}
+			catch(IOException e) {
+				e.printStackTrace();
+			}
+		}).start();
 	}
 	
 	void load(Socket client, String filename) throws Exception {
-		//Send the content of the file in fileFolder to the client
-		PrintWriter out = new PrintWriter(client.getOutputStream());
-		FileInputStream reader;
-		try {
-			reader = new FileInputStream(fileFolder + "/" + filename);
-		}
-		catch(FileNotFoundException e) {
-			out.print("ERROR DOES_NOT_EXIST");
-			out.flush();
-			out.close();
-			return;
-		}
-		
-		byte[] buf = new byte[8];
-		while(reader.read(buf) != -1) {
-			out.print(new String(buf));
-			out.flush();
-		}
-		
-		reader.close();
-		out.close();
+		new Thread(() -> {
+			try {
+				//Send the content of the file in fileFolder to the client
+				PrintWriter out = new PrintWriter(client.getOutputStream());
+				FileInputStream reader;
+				try {
+					reader = new FileInputStream(fileFolder + "/" + filename);
+				}
+				catch(FileNotFoundException e) {
+					out.print("ERROR DOES_NOT_EXIST");
+					out.flush();
+					out.close();
+					return;
+				}
+				
+				byte[] buf = new byte[8];
+				while(reader.read(buf) != -1) {
+					out.print(new String(buf));
+					out.flush();
+				}
+				
+				reader.close();
+				out.close();
+			}
+			catch(IOException e) {
+				e.printStackTrace();
+			}
+		}).start();
 	}
 	
 	void remove(Socket client, String filename) throws Exception {
-		//Remove the file from fileFolder
-		Path path = new File(fileFolder + "/" + filename).toPath();
-		PrintWriter out = new PrintWriter(client.getOutputStream());
-		
-		if(Files.deleteIfExists(path)) {
-			//Send REMOVE_ACK message to client (the controller)
-			out.print("REMOVE_ACK");
-		}
-		else {
-			//Send DOES NOT EXIST error
-			out.print("ERROR DOES_NOT_EXIST " + filename);
-		}
-		
-		out.flush();
-		out.close();
+		new Thread(() -> {
+			try {
+				//Remove the file from fileFolder
+				Path path = new File(fileFolder + "/" + filename).toPath();
+				PrintWriter out = new PrintWriter(client.getOutputStream());
+				
+				if(Files.deleteIfExists(path)) {
+					//Send REMOVE_ACK message to client (the controller)
+					out.print("REMOVE_ACK");
+				}
+				else {
+					//Send DOES NOT EXIST error
+					out.print("ERROR DOES_NOT_EXIST " + filename);
+				}
+				
+				out.flush();
+				out.close();
+			}
+			catch(IOException e) {
+				e.printStackTrace();
+			}
+		}).start();
 	}
 	
 	void list(Socket client) throws Exception {
-		//Send a list of all files in fileFolder to client (the controller)
-		PrintWriter out = new PrintWriter(client.getOutputStream());
-		for(File file : new File(fileFolder).listFiles()) {
-			out.print(file.getName());
-			out.flush();
-		}
-		out.close();
+		new Thread(() -> {
+			try {
+				//Send a list of all files in fileFolder to client (the controller)
+				PrintWriter out = new PrintWriter(client.getOutputStream());
+				for(File file : new File(fileFolder).listFiles()) {
+					out.print(file.getName());
+					out.flush();
+				}
+				out.close();
+			}
+			catch(IOException e) {
+				e.printStackTrace();
+			}
+		}).start();
 	}
 	
 	void rebalance(Socket client, String[] message) throws Exception {
-		//Interpret files to send and files to remove from the message
-		Map<String,Integer[]> filesToSend;
-		String[] filesToRemove;
-		int index;
-		
-		int numberToSend = Integer.parseInt(message[1]);
-		index = 2;
-		filesToSend = new HashMap<String,Integer[]>(numberToSend);
-		for(int i=0; i<numberToSend; i++) {
-			String name = message[index];
-			index++;
-			
-			int numberOfReceivers = Integer.parseInt(message[index]);
-			index++;
-			Integer[] receivers = new Integer[numberOfReceivers];
-			for(int j=0; j<numberOfReceivers; j++) {
-				receivers[j] = Integer.parseInt(message[index]);
+		new Thread(() -> {
+			try {
+				//Interpret files to send and files to remove from the message
+				Map<String,Integer[]> filesToSend;
+				String[] filesToRemove;
+				int index;
+				
+				int numberToSend = Integer.parseInt(message[1]);
+				index = 2;
+				filesToSend = new HashMap<String,Integer[]>(numberToSend);
+				for(int i=0; i<numberToSend; i++) {
+					String name = message[index];
+					index++;
+					
+					int numberOfReceivers = Integer.parseInt(message[index]);
+					index++;
+					Integer[] receivers = new Integer[numberOfReceivers];
+					for(int j=0; j<numberOfReceivers; j++) {
+						receivers[j] = Integer.parseInt(message[index]);
+						index++;
+					}
+					
+					filesToSend.put(name, receivers);
+				}
+				
+				int numberToRemove = Integer.parseInt(message[index]);
 				index++;
+				filesToRemove = new String[numberToRemove];
+				for(int k=0; k<numberToRemove; k++) {
+					filesToRemove[k] = message[index];
+					index++;
+				}
+				
+				//Send each file to send to the Dstore at the specified port number
+				for(String filename : filesToSend.keySet()) {
+					for(Integer dstore : filesToSend.get(filename)) {
+						//Same store functions as used in the client object
+					}
+				}
+				
+				//Remove each file to remove from fileFolder
+				for(String filename : filesToRemove) {
+					new File(fileFolder + "/" + filename).delete();
+				}
+				
+				//Send REBALANCE_COMPLETE message to client (the controller)
+				PrintWriter out = new PrintWriter(client.getOutputStream());
+				out.print("REBALANCE COMPLETE");
+				out.flush();
+				out.close();
 			}
-			
-			filesToSend.put(name, receivers);
-		}
-		
-		int numberToRemove = Integer.parseInt(message[index]);
-		index++;
-		filesToRemove = new String[numberToRemove];
-		for(int k=0; k<numberToRemove; k++) {
-			filesToRemove[k] = message[index];
-			index++;
-		}
-		
-		//Send each file to send to the Dstore at the specified port number
-		for(String filename : filesToSend.keySet()) {
-			for(Integer dstore : filesToSend.get(filename)) {
-				//Same store functions as used in the client object
+			catch(IOException e) {
+				e.printStackTrace();
 			}
-		}
-		
-		//Remove each file to remove from fileFolder
-		for(String filename : filesToRemove) {
-			new File(fileFolder + "/" + filename).delete();
-		}
-		
-		//Send REBALANCE_COMPLETE message to client (the controller)
-		PrintWriter out = new PrintWriter(client.getOutputStream());
-		out.print("REBALANCE COMPLETE");
-		out.flush();
-		out.close();
+		}).start();
 	}
 }
-- 
GitLab