Block Chain Transactions, Commits multiple parts version
authorAli Younis <ayounis@uci.edu>
Sat, 7 Jan 2017 23:23:39 +0000 (15:23 -0800)
committerAli Younis <ayounis@uci.edu>
Sat, 7 Jan 2017 23:23:39 +0000 (15:23 -0800)
62 files changed:
version2/backup/doc/iotcloud.aux [new file with mode: 0644]
version2/backup/doc/iotcloud.log [new file with mode: 0644]
version2/backup/doc/iotcloud.pdf [new file with mode: 0644]
version2/backup/doc/iotcloud.tex [new file with mode: 0644]
version2/backup/doc/makefile [new file with mode: 0644]
version2/backup/src/java/.dir-locals.el [new file with mode: 0644]
version2/backup/src/java/iotcloud/Abort.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/CloudComm.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/Commit.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/Entry.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/Guard.java_backup [new file with mode: 0644]
version2/backup/src/java/iotcloud/IoTString.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/KeyValue.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/LastMessage.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/Liveness.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/LocalComm.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/Makefile [new file with mode: 0644]
version2/backup/src/java/iotcloud/NewKey.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/Pair.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/PendingTransaction.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/RejectedMessage.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/ServerException.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/Slot.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/SlotBuffer.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/SlotIndexer.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/Table.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/TableStatus.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/Test.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/ThreeTuple.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/Transaction.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/TransactionStatus.java [new file with mode: 0644]
version2/backup/src/java/iotcloud/issues.txt [new file with mode: 0644]
version2/backup/src/script/C.cfg [new file with mode: 0644]
version2/backup/src/script/java.cfg [new file with mode: 0644]
version2/backup/src/script/makefile [new file with mode: 0644]
version2/backup/src/server/.dir-locals.el [new file with mode: 0644]
version2/backup/src/server/Makefile [new file with mode: 0644]
version2/backup/src/server/README.txt [new file with mode: 0644]
version2/backup/src/server/iotcloud.cpp [new file with mode: 0644]
version2/backup/src/server/iotquery.cpp [new file with mode: 0644]
version2/backup/src/server/iotquery.h [new file with mode: 0644]
version2/doc/iotcloud.tex [deleted file]
version2/doc/makefile [deleted file]
version2/src/java/iotcloud/Abort.java
version2/src/java/iotcloud/CloudComm.java
version2/src/java/iotcloud/Commit.java
version2/src/java/iotcloud/CommitPart.java [new file with mode: 0644]
version2/src/java/iotcloud/Entry.java
version2/src/java/iotcloud/LocalComm.java
version2/src/java/iotcloud/NewKey.java
version2/src/java/iotcloud/Pair.java
version2/src/java/iotcloud/PendingTransaction.java
version2/src/java/iotcloud/ServerException.java
version2/src/java/iotcloud/Table.java
version2/src/java/iotcloud/Test.java
version2/src/java/iotcloud/Transaction.java
version2/src/java/iotcloud/TransactionPart.java [new file with mode: 0644]
version2/src/java/iotcloud/TransactionStatus.java
version2/src/java/iotcloud/issues.txt [deleted file]
version2/src/script/C.cfg [deleted file]
version2/src/script/java.cfg [deleted file]
version2/src/script/makefile [deleted file]

diff --git a/version2/backup/doc/iotcloud.aux b/version2/backup/doc/iotcloud.aux
new file mode 100644 (file)
index 0000000..134fcf3
--- /dev/null
@@ -0,0 +1,18 @@
+\relax 
+\@writefile{toc}{\contentsline {section}{\numberline {1}\textbf  {Introduction}}{1}}
+\@writefile{toc}{\contentsline {section}{\numberline {2}Approach}{1}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Keys}{1}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Entry layout}{1}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {2.3}Live status}{3}}
+\@writefile{toc}{\contentsline {paragraph}{Validation procedure on client:}{4}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {2.4}Resizing Queue}{4}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {2.5}The Arbitrator}{4}}
+\@writefile{toc}{\contentsline {section}{\numberline {3}Server Algorithm}{4}}
+\@writefile{toc}{\contentsline {section}{\numberline {4}\textbf  {Client}}{6}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {4.1}\textbf  {Client Notation Conventions}}{6}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {4.2}\textbf  {Client State}}{7}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.2.1}Constants}{7}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.2.2}Primitive Variables}{7}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.2.3}Sets and Lists}{7}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {4.3}Helper Functions}{8}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {4.4}Client Interfaces}{37}}
diff --git a/version2/backup/doc/iotcloud.log b/version2/backup/doc/iotcloud.log
new file mode 100644 (file)
index 0000000..f9f7b1e
--- /dev/null
@@ -0,0 +1,589 @@
+This is pdfTeX, Version 3.14159265-2.6-1.40.16 (TeX Live 2015) (preloaded format=pdflatex 2015.5.24)  21 DEC 2016 15:40
+entering extended mode
+ restricted \write18 enabled.
+ %&-line parsing enabled.
+**iotcloud.tex
+(./iotcloud.tex
+LaTeX2e <2015/01/01>
+Babel <3.9l> and hyphenation patterns for 79 languages loaded.
+(/usr/local/texlive/2015/texmf-dist/tex/latex/base/article.cls
+Document Class: article 2014/09/29 v1.4h Standard LaTeX document class
+(/usr/local/texlive/2015/texmf-dist/tex/latex/base/size11.clo
+File: size11.clo 2014/09/29 v1.4h Standard LaTeX file (size option)
+)
+\c@part=\count79
+\c@section=\count80
+\c@subsection=\count81
+\c@subsubsection=\count82
+\c@paragraph=\count83
+\c@subparagraph=\count84
+\c@figure=\count85
+\c@table=\count86
+\abovecaptionskip=\skip41
+\belowcaptionskip=\skip42
+\bibindent=\dimen102
+)
+(/usr/local/texlive/2015/texmf-dist/tex/latex/graphics/color.sty
+Package: color 2014/10/28 v1.1a Standard LaTeX Color (DPC)
+
+(/usr/local/texlive/2015/texmf-dist/tex/latex/latexconfig/color.cfg
+File: color.cfg 2007/01/18 v1.5 color configuration of teTeX/TeXLive
+)
+Package color Info: Driver file: pdftex.def on input line 142.
+
+(/usr/local/texlive/2015/texmf-dist/tex/latex/pdftex-def/pdftex.def
+File: pdftex.def 2011/05/27 v0.06d Graphics/color for pdfTeX
+
+(/usr/local/texlive/2015/texmf-dist/tex/generic/oberdiek/infwarerr.sty
+Package: infwarerr 2010/04/08 v1.3 Providing info/warning/error messages (HO)
+)
+(/usr/local/texlive/2015/texmf-dist/tex/generic/oberdiek/ltxcmds.sty
+Package: ltxcmds 2011/11/09 v1.22 LaTeX kernel commands for general use (HO)
+)
+\Gread@gobject=\count87
+))
+(/usr/local/texlive/2015/texmf-dist/tex/latex/amscls/amsthm.sty
+Package: amsthm 2015/03/04 v2.20.2
+\thm@style=\toks14
+\thm@bodyfont=\toks15
+\thm@headfont=\toks16
+\thm@notefont=\toks17
+\thm@headpunct=\toks18
+\thm@preskip=\skip43
+\thm@postskip=\skip44
+\thm@headsep=\skip45
+\dth@everypar=\toks19
+)
+(/usr/local/texlive/2015/texmf-dist/tex/latex/amsmath/amsmath.sty
+Package: amsmath 2013/01/14 v2.14 AMS math features
+\@mathmargin=\skip46
+
+For additional information on amsmath, use the `?' option.
+(/usr/local/texlive/2015/texmf-dist/tex/latex/amsmath/amstext.sty
+Package: amstext 2000/06/29 v2.01
+
+(/usr/local/texlive/2015/texmf-dist/tex/latex/amsmath/amsgen.sty
+File: amsgen.sty 1999/11/30 v2.0
+\@emptytoks=\toks20
+\ex@=\dimen103
+))
+(/usr/local/texlive/2015/texmf-dist/tex/latex/amsmath/amsbsy.sty
+Package: amsbsy 1999/11/29 v1.2d
+\pmbraise@=\dimen104
+)
+(/usr/local/texlive/2015/texmf-dist/tex/latex/amsmath/amsopn.sty
+Package: amsopn 1999/12/14 v2.01 operator names
+)
+\inf@bad=\count88
+LaTeX Info: Redefining \frac on input line 210.
+\uproot@=\count89
+\leftroot@=\count90
+LaTeX Info: Redefining \overline on input line 306.
+\classnum@=\count91
+\DOTSCASE@=\count92
+LaTeX Info: Redefining \ldots on input line 378.
+LaTeX Info: Redefining \dots on input line 381.
+LaTeX Info: Redefining \cdots on input line 466.
+\Mathstrutbox@=\box26
+\strutbox@=\box27
+\big@size=\dimen105
+LaTeX Font Info:    Redeclaring font encoding OML on input line 566.
+LaTeX Font Info:    Redeclaring font encoding OMS on input line 567.
+\macc@depth=\count93
+\c@MaxMatrixCols=\count94
+\dotsspace@=\muskip10
+\c@parentequation=\count95
+\dspbrk@lvl=\count96
+\tag@help=\toks21
+\row@=\count97
+\column@=\count98
+\maxfields@=\count99
+\andhelp@=\toks22
+\eqnshift@=\dimen106
+\alignsep@=\dimen107
+\tagshift@=\dimen108
+\tagwidth@=\dimen109
+\totwidth@=\dimen110
+\lineht@=\dimen111
+\@envbody=\toks23
+\multlinegap=\skip47
+\multlinetaggap=\skip48
+\mathdisplay@stack=\toks24
+LaTeX Info: Redefining \[ on input line 2665.
+LaTeX Info: Redefining \] on input line 2666.
+)
+(/usr/local/texlive/2015/texmf-dist/tex/latex/graphics/graphicx.sty
+Package: graphicx 2014/10/28 v1.0g Enhanced LaTeX Graphics (DPC,SPQR)
+
+(/usr/local/texlive/2015/texmf-dist/tex/latex/graphics/keyval.sty
+Package: keyval 2014/10/28 v1.15 key=value parser (DPC)
+\KV@toks@=\toks25
+)
+(/usr/local/texlive/2015/texmf-dist/tex/latex/graphics/graphics.sty
+Package: graphics 2014/10/28 v1.0p Standard LaTeX Graphics (DPC,SPQR)
+
+(/usr/local/texlive/2015/texmf-dist/tex/latex/graphics/trig.sty
+Package: trig 1999/03/16 v1.09 sin cos tan (DPC)
+)
+(/usr/local/texlive/2015/texmf-dist/tex/latex/latexconfig/graphics.cfg
+File: graphics.cfg 2010/04/23 v1.9 graphics configuration of TeX Live
+)
+Package graphics Info: Driver file: pdftex.def on input line 94.
+)
+\Gin@req@height=\dimen112
+\Gin@req@width=\dimen113
+)
+(/usr/local/texlive/2015/texmf-dist/tex/latex/jknapltx/mathrsfs.sty
+Package: mathrsfs 1996/01/01 Math RSFS package v1.0 (jk)
+\symrsfs=\mathgroup4
+)
+(/usr/local/texlive/2015/texmf-dist/tex/latex/amsfonts/amssymb.sty
+Package: amssymb 2013/01/14 v3.01 AMS font symbols
+
+(/usr/local/texlive/2015/texmf-dist/tex/latex/amsfonts/amsfonts.sty
+Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support
+\symAMSa=\mathgroup5
+\symAMSb=\mathgroup6
+LaTeX Font Info:    Overwriting math alphabet `\mathfrak' in version `bold'
+(Font)                  U/euf/m/n --> U/euf/b/n on input line 106.
+))
+(/usr/local/texlive/2015/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty
+Package: algpseudocode 
+
+(/usr/local/texlive/2015/texmf-dist/tex/latex/base/ifthen.sty
+Package: ifthen 2014/09/29 v1.1c Standard LaTeX ifthen package (DPC)
+)
+(/usr/local/texlive/2015/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty
+Package: algorithmicx 2005/04/27 v1.2 Algorithmicx
+
+Document Style algorithmicx 1.2 - a greatly improved `algorithmic' style
+\c@ALG@line=\count100
+\c@ALG@rem=\count101
+\c@ALG@nested=\count102
+\ALG@tlm=\skip49
+\ALG@thistlm=\skip50
+\c@ALG@Lnr=\count103
+\c@ALG@blocknr=\count104
+\c@ALG@storecount=\count105
+\c@ALG@tmpcounter=\count106
+\ALG@tmplength=\skip51
+)
+Document Style - pseudocode environments for use with the `algorithmicx' style
+) (/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xy.sty
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xy.tex Bootstrap'ing:
+catcodes, docmode,
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xyrecat.tex)
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xyidioms.tex)
+
+ Xy-pic version 3.8.9 <2013/10/06>
+ Copyright (c) 1991-2013 by Kristoffer H. Rose <krisrose@tug.org> and others
+ Xy-pic is free software: see the User's Guide for details.
+
+Loading kernel: messages; fonts; allocations: state,
+\X@c=\dimen114
+\Y@c=\dimen115
+\U@c=\dimen116
+\D@c=\dimen117
+\L@c=\dimen118
+\R@c=\dimen119
+\Edge@c=\toks26
+\X@p=\dimen120
+\Y@p=\dimen121
+\U@p=\dimen122
+\D@p=\dimen123
+\L@p=\dimen124
+\R@p=\dimen125
+\Edge@p=\toks27
+\X@origin=\dimen126
+\Y@origin=\dimen127
+\X@xbase=\dimen128
+\Y@xbase=\dimen129
+\X@ybase=\dimen130
+\Y@ybase=\dimen131
+\X@min=\dimen132
+\Y@min=\dimen133
+\X@max=\dimen134
+\Y@max=\dimen135
+\lastobjectbox@=\box28
+\zerodotbox@=\box29
+\almostz@=\dimen136
+ direction,
+\d@X=\dimen137
+\d@Y=\dimen138
+\K@=\count107
+\KK@=\count108
+\Direction=\count109
+\K@dXdY=\dimen139
+\K@dYdX=\dimen140
+\xyread@=\read1
+\xywrite@=\write3
+\csp@=\count110
+\quotPTK@=\dimen141
+
+utility macros; pictures: \xy, positions,
+\swaptoks@@=\toks28
+\connectobjectbox@@=\box30
+ objects,
+\styletoks@=\toks29
+ decorations;
+kernel objects: directionals, circles, text; options; algorithms: directions,
+edges, connections;  Xy-pic loaded)
+(/usr/local/texlive/2015/texmf-dist/tex/generic/oberdiek/ifpdf.sty
+Package: ifpdf 2011/01/30 v2.3 Provides the ifpdf switch (HO)
+Package ifpdf Info: pdfTeX in PDF mode is detected.
+)
+Package: xy 2013/10/06 Xy-pic version 3.8.9
+
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xyall.tex
+ Xy-pic option: All features v.3.8
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xycurve.tex
+ Xy-pic option: Curve and Spline extension v.3.12 curve,
+\crv@cnt@=\count111
+\crvpts@=\toks30
+\splinebox@=\box31
+\splineval@=\dimen142
+\splinedepth@=\dimen143
+\splinetol@=\dimen144
+\splinelength@=\dimen145
+ circles,
+\L@=\dimen146
+ loaded)
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xyframe.tex
+ Xy-pic option: Frame and Bracket extension v.3.14 loaded)
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xycmtip.tex
+ Xy-pic option: Computer Modern tip extension v.3.7
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xytips.tex
+ Xy-pic option: More Tips extension v.3.11 loaded) loaded)
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xyline.tex
+ Xy-pic option: Line styles extension v.3.10
+\xylinethick@=\dimen147
+ loaded)
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xyrotate.tex
+ Xy-pic option: Rotate and Scale extension v.3.8 loaded)
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xycolor.tex
+ Xy-pic option: Colour extension v.3.11 loaded)
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xymatrix.tex
+ Xy-pic option: Matrix feature v.3.14
+\Row=\count112
+\Col=\count113
+\queue@=\toks31
+\queue@@=\toks32
+\qcount@=\count114
+\qcount@@=\count115
+\matrixsize@=\count116
+ loaded)
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xyarrow.tex
+ Xy-pic option: Arrow and Path feature v.3.9 path, \ar, loaded)
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xygraph.tex
+ Xy-pic option: Graph feature v.3.11 loaded) loaded)
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xypdf.tex
+ Xy-pic option: PDF driver v.1.7 Xy-pic pdf driver: `color' extension support
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xypdf-co.tex loaded)
+Xy-pic pdf driver: `curve' extension support
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xypdf-cu.tex loaded)
+Xy-pic pdf driver: `frame' extension support
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xypdf-fr.tex loaded)
+Xy-pic pdf driver: `line' extension support
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xypdf-li.tex loaded)
+Xy-pic pdf driver: `rotate' extension support
+(/usr/local/texlive/2015/texmf-dist/tex/generic/xypic/xypdf-ro.tex loaded)
+loaded)) (/usr/local/texlive/2015/texmf-dist/tex/latex/varwidth/varwidth.sty
+Package: varwidth 2009/03/30 ver 0.92;  Variable-width minipages
+\@vwid@box=\box32
+\sift@deathcycles=\count117
+\@vwid@loff=\dimen148
+\@vwid@roff=\dimen149
+)
+\c@theorem=\count118
+\c@prop=\count119
+\c@lem=\count120
+\c@defn=\count121
+
+No file iotcloud.aux.
+\openout1 = `iotcloud.aux'.
+
+LaTeX Font Info:    Checking defaults for OML/cmm/m/it on input line 21.
+LaTeX Font Info:    ... okay on input line 21.
+LaTeX Font Info:    Checking defaults for T1/cmr/m/n on input line 21.
+LaTeX Font Info:    ... okay on input line 21.
+LaTeX Font Info:    Checking defaults for OT1/cmr/m/n on input line 21.
+LaTeX Font Info:    ... okay on input line 21.
+LaTeX Font Info:    Checking defaults for OMS/cmsy/m/n on input line 21.
+LaTeX Font Info:    ... okay on input line 21.
+LaTeX Font Info:    Checking defaults for OMX/cmex/m/n on input line 21.
+LaTeX Font Info:    ... okay on input line 21.
+LaTeX Font Info:    Checking defaults for U/cmr/m/n on input line 21.
+LaTeX Font Info:    ... okay on input line 21.
+(/usr/local/texlive/2015/texmf-dist/tex/context/base/supp-pdf.mkii
+[Loading MPS to PDF converter (version 2006.09.02).]
+\scratchcounter=\count122
+\scratchdimen=\dimen150
+\scratchbox=\box33
+\nofMPsegments=\count123
+\nofMParguments=\count124
+\everyMPshowfont=\toks33
+\MPscratchCnt=\count125
+\MPscratchDim=\dimen151
+\MPnumerator=\count126
+\makeMPintoPDFobject=\count127
+\everyMPtoPDFconversion=\toks34
+) (/usr/local/texlive/2015/texmf-dist/tex/generic/oberdiek/pdftexcmds.sty
+Package: pdftexcmds 2011/11/29 v0.20 Utility functions of pdfTeX for LuaTeX (HO
+)
+
+(/usr/local/texlive/2015/texmf-dist/tex/generic/oberdiek/ifluatex.sty
+Package: ifluatex 2010/03/01 v1.3 Provides the ifluatex switch (HO)
+Package ifluatex Info: LuaTeX not detected.
+)
+Package pdftexcmds Info: LuaTeX not detected.
+Package pdftexcmds Info: \pdf@primitive is available.
+Package pdftexcmds Info: \pdf@ifprimitive is available.
+Package pdftexcmds Info: \pdfdraftmode found.
+)
+(/usr/local/texlive/2015/texmf-dist/tex/latex/oberdiek/epstopdf-base.sty
+Package: epstopdf-base 2010/02/09 v2.5 Base part for package epstopdf
+
+(/usr/local/texlive/2015/texmf-dist/tex/latex/oberdiek/grfext.sty
+Package: grfext 2010/08/19 v1.1 Manage graphics extensions (HO)
+
+(/usr/local/texlive/2015/texmf-dist/tex/generic/oberdiek/kvdefinekeys.sty
+Package: kvdefinekeys 2011/04/07 v1.3 Define keys (HO)
+))
+(/usr/local/texlive/2015/texmf-dist/tex/latex/oberdiek/kvoptions.sty
+Package: kvoptions 2011/06/30 v3.11 Key value format for package options (HO)
+
+(/usr/local/texlive/2015/texmf-dist/tex/generic/oberdiek/kvsetkeys.sty
+Package: kvsetkeys 2012/04/25 v1.16 Key value parser (HO)
+
+(/usr/local/texlive/2015/texmf-dist/tex/generic/oberdiek/etexcmds.sty
+Package: etexcmds 2011/02/16 v1.5 Avoid name clashes with e-TeX commands (HO)
+Package etexcmds Info: Could not find \expanded.
+(etexcmds)             That can mean that you are not using pdfTeX 1.50 or
+(etexcmds)             that some package has redefined \expanded.
+(etexcmds)             In the latter case, load this package earlier.
+)))
+Package grfext Info: Graphics extension search list:
+(grfext)             [.png,.pdf,.jpg,.mps,.jpeg,.jbig2,.jb2,.PNG,.PDF,.JPG,.JPE
+G,.JBIG2,.JB2,.eps]
+(grfext)             \AppendGraphicsExtensions on input line 452.
+
+(/usr/local/texlive/2015/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg
+File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv
+e
+))
+LaTeX Font Info:    Try loading font information for U+rsfs on input line 21.
+
+(/usr/local/texlive/2015/texmf-dist/tex/latex/jknapltx/ursfs.fd
+File: ursfs.fd 1998/03/24 rsfs font definition file (jk)
+)
+LaTeX Font Info:    Try loading font information for U+msa on input line 21.
+
+(/usr/local/texlive/2015/texmf-dist/tex/latex/amsfonts/umsa.fd
+File: umsa.fd 2013/01/14 v3.01 AMS symbols A
+)
+LaTeX Font Info:    Try loading font information for U+msb on input line 21.
+
+(/usr/local/texlive/2015/texmf-dist/tex/latex/amsfonts/umsb.fd
+File: umsb.fd 2013/01/14 v3.01 AMS symbols B
+)
+Package xypdf Info: Line width: 0.43799pt on input line 21.
+LaTeX Font Info:    Try loading font information for OMS+cmr on input line 67.
+
+(/usr/local/texlive/2015/texmf-dist/tex/latex/base/omscmr.fd
+File: omscmr.fd 2014/09/29 v2.5h Standard LaTeX font definitions
+)
+LaTeX Font Info:    Font shape `OMS/cmr/m/n' in size <10.95> not available
+(Font)              Font shape `OMS/cmsy/m/n' tried instead on input line 67.
+ [1
+
+{/usr/local/texlive/2015/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] [2] [3]
+
+Underfull \hbox (badness 10000) in paragraph at lines 145--159
+
+ []
+
+
+Underfull \hbox (badness 10000) in paragraph at lines 145--159
+
+ []
+
+
+Underfull \hbox (badness 10000) in paragraph at lines 145--159
+
+ []
+
+[4] [5]
+Underfull \hbox (badness 10000) in paragraph at lines 206--216
+
+ []
+
+
+Underfull \hbox (badness 10000) in paragraph at lines 217--224
+
+ []
+
+[6]
+Underfull \hbox (badness 10000) in paragraph at lines 226--228
+
+ []
+
+
+Underfull \hbox (badness 10000) in paragraph at lines 229--231
+
+ []
+
+
+Underfull \hbox (badness 10000) in paragraph at lines 235--241
+
+ []
+
+
+Underfull \hbox (badness 10000) in paragraph at lines 243--244
+
+ []
+
+[7]
+Underfull \hbox (badness 10000) in paragraph at lines 257--258
+
+ []
+
+
+Underfull \hbox (badness 10000) in paragraph at lines 259--261
+
+ []
+
+[8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22]
+[23] [24] [25]
+Underfull \hbox (badness 1603) in paragraph at lines 1227--1227
+[] $\OML/cmm/m/it/10.95 LSDelete \OMS/cmsy/m/n/10.95   fh\OML/cmm/m/it/10.95 se
+q[]; Dat[]\OMS/cmsy/m/n/10.95 ijh\OML/cmm/m/it/10.95 seq[]; Dat[]\OMS/cmsy/m/n/
+10.95 i 2 \OML/cmm/m/it/10.95 LocalSlots; seq[] >
+ []
+
+
+Underfull \hbox (badness 1603) detected at line 1227
+[] $\OML/cmm/m/it/10.95 LSDelete \OMS/cmsy/m/n/10.95   fh\OML/cmm/m/it/10.95 se
+q[]; Dat[]\OMS/cmsy/m/n/10.95 ijh\OML/cmm/m/it/10.95 seq[]; Dat[]\OMS/cmsy/m/n/
+10.95 i 2 \OML/cmm/m/it/10.95 LocalSlots; seq[] >
+ []
+
+[26]
+Underfull \hbox (badness 10000) in paragraph at lines 1301--1301
+[] $\OML/cmm/m/it/10.95 LstSlt[] \OMS/cmsy/m/n/10.95  $ \OT1/cmr/m/sc/10.95 Up-
+date-LastMes-
+ []
+
+
+Underfull \hbox (badness 10000) detected at line 1301
+[] $\OML/cmm/m/it/10.95 LstSlt[] \OMS/cmsy/m/n/10.95  $ \OT1/cmr/m/sc/10.95 Up-
+date-LastMes-
+ []
+
+[27]
+Overfull \vbox (27.29413pt too high) has occurred while \output is active []
+
+
+[28]
+Underfull \hbox (badness 2376) in paragraph at lines 1385--1385
+[] $\OML/cmm/m/it/10.95 smallestseq \OMS/cmsy/m/n/10.95   \OML/cmm/m/it/10.95 s
+eq$ \OT1/cmr/m/n/10.95 such that $\OMS/cmsy/m/n/10.95 h\OML/cmm/m/it/10.95 seq;
+ DE\OMS/cmsy/m/n/10.95 i 2 \OML/cmm/m/it/10.95 LocalSlots \OMS/cmsy/m/n/10.95 ^
+
+ []
+
+
+Underfull \hbox (badness 2359) detected at line 1385
+[] $\OML/cmm/m/it/10.95 smallestseq \OMS/cmsy/m/n/10.95   \OML/cmm/m/it/10.95 s
+eq$ \OT1/cmr/m/n/10.95 such that $\OMS/cmsy/m/n/10.95 h\OML/cmm/m/it/10.95 seq;
+ DE\OMS/cmsy/m/n/10.95 i 2 \OML/cmm/m/it/10.95 LocalSlots \OMS/cmsy/m/n/10.95 ^
+
+ []
+
+[29]
+Underfull \hbox (badness 2376) in paragraph at lines 1430--1430
+[] $\OML/cmm/m/it/10.95 smallestseq \OMS/cmsy/m/n/10.95   \OML/cmm/m/it/10.95 s
+eq$ \OT1/cmr/m/n/10.95 such that $\OMS/cmsy/m/n/10.95 h\OML/cmm/m/it/10.95 seq;
+ DE\OMS/cmsy/m/n/10.95 i 2 \OML/cmm/m/it/10.95 LocalSlots \OMS/cmsy/m/n/10.95 ^
+
+ []
+
+
+Underfull \hbox (badness 3482) in paragraph at lines 1430--1430
+[] $\OML/cmm/m/it/10.95 largestseq \OMS/cmsy/m/n/10.95   \OML/cmm/m/it/10.95 se
+q$ \OT1/cmr/m/n/10.95 such that $\OMS/cmsy/m/n/10.95 h\OML/cmm/m/it/10.95 seq; 
+DE\OMS/cmsy/m/n/10.95 i 2 \OML/cmm/m/it/10.95 LocalSlots \OMS/cmsy/m/n/10.95 ^
+ []
+
+
+Underfull \hbox (badness 3482) detected at line 1430
+[] $\OML/cmm/m/it/10.95 largestseq \OMS/cmsy/m/n/10.95   \OML/cmm/m/it/10.95 se
+q$ \OT1/cmr/m/n/10.95 such that $\OMS/cmsy/m/n/10.95 h\OML/cmm/m/it/10.95 seq; 
+DE\OMS/cmsy/m/n/10.95 i 2 \OML/cmm/m/it/10.95 LocalSlots \OMS/cmsy/m/n/10.95 ^
+ []
+
+
+Underfull \hbox (badness 2376) detected at line 1430
+[] $\OML/cmm/m/it/10.95 smallestseq \OMS/cmsy/m/n/10.95   \OML/cmm/m/it/10.95 s
+eq$ \OT1/cmr/m/n/10.95 such that $\OMS/cmsy/m/n/10.95 h\OML/cmm/m/it/10.95 seq;
+ DE\OMS/cmsy/m/n/10.95 i 2 \OML/cmm/m/it/10.95 LocalSlots \OMS/cmsy/m/n/10.95 ^
+
+ []
+
+[30]
+Overfull \vbox (13.69412pt too high) has occurred while \output is active []
+
+
+[31]
+Underfull \hbox (badness 10000) in paragraph at lines 1471--1471
+[] $\OML/cmm/m/it/10.95 DE[] \OMS/cmsy/m/n/10.95   \OML/cmm/m/it/10.95 DE[]\OMS
+/cmsy/m/n/10.95 [$ \OT1/cmr/m/sc/10.95 Cre-ate-Col-
+ []
+
+
+Underfull \hbox (badness 10000) detected at line 1471
+[] $\OML/cmm/m/it/10.95 DE[] \OMS/cmsy/m/n/10.95   \OML/cmm/m/it/10.95 DE[]\OMS
+/cmsy/m/n/10.95 [$ \OT1/cmr/m/sc/10.95 Cre-ate-Col-
+ []
+
+[32]
+Overfull \vbox (149.69418pt too high) has occurred while \output is active []
+
+
+[33] [34]
+Overfull \vbox (95.29416pt too high) has occurred while \output is active []
+
+
+[35]
+Overfull \vbox (95.20291pt too high) has occurred while \output is active []
+
+
+[36] [37] [38] [39] [40] (./iotcloud.aux) ) 
+Here is how much of TeX's memory you used:
+ 5802 strings out of 493089
+ 75548 string characters out of 6134842
+ 202852 words of memory out of 5000000
+ 9157 multiletter control sequences out of 15000+600000
+ 13316 words of font info for 54 fonts, out of 8000000 for 9000
+ 1141 hyphenation exceptions out of 8191
+ 38i,11n,26p,3240b,312s stack positions out of 5000i,500n,10000p,200000b,80000s
+</usr/local/texlive/2015/texmf-dist/
+fonts/type1/public/amsfonts/cm/cmbx10.pfb></usr/local/texlive/2015/texmf-dist/f
+onts/type1/public/amsfonts/cm/cmbx12.pfb></usr/local/texlive/2015/texmf-dist/fo
+nts/type1/public/amsfonts/cm/cmcsc10.pfb></usr/local/texlive/2015/texmf-dist/fo
+nts/type1/public/amsfonts/cm/cmmi10.pfb></usr/local/texlive/2015/texmf-dist/fon
+ts/type1/public/amsfonts/cm/cmmi6.pfb></usr/local/texlive/2015/texmf-dist/fonts
+/type1/public/amsfonts/cm/cmmi8.pfb></usr/local/texlive/2015/texmf-dist/fonts/t
+ype1/public/amsfonts/cm/cmr10.pfb></usr/local/texlive/2015/texmf-dist/fonts/typ
+e1/public/amsfonts/cm/cmr6.pfb></usr/local/texlive/2015/texmf-dist/fonts/type1/
+public/amsfonts/cm/cmr8.pfb></usr/local/texlive/2015/texmf-dist/fonts/type1/pub
+lic/amsfonts/cm/cmr9.pfb></usr/local/texlive/2015/texmf-dist/fonts/type1/public
+/amsfonts/cm/cmsy10.pfb></usr/local/texlive/2015/texmf-dist/fonts/type1/public/
+amsfonts/cm/cmsy8.pfb></usr/local/texlive/2015/texmf-dist/fonts/type1/public/am
+sfonts/cm/cmti10.pfb>
+Output written on iotcloud.pdf (40 pages, 245596 bytes).
+PDF statistics:
+ 187 PDF objects out of 1000 (max. 8388607)
+ 130 compressed objects within 2 object streams
+ 0 named destinations out of 1000 (max. 500000)
+ 1 words of extra memory for PDF output out of 10000 (max. 10000000)
+
diff --git a/version2/backup/doc/iotcloud.pdf b/version2/backup/doc/iotcloud.pdf
new file mode 100644 (file)
index 0000000..6feabc2
Binary files /dev/null and b/version2/backup/doc/iotcloud.pdf differ
diff --git a/version2/backup/doc/iotcloud.tex b/version2/backup/doc/iotcloud.tex
new file mode 100644 (file)
index 0000000..1d760d7
--- /dev/null
@@ -0,0 +1,1860 @@
+\documentclass[11pt]{article}\r
+\newcommand{\tuple}[1]{\ensuremath \langle #1 \rangle}\r
+\usepackage{color}\r
+\usepackage{amsthm}\r
+\usepackage{amsmath}\r
+\usepackage{graphicx}\r
+\usepackage{mathrsfs}\r
+\usepackage{amssymb}\r
+\usepackage{algpseudocode}% http://ctan.org/pkg/algorithmicx\r
+\usepackage[all]{xy}\r
+\usepackage{varwidth}\r
+\r
+\newtheorem{theorem}{Theorem}\r
+\newtheorem{prop}{Proposition}\r
+\newtheorem{lem}{Lemma}\r
+\newtheorem{defn}{Definition}\r
+\newcommand{\note}[1]{{\color{red} \bf [[#1]]}}\r
+\newcommand{\push}[1][1]{\hskip\dimexpr #1\algorithmicindent\relax}\r
+\newcommand*\xor{\mathbin{\oplus}}\r
+\algnewcommand{\LeftComment}[1]{\Statex \(\triangleright\) #1}\r
+\begin{document}\r
+\r
+\r
+\setlength\parindent{0pt} % Removes all indentation from paragraphs - comment this line for an assignment with lots of text\r
+\r
+\r
+\section{\textbf{Introduction}}\r
+\r
+\r
+\section{Approach}\r
+\r
+\subsection{Keys}\r
+\r
+Each device has: user id + password\r
+\r
+Server login is:\r
+hash1(user id), hash1(password)\r
+\r
+Symmetric Crypto keys is:\r
+hash2(user id | password)\r
+\r
+Server has finite length queue of entries + max\_entry\_identifier +\r
+server login key\r
+\r
+\subsection{Entry layout}\r
+Each entry has:\r
+\begin{enumerate}\r
+\item Sequence identifier\r
+\item Random IV (if needed by crypto algorithm)\r
+\item Encrypted payload\r
+\end{enumerate}\r
+\r
+Payload has:\r
+\begin{enumerate}\r
+\item Sequence identifier\r
+\item Machine id (most probably something like a 64-bit random number \r
+that is self-generated by client)\r
+\item HMAC of previous slot\r
+\item Data entries\r
+\item HMAC of current slot\r
+\end{enumerate}\r
+\r
+A data entry can be one of these:\r
+\begin{enumerate}\r
+    \item A transaction:\r
+        \begin{itemize}\r
+            \item Contains a sequence number, a set of key value pair updates and a guard condition that can be evaluated.\r
+            \item Must have the same arbitrator for all its key value pair updates and reads within the guard condition\r
+        \end{itemize}\r
+    \r
+    \item A Commit\r
+        \newline{Commits a transaction into the block chain.  Until a transaction is committed, no client can be sure if that transaction's key value updates will be used to update the state of the system.  Once an arbitrator commits a transaction then that transaction becomes a permanent state change in the system.  Transactions should be committed and aborted in order of their sequence numbers.}\r
+    \r
+    \item An Abort\r
+        \newline{An abort is used to show that a transactions key value update should not be used in the state change of the system.  This occurs when the guard of a transaction evaluates to false meaning that the conditions under-which this transaction should be committed no longer exists in the system (another transaction could have been committed first that would have changed the system in a way that makes the current transaction invalid).}\r
+    \r
+    \item New Key:\r
+        \newline{This creates a new key and assignes an arbitrator to that key.  Only the first new key message for a given key is valid.  Once a new key message is inserted into the block chain it is never removed and no other new key entries for the same key name can be inserted into the block chain.}\r
+        \r
+    \item Slot sequence entry: Machine id + last message identifier \r
+        \newline {The purpose of this is to keep the record of the last slot from a certain client if a client's update has to expunge that other client's last entry from the queue. This is kept in the slot until the entry owner inserts a newer update into the queue.}\r
+\r
+    \item Queue state entry: Includes queue size \r
+        \newline {The purpose of this is for the client to tell if the server lies about the number of slots in the queue, e.g. if there are 2 queue state entry in the queue, e.g. 50 and 70, the client knows that when it sees 50, it should expect at most 50 slots in the queue and after it sees 70, it should expect 50 slots before that queue state entry slot 50 and at most 70 slots. The queue state entry slot 70 is counted as slot number 51 in the queue.}\r
+\r
+    \item Collision resolution entry: message identifier + machine id of a collision winner\r
+        \newline {The purpose of this is to keep keep track of the winner of all the collisions until all clients have seen the particular entry.}\r
+\end{enumerate}\r
+\r
+\subsection{Live status}\r
+\r
+Live status of entries:\r
+\begin{enumerate}\r
+    \item Transaction is live if it has not been committed or aborted yet.\r
+    \r
+    \item Abort is live until the machine ID that created the transaction that is being aborted inserts into the block chain a message with a sequence number greater than the abort (that client sees the abort).\r
+        \r
+    \item Commit is dead if for all key value updates in the commit there is a commit with the same key value update that is newer (larger sequence number).  The committing client (arbitrator) will see those newer commits since it is the one that generates them.\r
+    \r
+    \item New Key messages are always kept alive.  Keys can not be deleted.  Deleted keys will cause arbitration to fail if a key is deleted then reassigned to a new client device for arbitration.\r
+    \r
+    \item Slot sequence number (of either a message version data or user-level data) is dead if there is a newer slot from the same machine.\r
+\r
+    \item Queue state entry is dead if there is a newer queue state entry.\r
+    {In the case of queue state entries 50 and 70, this means that queue state entry 50 is dead and 70 is live. However, not until the number of slots reaches 70 that queue state entry 50 will be expunged from the queue.  Further all entries before the 50 entry will also not be expunged until the queue size has reached 70}\r
+\r
+    \item Collision resolution entry is dead if this entry has been seen by all clients after a collision happens.\r
+\end{enumerate}\r
+\r
+When data is at the end of the queue ready to expunge, if:\r
+\begin{enumerate}\r
+    \item If any entry is not dead it must be reinserted into the queue.\r
+\r
+    \item If the slot sequence number is not dead, then a message sequence entry must be inserted.\r
+\end{enumerate}\r
+\r
+\paragraph{Validation procedure on client:}\r
+\begin{enumerate}\r
+    \item Decrypt each new slot in order.\r
+    \item For each slot:\r
+        (a) check its HMAC, and\r
+        (b) check that the previous entry HMAC field matches the previous entry (in case of a gap do not check for slots on gap margins).\r
+    \item That no slots are slots we have seen before (server trying to pass old slots).    \r
+    \r
+    \item For all other machines, check that the latest sequence number is at least as large (never goes backwards).\r
+    \r
+    \item That the queue has a current queue state entry.\r
+    \r
+    \item That the number of entries received is consistent with the size specified in the queue state entry and/or the queue is growing in size.\r
+\end{enumerate}\r
+\r
+\subsection{Resizing Queue}\r
+Client can make a request to resize the queue. This is done as a write that combines:\r
+  (a) a slot with the message, and (b) a request to the server. The queue can only be expanded, never contracted; attempting to decrease the size of the queue will cause future clients to throw an error.\r
+\r
+\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+\subsection{The Arbitrator}\r
+Each key has an arbitrator that makes the final decision when it comes to whether a specific transaction containing that key updates the state of the system or is aborted.  This ensures that clients can make offline updates and then push those updates to the server at a later time.  The arbitrator then tries to merge those updates and if possible will commit them into the current working state of the system.  If not possible then the arbitrator will abort that transaction.  The arbitrator arbitrates on transactions in order of transaction sequence number.\r
+\r
+\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\section{Server Algorithm}\r
+$s \in SN$ is a sequence number\\\r
+$sv \in SV$ is a slot's value\\\r
+$slot_s = \tuple{s, sv} \in SL \subseteq SN \times SV$ \\ \\\r
+\textbf{State} \\\r
+\textit{SL = set of live slots on server} \\\r
+\textit{max = maximum number of slots (input only for resize message)} \\\r
+\textit{n = number of slots} \\ \\\r
+\textbf{Helper Function} \\\r
+$MaxSlot(SL_s)= \tuple{s, sv} \mid \tuple{s, sv}\r
+\in SL_s \wedge \forall \tuple{s_s, sv_s} \in SL_s, s \geq s_s$ \\\r
+$MinSlot(SL_s)= \tuple{s, sv} \mid \tuple{s, sv} \r
+\in SL_s \wedge \forall \tuple{s_s, sv_s} \in SL_s, s \leq s_s$ \\\r
+$SeqN(slot_s = \tuple{s, sv})=s$ \\\r
+$SlotVal(slot_s = \tuple{s, sv})=sv$ \\\r
+\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Get Slot:}\\\r
+Returns to the client the slots that have a sequence number that is greater than or equal to the sequence number that is in the requese.\\\r
+\begin{algorithmic}[1]\r
+\Function{GetSlot}{$s_g$}\r
+\State \Return{$\{\tuple{s, sv} \in SL \mid s \geq s_g\}$}\r
+\EndFunction\r
+\end{algorithmic}\end{varwidth}% \r
+}\r
+\r
+\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Get Slot:}\\\r
+Puts a slot in the server memory if the slot has the correct sequence number.  Also resizes the server memory if needed.\\\r
+\begin{algorithmic}[1]\r
+\Function{PutSlot}{$s_p,sv_p,max'$}\r
+\If{$(max' \neq \emptyset)$}  \Comment{Resize}\r
+\State $max \gets max'$\r
+\EndIf\r
+\State $\tuple{s_n,sv_n} \gets MaxSlot(SL)$\Comment{Last sv}\r
+%\State $s_n \gets SeqN(\tuple{s_n,sv_n})$\r
+\If{$(s_p = s_n + 1)$}\r
+    \If{$n = max$}\r
+        \State $\tuple{s_m,sv_m} \gets MinSlot(SL)$\Comment{First sv}\r
+        \State $SL \gets SL - \{\tuple{s_m,sv_m}\}$\r
+    \Else \Comment{$n < max$}\r
+        \State $n \gets n + 1$\r
+    \EndIf\r
+    \State $SL \gets SL \cup \{\tuple{s_p,sv_p}\}$\r
+    \State \Return{$(true,\emptyset)$}\r
+\Else\r
+    \State \Return{$(false,\{\tuple{s,sv}\in SL \mid \r
+    s \geq s_p\})$}\r
+\EndIf\r
+\EndFunction\r
+\end{algorithmic}\end{varwidth}% \r
+}\r
+\r
+\r
+\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\section{\textbf{Client}}\r
+\r
+\subsection{\textbf{Client Notation Conventions}}\r
+$k$ is key of entry \\\r
+$v$ is value of entry \\\r
+$size$ is a size (target size of the current block chain) \\\r
+$kv$ is a key-value pair $\tuple{k,v}$ \\\r
+$KV$ is a set of $kv$ \\\r
+$id$ is a machine ID \\\r
+$seq$ is a sequence number \\\r
+$hmac_p$ is the HMAC value of the previous slot \\\r
+$hmac_c$ is the HMAC value of the current slot \\\r
+$Guard$ is a set of$ \tuple{k,v,$logical operator$}$ which can be evaluated to a boolean \\\r
+\r
+$trans$ is a transaction entry , $\tuple{seq, id, KV, Guard}$  \\\r
+$lastmsg$ is a last message entry, $\tuple{seq, id}$ \\\r
+$qstate$ is a queue state entry, $\tuple{size}$ \\\r
+$colres$ is a collision resolution entry, $\tuple{id, seq_{old}, seq_{new}, true \lor false}$ \\\r
+$newkey$ is a new key entry, $\tuple{k, id}$, $id$ is ID of arbitrator \\\r
+$commit$ is a commit transaction entry, $\tuple{seq_{trans},KV}$, id is id of arbitrator \\\r
+$abort$ is an abort transaction entry, $\tuple{seq_{trans},id_{trans}}$ \\\r
+\r
+\r
+$de$ is a data entry that can one of: $trans$, $lastmsg$, $qstate$, $colres$, $newkey$, $commit$, $abort$ \\\r
+$DE$ is a set of all data entries, possibly of different types, in a single message, set of $de$\\\r
+\r
+$slotDat = \tuple{seq,id,DE,hmac_p,hmac_c}$ \\\r
+$slot = \tuple{seq, Encrpt(slotDat)}$\\\r
+\r
+\subsection{\textbf{Client State}}\r
+\r
+\subsubsection{Constants}\r
+$LOCAL\_ID$ = machine ID of this client.\\\r
+$RESIZE\_THRESH\_PERCENT$ = percent of slots that need to have live data to trigger a resize.\\\r
+$RESIZE\_PERCENT$ = percent that we should grow the block chain to.\\\r
+$DATA\_ENTRY\_SET\_MAX\_SIZE$ = max size that a data entry set can have (in bytes).\\\r
+$DEAD\_SLOT\_COUNT$ = number of slots to keep dead if possible at the end of the block chain.\\\r
+$MAX\_RESCUE\_SKIPS$ = number of skips that are allowed when saving data entries.\\\r
+\r
+\subsubsection{Primitive Variables}\r
+$max\_size$ = max size of the block chain\\\r
+\r
+\subsubsection{Sets and Lists}\r
+\r
+$PendingTransQueue$ = Queue of pending transactions that need to be pushed to the block chain, $\tuple{PendingTrans}$\\\r
+$PendingTrans= \tuple{KV, Guard} = \tuple{$set of key value pairs, set of guard conditions$}$.\\\r
+$Arbitrator$ = set of $\tuple{k,id}$ containing the key and its arbitrating device.\\\r
+$LastSlot$ = set of $\tuple{id, seq}$ containing the machine ID and the largest sequence number from that machine ID.\\\r
+$LocalSlots$ = set of slots that are in the clients local buffer (initially $\emptyset$), data is decrypted.\\\r
+$RejectedSlotList$ = ordered list of the sequence numbers of slots that this client tried to insert but were rejected.\\\r
+$CommittedKV$ = set of committed key value pairs (initially $\emptyset$).\\\r
+$SpeculatedKV$ = set of speculated key value pairs (initially $\emptyset$).\r
+\r
+\subsection{Helper Functions}\r
+The following helper functions are needed:\\\r
+\r
+$MaxSlot(SL_s)= \tuple{s, sv} \mid \tuple{s, sv} \in SL_s \wedge \forall \tuple{s_s, sv_s} \in SL_s, s \geq s_s$ \\\r
+$MinSlot(SL_s)= \tuple{s, sv} \mid \tuple{s, sv} \in SL_s \wedge \forall \tuple{s_s, sv_s} \in SL_s, s \leq s_s$ \\\r
+\r
+\r
+% Get Size\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Get Byte Size:}\\\r
+Get the size in bytes of the thing that is passed in.\\\r
+\begin{algorithmic}[1]\r
+\Function{GetSize}{$a$}\r
+    \State \Return{Size in bytes of $a$}\r
+\EndFunction\r
+\end{algorithmic}\end{varwidth}% \r
+}\r
+\r
+% Error\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{ Error:}\\\r
+Prints an error message and halts the execution of the client.\\\r
+\begin{algorithmic}[1]\r
+\Function{Error}{$msg$}\r
+    \State $Print(msg)$\r
+    \State $Halt()$\r
+\EndFunction\r
+\end{algorithmic}\end{varwidth}% \r
+}\r
+\r
+% Get Next Sequence Number\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Get Next Sequence Number:}\\\r
+Get the next sequence number for insertion into the block chain.\\\r
+\begin{algorithmic}[1]\r
+\Function{GetNextSeq}{$k$}\r
+    \LeftComment{Get the largest known sequence number}\r
+    \State $seq_{ret} \gets seq$ such that $\tuple{id, seq}\in LastSlo \land (\forall \tuple{id', seq'} \in LastSlo, seq \geq seq')$\\\r
+    \r
+    \LeftComment{Add one to the largest seq number to generate the new seq number}\r
+    \State \Return{$seq_{ret} + 1$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Get Arbitrator\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Get Arbitrator:}\\\r
+Get the arbitrator for a given key.\\\r
+\begin{algorithmic}[1]\r
+\Function{GetArbitrator}{$k$}\r
+    \State $\tuple{k_1,id_1} \gets \tuple{k_2,id_2} $ \textit{such that} $ \tuple{k_2,id_2} \in Arbitrator \land k_2=k$\r
+    \State \Return{$id_1$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Get Arbitrator KV\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Get Arbitrator for KV Set:}\\\r
+Get the arbitrator for a given key value set.\\\r
+\begin{algorithmic}[1]\r
+\Function{GetArbitratorKV}{$KV$}\r
+    \State $\tuple{k,v} \gets \tuple{k',v'}$ such that $\tuple{k',v'} \in KV$\r
+    \State $\tuple{k_1,id_1} \gets \tuple{k_2,id_2} $ \textit{such that} $ \tuple{k_2,id_2} \in Arbitrator \land k_2=k$\r
+    \State \Return{$id_1$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Check Transaction arbitrator\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Check Arbitrator for a Transaction:}\\\r
+Check that the arbitrators for a given set are all the same arbitrator.\\\r
+\begin{algorithmic}[1]\r
+\Function{CheckArbitrator}{$PendingTrans_a$}\r
+    \State $id_{arb} \gets NULL$\\\r
+    \State $\tuple{KV_a, Guard_a} \gets PendingTrans_a$\r
+    \r
+    \ForAll{$\tuple{k',v'} \in KV_a$}\r
+        \State $id' \gets$ \Call{GetArbitrator}{$k'$}\\\r
+        \r
+        \If{$id_{arb} = NULL$}  \r
+            \State $id_{arb} \gets id'$\r
+        \ElsIf{$id' \neq id_{arb}$} \Comment{Check all arbitrators are the same}\r
+            \State \Call{Error}{"Multiple arbitrators for key values in transaction."}\r
+        \EndIf\r
+    \EndFor\r
+    \r
+    \ForAll{$\tuple{k',v', lop'} \in Guard_a$}\r
+        \State $id' \gets$ \Call{GetArbitrator}{$k'$}\\\r
+        \r
+        \If{$id_{arb} = NULL$}  \r
+            \State $id_{arb} \gets id'$\r
+        \ElsIf{$id' \neq id_{arb}$} \Comment{Check all arbitrators are the same}\r
+            \State \Call{Error}{"Multiple arbitrators for key values in transaction."}\r
+        \EndIf\r
+    \EndFor\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Get all Commits\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Get all Commits:}\\\r
+Get all commits that are currently in the local block chain.  Iterate over all the local slots and extract all the commits from each slot.\\\r
+\begin{algorithmic}[1]\r
+\Function{GetCommits}{$ $}\r
+    \State $ComSet \gets \emptyset$ \Comment{Set of the commits}\\\r
+        \r
+    \LeftComment{Iterate over all the slots saved locally}\r
+    \ForAll{$\tuple{s_1', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \in LocalSlots$}\r
+        \State $ComSet \gets ComSet \cup \{c |c \in DE',c$is a $commit\}$\r
+    \EndFor\r
+    \State \Return{$ComSet$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Get all Transactions\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Get all Transactions:}\\\r
+Get all transactions that are currently in the local block chain.  Iterate over all the local slots and extract all the transactions from each slot.\\\r
+\begin{algorithmic}[1]\r
+\Function{GetTrans}{$ $}\r
+    \State $TransSet \gets \emptyset$ \Comment{Set of the trans}\\\r
+        \r
+    \LeftComment{Iterate over all the slots saved locally}\r
+    \ForAll{$\tuple{s_1', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \in LocalSlots$}\r
+        \State $TransSet \gets TransSet \cup \{c |c \in DE',c$is a $trans\}$\r
+    \EndFor\r
+    \State \Return{$TransSet$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Get all aborts\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Get all aborts:}\\\r
+Get all aborts that are currently in the local block chain.  Iterate over all the local slots and extract all the aborts from each slot.\\\r
+\begin{algorithmic}[1]\r
+\Function{GetAborts}{$ $}\r
+    \State $AbrtSet \gets \emptyset$ \Comment{Set of the aborts}\\\r
+        \r
+    \LeftComment{Iterate over all the slots saved locally}\r
+    \ForAll{$\tuple{s_1', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \in LocalSlots$}\r
+        \State $AbrtSet \gets AbrtSet \cup \{c |c \in DE',c$is a $abort\}$\r
+    \EndFor\r
+    \State \Return{$AbrtSet$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Get all Queue States\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Get all queue states:}\\\r
+Get all qstates that are currently in the local block chain.  Iterate over all the local slots and extract all the qstates from each slot.\\\r
+\begin{algorithmic}[1]\r
+\Function{GetQStates}{$ $}\r
+    \State $QSet \gets \emptyset$ \Comment{Set of the qstates}\\\r
+        \r
+    \LeftComment{Iterate over all the slots saved locally}\r
+    \ForAll{$\tuple{s_1', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \in LocalSlots$}\r
+        \State $QSet \gets QSet \cup \{c |c \in DE',c$is a $qstate\}$\r
+    \EndFor\r
+    \State \Return{$QSet$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Get all Last Messages States\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Get all last message data entrues:}\\\r
+Get all last msg that are currently in the local block chain.  Iterate over all the local slots and extract all the last msg from each slot.\\\r
+\begin{algorithmic}[1]\r
+\Function{GetLastMsg}{$ $}\r
+    \State $LMSet \gets \emptyset$ \Comment{Set of the last msg}\\\r
+        \r
+    \LeftComment{Iterate over all the slots saved locally}\r
+    \ForAll{$\tuple{s_1', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \in LocalSlots$}\r
+        \State $LMSet \gets LMSet \cup \{c |c \in DE',c$is a $lastmsg\}$\r
+    \EndFor\r
+    \State \Return{$LMSet$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Check Queue State Live\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Check Queue State Live:}\\\r
+A queue state is dead if there is another queue state data entry that has a larger queue state.\\\r
+\begin{algorithmic}[1]\r
+\Function{CheckQStateLive}{$qstate_a$}\r
+    \State $\tuple{size_a} \gets qstate_a$\r
+    \State $AllQStates \gets$ \Call{GetQState}{} \Comment{Get all the qstates} \\\r
+    \r
+    \If{$\exists \tuple{size'} \in AllQStates, size' > size_a$}\r
+        \State \Return{false}\r
+    \EndIf\r
+    \State \Return{true}\r
+    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Check Commit Live\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Check Commit Live:}\\\r
+A commit is dead if for every key value pair in the commit there is a commit with a larger transaction sequence number that has a key value pair with the same key.\\\r
+\begin{algorithmic}[1]\r
+\Function{CheckCommitLive}{$commit_a$}\r
+    \State $\tuple{seq_{a_{trans}},KV_a} \gets commit_a$\r
+    \State $KSet \gets \{k|\tuple{k,v} \in KV\}$\r
+    \State $AllCommits \gets$ \Call{GetCommits}{} \Comment{Get all the commits} \\\r
+    \r
+    \LeftComment{Iterate all commits that are newer in time}\r
+    \ForAll{$\tuple{seq_{trans}',KV'}\in AllCommits, seq_{trans}' > seq_{a_{trans}}$}\r
+        \State $KVSet \gets KVSet \setminus \{k|\tuple{k,v} \in KV'\}$\\\r
+        \r
+        \If{$KVSet = \emptyset$}\r
+            \State \Return{false} \Comment{All keys have a newer commit}\r
+        \EndIf\r
+    \EndFor\r
+    \State \Return{true} \Comment{If got here then some keys still live}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Check Last Message Live\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Check Last Message Live:}\\\r
+The last message is dead if the device in question pushed a slot that has a larger sequence number than the one recorded in the last message data entry. \\\r
+\begin{algorithmic}[1]\r
+\Function{CheckLastMsgLive}{$lastmsg_a$}\r
+    \State $\tuple{seq_a, id_a} \gets lastmsg_a$\\\r
+    \r
+    \If{$\exists \tuple{id', seq'} \in LastSlot, id'=id_a \land seq' > seq_a$}\r
+        \State \Return{false}\r
+    \EndIf\r
+    \State \Return{True}    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+%Check Collision Resolution Live\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Check Collision Resolution Live:}\\\r
+Check if a collision resolution data entry is live or not.  This done by checking if all clients that we know about have seen the collision resolution entry.  This is checked by seeing if all devices have inserted a message with a larger sequence number into the block chain.\\\r
+\begin{algorithmic}[1]\r
+\Function{CheckColResLive}{$colres_a$}\r
+    \State $\tuple{id_a, seq_{a_{old}}, seq_{a_{new}}, equal_a} \gets colres_a$\\\r
+    \r
+    \If{$\forall \tuple{id', seq'} \in LastSlot, seq' \geq seq_{a_{new}}$}\r
+        \State \Return{false}\r
+    \EndIf\r
+    \State \Return{true}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Check New Key Live\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Check New Key Live:}\\\r
+A new key data entry is always live.\\\r
+\begin{algorithmic}[1]\r
+\Function{CheckNewkeyLive}{$newkey_a$}\r
+    \State \Return{True}    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Check Abort Live\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Check Abort Live:}\\\r
+Check if an abort data entry is live or not.  Abort is dead if the device whos transaction was aborted sees the abort.  This is checked by seeing if that device inserted a slot into the block chain which has a sequence numberl that is larger than the aborts sequence number.\\\r
+\begin{algorithmic}[1]\r
+\Function{CheckAbortLive}{$abort_a, seq_a$}\r
+    \State $\tuple{seq_{a_{trans}},id_a} \gets abort_a$\\\r
+    \r
+    \LeftComment{The device whos transaction was aborted saw the abort}\r
+    \If{$\exists \tuple{id', seq'} \in LastSlot, id'=id_a \land seq' > seq_a$}\r
+        \State \Return{false}\r
+    \EndIf\r
+    \State \Return{True}    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Check Transaction Live\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Check Transaction Live:}\\\r
+A transaction is dead if there is an abort for that transaction or if there is a commit for that a transaction that came after this transaction.  Since transactions must be committed in order of there insertion, seeing a transaction that is committed and has a larger sequence number than the transaction in question means that the transaction in question was committed at some point.\\\r
+\begin{algorithmic}[1]\r
+\Function{CheckTransLive}{$trans_a$}\r
+    \State $\tuple{seq_a, id_a, KV_a, Guard_a} \gets trans_a$\r
+    \State $AllCommits \gets$ \Call{GetCommits}{} \Comment{Get all the commits}\r
+    \State $AllAborts \gets$ \Call{GetAborts}{} \Comment{Get all the aborts} \\\r
+    \r
+    \If{$\exists \tuple{seq_{abrt}',seq_{trans}',id'} \in AllAborts, seq_{trans}' = seq_a$}\r
+        \State \Return{false}\r
+    \ElsIf{$\exists \tuple{seq_{trans}',KV'} \in AllCommits, seq_{trans}' \geq seq_a$}\r
+        \State \Return{false}\r
+    \EndIf\r
+    \State \Return{true}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Check Live\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Check Live:}\\\r
+Checks if a data entry is live based on its type.\\\r
+\begin{algorithmic}[1]\r
+\Function{CheckLive}{$datentry, seq$}\r
+    \If{$datentry$ is a $commit$}\r
+        \State \Return{\Call{CheckCommitLive}{$datentry$}}\\r
+    \ElsIf{$datentry$ is a $abort$}\r
+        \State \Return{\Call{CheckAbortLive}{$datentry, seq$}}\\r
+    \ElsIf{$datentry$ is a $trans$}\r
+        \State \Return{\Call{CheckTransLive}{$datentry$}}\\r
+    \ElsIf{$datentry$ is a $lastmsg$}\r
+        \State \Return{\Call{CheckLastMsgLive}{$datentry$}}\\r
+    \ElsIf{$datentry$ is a $colres$}\r
+        \State \Return{\Call{CheckColResLive}{$datentry$}}\\r
+    \ElsIf{$datentry$ is a $qstate$}\r
+        \State \Return{\Call{CheckQStateLive}{$datentry$}}\r
+    \ElsIf{$datentry$ is a $newkey$}\r
+        \State \Return{\Call{CheckNewkeyLive}{$datentry$}}\r
+    \Else\r
+        \State \Call{Error}{"Unknown data entry type."}\r
+    \EndIf\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Slot Has Live\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Slot Has Live:}\\\r
+Check if the slot has any live data entries in it. Do this by looking at all the data entries in the slot and checking if they are live\\\r
+\begin{algorithmic}[1]\r
+\Function{SlotHasLive}{$slot_a$}\r
+    \State $\tuple{s_1, \tuple{seq_2,id,DE,hmac_p,hmac_c}} \in LocalSlots$\r
+    \r
+    \ForAll{$datentry \in DE$}\r
+        \If{\Call{CheckLive}{$datentry, s_1$}} \Comment{an entry is alive}\r
+            \State \Return{true}\r
+        \EndIf\r
+    \EndFor\r
+    \r
+    \State \Return{false} \Comment{All entries were dead}    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Calculate Resize Threshold\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Calculate Resize Threshold:}\\\r
+Calculate a threshold for how many slots need to have live data entries in them for a resize to take place.\\\r
+\begin{algorithmic}[1]\r
+\Function{CalcResizeThresh}{$maxsize$}\r
+    \State \Return{$\left \lfloor {maxsize * RESIZE\_THRESH\_PERCENT} \right \rfloor$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Calculate Block Chain New Size\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Calculate Block Chain New Size:}\\\r
+Calculate the new size of the block chain which we need if we are to resize the data structure.\\\r
+\begin{algorithmic}[1]\r
+\Function{CalcNewSize}{$maxsize$}\r
+    \State \Return{$\left \lceil {maxsize * RESIZE\_THRESH\_PERCENT} \right \rceil$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Should Resize\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Should Resize:}\\\r
+Check if the block should resize based on some metric of how many slots in the block chain are filled with live data. \\\r
+\begin{algorithmic}[1]\r
+\Function{ShouldResize}{$ $}\r
+    \State $LiveSlots \gets \{slot_s|slot_s \in LocalSlots \land $\Call{SlotHasLive}{$slot_s$}$\}$\r
+    \State $resizethreshold \gets $ \Call{CalcResizeThresh}{$max\_size$}\r
+    \State \Return{$|LiveSlots| \geq resizethreshold$} \Comment{If passes threshold then resize}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Create Queue State \r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Create Queue State:}\\\r
+Generate a queue state data entry.\\\r
+\begin{algorithmic}[1]\r
+\Function{CreateQState}{$size_a$}\r
+    \State \Return{$\tuple{size_a}$}    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Create Abort\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Create Abort:}\\\r
+Generate a abort data entry.\\\r
+\begin{algorithmic}[1]\r
+\Function{CreateAbort}{$seq_a, id_a$}\r
+    \State \Return{$\tuple{seq_a, id_a}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Create Collision\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Create ColRes:}\\\r
+Generate a colres data entry.\\\r
+\begin{algorithmic}[1]\r
+\Function{CreateColRes}{$is_a, seq_{a_{old}}, seq_{a_{new}}, isequal_a$}\r
+    \State \Return{$\tuple{id_a, seq_{a_{old}}, seq_{a_{new}},}isequal_a$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+\r
+% Create Transaction\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Create Transaction:}\\\r
+Generate a transaction data entry.\\\r
+\begin{algorithmic}[1]\r
+\Function{CreateTrans}{$pendingtrans_a, seq_a$}\r
+    \State $\tuple{KV_a, Guard_a} \gets pendingtrans_a$\r
+    \State \Return{$\tuple{seq_a, LOCAL\_ID, KV_a, Guard_a}$}    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Create Commit\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Create Commit:}\\\r
+Generate a commit data entry.\\\r
+\begin{algorithmic}[1]\r
+\Function{CreateCommit}{$seq_a,KV_a$}\r
+    \State \Return{$\tuple{seq_a,KV_a}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Create New Key\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Create New Key:}\\\r
+Generate a new key data entry.\\\r
+\begin{algorithmic}[1]\r
+\Function{CreateNewKey}{$k_a, id_a$}\r
+    \State \Return{$\tuple{k_a,id_a}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Data Entry Set Has Space \r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Data Entry Set Has Space :}\\\r
+Checks if a data entry set has enough space for a new data entry to be inserted.\\\r
+\begin{algorithmic}[1]\r
+\Function{DEHasSpace}{$DE_a, de_a$}\r
+    \State $newsize \gets $ \Call{GetSize}{$DE_a$}\r
+    \State $newsize \gets newsize +$ \Call{GetSize}{$de_a$}\r
+    \State \Return{$newsize \leq DATA\_ENTRY\_SET\_MAX\_SIZE$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Create Rescued Commit\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Create Rescued Date Entry:}\\\r
+For commits only the key-value pairs that are most recent (no newer commit that has those key values in it).\\\r
+\begin{algorithmic}[1]\r
+\Function{CreateRescuedCommit}{$commit_a$}\r
+    \State $AllCommits \gets $ \Call{GetCommits}{}\r
+    \State $\tuple{seq_{a_{trans}},KV_a} \gets de_a$\r
+    \State $NewKV \gets KV_a$\\\r
+\r
+    \LeftComment{Get rid of all key values that have newer commits}\r
+    \ForAll{$\tuple{k_a, v_a} \in KV_a$}\r
+        \LeftComment{Iterate over all commits that are newer than the rescue commit}\r
+        \ForAll{$\tuple{seq', KV'} \in AllCommits, seq' > seq_{a_{trans}}$}\r
+            \If{$\exists \tuple{k', v'} \in KV', k' = k_a$}\r
+                \State $NewKV \gets NewKV \setminus \tuple{k_a, v_a}$\r
+                \State Break\r
+            \EndIf\r
+        \EndFor\r
+    \EndFor\r
+    \State \Return{$\tuple{seq_{a_{trans}}, NewKV}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Create Rescued Date Entry\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Create Rescued Date Entry:}\\\r
+Generate the data entry rescued version of the entry.  For some data entry types such as commits, the entry is not rescued as is.  For commits only the key-value pairs that are most recent (no newer commit that has those key values in it).\\\r
+\begin{algorithmic}[1]\r
+\Function{CreateRescuedEntry}{$de_a$}\r
+\r
+    \If{$de_a$is a $commit$}\r
+        \State \Return{\Call{CreateRescuedCommit}{$de_a$}}\r
+    \EndIf\r
+    \r
+    \State \Return{$de_a$} \Comment{No Modification needed}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Check Slot Hmacs\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Check Slot HMACs:}\\\r
+Check that each slot has not been tampered with by checking that the stored HMAC matches the calculated HMAC.  Also check thatthe slot number reported by the server matches the slot number of the actual slot.\\\r
+\begin{algorithmic}[1]\r
+\Function{CheckSlotsHmacAndSeq}{$Slots_a$}\r
+    \ForAll{$slot_a \in Slots_a$}\r
+        \State $\tuple{seq_{a_1}, \tuple{seq_{a_2},id_a,DE_a,hmac_{a_p},hmac_{a_c}}} \gets slot_a$\r
+        \State $calchmac \gets $ \Call{GenerateHmac}{$seq_{a_2}, id_a, DE_a, hmac_{a_p}$}\r
+    \r
+        \If{$seq_{a_1} \neq seq_{a_2}$}\r
+          \State \Call{Error}{"Slot sequence number mismatch"}\r
+        \ElsIf{$calchmac \neq hmac_{a_c}$}\r
+            \State \Call{Error}{"Slot HMAC mismatch"}\r
+        \EndIf\r
+    \EndFor\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Check HMAC Chain\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Check HMAC Chain:}\\\r
+Check that the HMAC chain has not been violated.\\\r
+\begin{algorithmic}[1]\r
+\Function{CheckHmacChain}{$Slots_a$}\r
+    \State $SlotsList \gets Slots_a$ sorted by sequence number\\  \r
+    \r
+    \r
+    \LeftComment{Check all new slots}\r
+    \ForAll{$index \in [2: |SlotsList|]$}\r
+        \State $\tuple{seq_{a_1}, \tuple{seq_{a_2},id_a,DE_a,hmac_{a_p},hmac_{a_c}}} \gets SlotList[i-1]$\r
+        \State $\tuple{seq_{b_1}, \tuple{seq_{b_2},id_b,DE_b,hmac_{b_p},hmac_{b_c}}} \gets SlotList[i]$\r
+        \r
+        \If{$hmac_{b_p} \neq hmac_{b_c}$}\r
+            \State \Call{Error}{"Invalid previous HMAC."}\r
+        \EndIf    \r
+    \EndFor\\\r
+    \r
+    \LeftComment{Check against slots that we already have in the block chain}\r
+    \If{$|LocalSlots| \neq 0$}\r
+        \State $\tuple{seq, SDE} \gets $\Call{MaxSlot}{$LocalSlots$}\r
+        \State $\tuple{seq{last_2},id_{last},DE_{last},hmac_{last_p},hmac_{last_c}} \gets SDE$\\\r
+        \r
+        \State $\tuple{seq_{a_1}, \tuple{seq_{a_2},id_a,DE_a,hmac_{a_p},hmac_{a_c}}} \gets SlotList[1]$\\\r
+\r
+        \If{$(seq_{last_2} + 1) = seq_{a_1}$}\r
+            \If{$hmac_{a_p} \neq hmac_{last_c}$}\r
+                \State \Call{Error}{"Invalid previous HMAC."}\r
+            \EndIf\r
+        \EndIf\r
+    \EndIf\r
+    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+\r
+% Check For Old Slots\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Check For Old Slots:}\\\r
+Check if the slots are not new.  Checks if the "new" slots are actually new or if they are older than the most recent slot that we have.\\\r
+\begin{algorithmic}[1]\r
+\Function{CheckOldSlots}{$Slots_a$}\r
+    \State $\tuple{seq_{new}, Dat_{new}} \gets$ \Call{MinSlot }{$Slots_a$} \Comment{Get the oldest new slot}\r
+    \State $\tuple{seq_{local}, Dat_{local}} \gets$ \Call{MaxSlot }{$LocalSlots$} \Comment{Get the newest slot seen}\\\r
+    \r
+    \If{$seq_{new} \leq seq_{local}$} \Comment{The slots were not newer than what was already seen}\r
+        \State \Call{Error}{"Server sent old slots."}\r
+    \EndIf\\\r
+    \r
+    \LeftComment{Check if slots have the same sequence number but different data entries}\r
+    \ForAll{$\tuple{seq, Dat} \in Slots_a$}\r
+        \If{$\exists \tuple{seq', Dat'} \in (LocalSlots \cup Slots_a), seq'=seq \land Dat' \neq Dat$}\r
+            \State \Call{Error}{"Slot sequence number match but data does not"}\r
+        \EndIf\r
+    \EndFor\r
+    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Get All Queue States with Sequence numbers\r
+% \noindent\fbox{%\r
+% \begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+% \textbf{Get All Queue States with Sequence numbers:}\\\r
+% Gets all the queue states with the sequence number of the slot that the queue state was inside.\r
+% \begin{algorithmic}[1]\r
+% \Function{GetQStateWithSeq}{$Slots_a$}\r
+%     \State $QSet \gets \emptyset$\\\r
+    \r
+%     \ForAll{$\tuple{seq_1', \tuple{seq_2',id',DE',hmac_p', hmac_c'}} \in Slots_a$}\r
+%         \ForAll{$de' \in DE'$}\r
+%             \If{$de'$ is a  $qstate$}\r
+%                 \State $QSet \gets QSet \cup \{\tuple{seq_1', de'}\}$\r
+%             \EndIf\r
+%         \EndFor\r
+%     \EndFor\\\r
+    \r
+%     \State \Return{$QSet$}\r
+% \EndFunction\r
+% \end{algorithmic}\r
+% \end{varwidth}% \r
+% }\r
+\r
+% Get All Queue States\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Get All Queue States:}\\\r
+Gets all the queue states from the slots that were passed in.\\\r
+\begin{algorithmic}[1]\r
+\Function{GetQState}{$Slots_a$}\r
+    \State $QSet \gets \emptyset$\\\r
+    \r
+    \ForAll{$\tuple{seq_1', \tuple{seq_2',id',DE',hmac_p', hmac_c'}} \in Slots_a$}\r
+        \ForAll{$de' \in DE'$}\r
+            \If{$de'$ is a  $qstate$}\r
+                \State $QSet \gets QSet \cup \{de'\}$\r
+            \EndIf\r
+        \EndFor\r
+    \EndFor\\\r
+    \r
+    \State \Return{$QSet$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+\r
+% Check Size With Gap\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Check Size With Gap:}\\\r
+Checks that the block chain size is correct when there is a gap in the block chain.  This check makes sure that the server is not hiding any information from the client.  If there is a gap and there is only 1 queue state in the new slot entries then there must have at least that many slots since the old slot entry must have been purged.  If there is more than 1 queue state then the block chain is still growing check the smallest max size and there should be at least that many slots. \\\r
+\begin{algorithmic}[1]\r
+\Function{CheckSizeWithGap}{$Slots_a$}    \r
+    %\State $QSSet \gets $ \Call{GetQStateWithSeq}{$Slots_a$}\r
+    %\State $\tuple{seq_{max}, size_{max}} \gets \tuple{seq, size}$ such that $\tuple{seq, size} \in QSSet \land \forall \tuple{seq', size'} \in QSSet, size \geq size'$ \Comment{Get largest size}\r
+    %\State $\tuple{seq_{min}, size_{min}} \gets \tuple{seq, size}$ such that $\tuple{seq, size} \in QSSet \land \forall \tuple{seq', size'} \in QSSet , size \leq size'$ \Comment{Get smallest size}\r
+    \r
+    \State $QSet \gets $ \Call{GetQState}{$Slots_a$}\r
+    \State $size_{max} \gets size$ such that $size \in QSet \land \forall size' \in QSet, size \geq size'$ \r
+    \State $size_{min} \gets size$ such that $size \in QSet \land \forall size' \in QSet, size \leq size'$     \r
+    \State $Slots_{oldmax} \gets \emptyset$\\\r
+\r
+    \r
+    \LeftComment{If only 1 max size then we must have all the slots for that size}\r
+    \If{$(|QSSet| = 1) \land (|Slots_a| \neq size_{max})$}\r
+        \State \Call{Error}{"Missing Slots"}\r
+    \EndIf\\\r
+    \r
+    \LeftComment{We definitely have all the slots}\r
+    \If$|Slots_a| = size_{max}$\r
+        \State \Return{} \Comment{We have all the slots}\r
+    \EndIf\\\r
+    \r
+    \LeftComment{We must have at least this many slots}\r
+    \If$|Slots_a| < size_{min}$\r
+        \State \Call{Error}{"Missing Slots"}\r
+    \EndIf\\\r
+\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Check Size\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Check Size:}\\\r
+\begin{algorithmic}[1]\r
+\Function{CheckSize}{$Slots_a$}    \r
+    \State $\tuple{seq_{old_{max}}, Dat_{old_{max}}} \gets $ \Call{MaxSlot}{$LocalSlots$}\r
+    \State $\tuple{seq_{new_{max}}, Dat_{new_{max}}} \gets $ \Call{MinSlot}{$Slots_a$}\\\r
+    \r
+    \If{$(seq_{old_{max}} + 1) = seq_{new_{max}}$}\r
+        \LeftComment{No Gap so cannot say anything about the size}\r
+        \State \Return{} \r
+    \Else \r
+        \LeftComment{Has a gap so we need to do checks}\r
+        \State \Call{CheckSizeWithGap}{$Slots_a$}\r
+    \EndIf\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+\r
+% % Initialize the expected size of the block chain\r
+% \noindent\fbox{%\r
+% \begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+% \textbf{Initialize the expected size of the block chain:}\\\r
+% Initialize the expected size of the block chain based on the size at the server.\\\r
+% \begin{algorithmic}[1]\r
+% \Function{InitExpSize}{$seq_a$}\r
+%     \State $startingsize \gets 0$\\\r
+\r
+%     \If{$seq_a < max\_size$} \Comment{Check whether saves slots are full on server}\r
+%         \State $startingsize \gets seq_a$\r
+%     \Else\r
+%         \State $startingsize \gets max\_size$\r
+%     \EndIf\\\r
+    \r
+%     \State \Return{$startingsize$}\r
+% \EndFunction\r
+% \end{algorithmic}\r
+% \end{varwidth}% \r
+% }\r
+\r
+% % Update the expected size of the block chain\r
+% \noindent\fbox{%\r
+% \begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+% \textbf{Update the expected size of the block chain:}\\\r
+% Update the expected size of the block chain.\\\r
+% \begin{algorithmic}[1]\r
+% \Function{UpdateExpSize}{$size_a$}\r
+%     \State $size_a \gets size_a + 1$\\\r
+    \r
+%     \If{$size_a > max\_size$}\Comment{Expected size $\leq max\_size$}\r
+%         \State $ssize_a \gets max_\_size$\r
+%     \EndIf\\\r
+    \r
+%     \State \Return{$size_a$}\r
+% \EndFunction\r
+% \end{algorithmic}\r
+% \end{varwidth}% \r
+% }\r
+\r
+\r
+\r
+% Update Last Message\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Process Commit Data Entry:}\\\r
+Process a commit entry.  Updates the local copy of commits.\\\r
+\begin{algorithmic}[1]\r
+\Function{UpdateLastMessage}{$seq_a, id_a, LstSlt_a, updateinglocal_a$}\r
+    \State $\tuple{id_{old}, seq_{old}} \gets \tuple{id', seq'}$ such that $\tuple{id', seq'} \in LastSlot \land id'=id$\\\r
+    \r
+    \If{$id_a = LOCAL\_ID$}\r
+        \If{$\lnot updateinglocal_a \land (seq_a \neq seq_{old})$}\r
+            \LeftComment{This client did not make any updates so its latest sequence number should not change}\r
+            \State \Call{Error}{"Mismatch on local machine sequence number"}\r
+        \EndIf\r
+    \Else\r
+        \If{$seq_{old} > seq_a$}\r
+            \State \Call{Error}{"Rollback on remote machine sequence number"}\r
+        \EndIf\r
+    \EndIf\\\r
+    \r
+    \State $LastSlot \gets LastSlot \setminus \{\tuple{id, seq} | \tuple{id, seq} \in LastSlot, id=id_a\}$\r
+    \State $LastSlot \gets LastSlot \cup \{\tuple{id_a, seq_a}\}$\r
+    \r
+    \State \Return{$LstSlt_a \setminus \{\tuple{id, seq} | \tuple{id, seq} \in LstSlt_a, id=id_a\}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Process Commit Data Entry\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Process Commit Data Entry:}\\\r
+Process a commit entry.  Updates the local copy of commits.\\\r
+\begin{algorithmic}[1]\r
+\Function{ProcessCommit}{$commit_a$}\r
+    \State $\tuple{seq_{a_{trans}},KV_a} \gets commit_a$\r
+    \State $DKV \gets \{\tuple{k,v}| \tuple{k,v} \in CommittedKV \land \tuple{k',v'}\in KV_a \land k'=k\}$\r
+    \State $CommittedKV \gets (CommittedKV \setminus DKV) \cup KV_a$\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Process Queue State Data Entry\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Process Queue State Entry:}\\\r
+Process a queue state entry. Updates the max size of the block chain\\\r
+\begin{algorithmic}[1]\r
+\Function{ProcessQState}{$qstate_a$}\r
+    \State $\tuple{size_a} \gets qstate_a$\r
+    \State $max\_size \gets size_a$ \Comment{Update the max size we can have}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Process Collision Resolution Entry\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Process Queue State Entry:}\\\r
+Process a collision resolution entry.\\\r
+\begin{algorithmic}[1]\r
+\Function{ProcessColres}{$colres_a, NewSlots_a$}\r
+    \State $\tuple{id_a, seq_{a_{old}}, seq_{a_{new}}, isequal_a}$\r
+    \State $AllSlots \gets LocalSlots \cup NewSlots_a$\r
+    \State $index \gets seq_{a_{old}}$\\\r
+    \r
+    \While{$index <= seq_{a_{new}}$}\r
+        \State $slt \gets \tuple{seq' Dat'}$ such that $\tuple{seq' Dat'} \in AllSlots \land seq'=index$\r
+        \r
+        \If{$\exists \tuple{seq' Dat'} \in AllSlots, seq' = index$}\r
+            \State $\tuple{seq, Dat} \gets \tuple{seq' Dat'}$ such that $\tuple{seq' Dat'} \in AllSlots \land seq'=index$\r
+            \State $\tuple{seq,id,DE,hmac_p,hmac_c} \gets Dat$\r
+            \If{$isequal_a \neq (id=id_a)$}\r
+                \State \Call{Error}{"Trying to insert rejected messages for slot"}\r
+            \EndIf\r
+        \EndIf\\\r
+        \State $index \gets index + 1$\r
+    \EndWhile\r
+    \r
+    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Process New Key Data Entry\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Process New Key Entry:}\\\r
+Process a queue state entry. Adds a key to the key arbitrator set\\\r
+\begin{algorithmic}[1]\r
+\Function{ProcessNewkey}{$newkey_a$}\r
+    \State $\tuple{seq_a, k_a, id_a} \gets newkey_a$\r
+    \State $Arbitrator \gets Arbitrator \cup \{\tuple{k_a,id_a}\}$\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Process Process Data Entry\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Process Data Entry:}\\\r
+Process the data entry based on what kind of entry it is.\\\r
+\begin{algorithmic}[1]\r
+\Function{ProcessDatEntry}{$slot_a, NewSlots_a,LstSlt_a$}\r
+    \If{$datentry_a$ is a $commit$}\r
+        \State \Call{ProcessCommit}{$dataentry_a$}\r
+        \r
+    \ElsIf{$datentry_a$ is a $abort$}\r
+        \LeftComment{Do Nothing in this case}\r
+        \r
+    \ElsIf{$datentry_a$ is a $trans$}\r
+        \LeftComment{Do Nothing in this case}\r
+    \r
+    \ElsIf{$datentry_a$ is a $lastmsg$}\r
+        \State $\tuple{seq_a, id_a} \gets dataentry_a$\r
+        \State $LstSlt_a \gets$ \Call{UpdateLastMessage}{$seq_a, id_a, LstSlt_a, false$}\r
+    \r
+    \ElsIf{$datentry_a$ is a $colres$}\r
+        \State \Call{ProcessColres}{$dataentry_a, NewSlots_a$}\r
+        \r
+    \ElsIf{$datentry_a$ is a $qstate$}\r
+        \State \Call{ProcessQState}{$dataentry_a$}\r
+        \r
+    \ElsIf{$datentry_a$ is a $newkey$}\r
+        \State \Call{ProcessNewkey}{$dataentry_a$}\r
+        \r
+    \Else\r
+        \State \Call{Error}{"Unknown data entry type."}\r
+    \EndIf\r
+    \r
+    \State \Return{$LstSlt_a$}    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+\r
+% Delete Local Slots\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Delete Local Slots:}\\\r
+Deletes local slots that are deleted at the server.  This keeps the size of the local block chain bounded.\\\r
+\begin{algorithmic}[1]\r
+\Function{DeleteLocalSlots}{$ $}\r
+    \State $\tuple{seq_{max}, Dat_{max}} \gets $ \Call{MaxSlot}{$LocalSlots$}\r
+    \State $seq_{min} \gets seq_{max} - max\_size$ \Comment{Min sequence number we should keep}\r
+    \State $LSDelete \gets \emptyset$\r
+        \r
+    \If{$|LocalSlots| \leq max\_size$}\r
+        \State \Return{} \Comment{Nothing to delete}\r
+    \EndIf\\\r
+    \r
+    \State $LSDelete \gets \{\tuple{seq', Dat'}|\tuple{seq', Dat'} \in LocalSlots, seq' > seq_{min}\}$\r
+    \State $LocalSlots \gets LocalSlots \setminus LSDelete$    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Create Speculative KV\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Create Speculative KV:}\\\r
+Speculates on what the most recent key value pairs will be based on the latest committed key value pairs and the uncommitted transactions.\\\r
+\begin{algorithmic}[1]\r
+\Function{SpeculateKV}{$ $}\r
+    \State $AllTrans \gets$ \Call{GetTrans}{}\r
+    \State $LiveTrans \gets \{t| t\in AllTrans, $\Call{CheckTransLive}{$t$}$\}$\r
+    \State $CurrKV \gets CommittedKV$\r
+    \State $DKV \gets \emptyset$\r
+\r
+    \ForAll{$\tuple{seq_t, id_t, KV_t, Guard_t} \in LiveTrans$ ordered by $seq'$} \r
+        \If{\Call{EvaluateGuard}{$Guard_t, CurrKV$}}\r
+            \State $DKV \gets \{\tuple{k,v}| \tuple{k,v} \in CurrKV \land \tuple{k',v'}\in KV_t \land k'=k\}$\r
+            \State $CurrKV \gets (CurrKV \setminus DKV) \cup KV_t$\r
+        \EndIf\r
+    \EndFor\r
+    \r
+    \State \Return{$CurrKV$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+\r
+% Validate and Update \r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Validate Update:}\\\r
+Validate the block chain and insert into the local block chain.\\\r
+\begin{algorithmic}[1]\r
+\Function{ValidateUpdate}{$NewSlots_a, updatinglocal_a$}\r
+    \State $\tuple{seq_{oldest}, Dat_{oldest}} \gets$ \Call{MinSlot}{$NewSlots_a$}\r
+    \State $\tuple{seq_{newest}, Dat_{newest}} \gets$ \Call{MaxSlot}{$NewSlots_a$}\r
+    \State $\tuple{seq_{local}, Dat_{local}} \gets$ \Call{MaxSlot}{$LocalSlots$}\r
+    \State $LastSlotTmp \gets LastSlot$\\\r
+    %\State $currsize \gets $\Call{InitExpSize}{$seq_{oldest}$}\\\r
+    \r
+    \State \Call{CheckSlotsHmacAndSeq}{$NewSlots_a$} \Comment{Check all the HMACs}\r
+    \State \Call{CheckHmacChain}{$NewSlots_a$} \Comment{Check HMAC Chain} \r
+    \State \Call{CheckOldSlots}{$NewSlots_a$} \Comment{Check if new slots are actually old slots} \r
+    \State \Call{CheckSize}{$NewSlots_a$} \Comment{Check if the size is correct}\\\r
+    \r
+    \ForAll{$slot_a \in NewSlots_a$ in order of sequence number}\r
+        \If{$slot_a \in LocalSlots$} \Comment{Client already has this slot}\r
+            \State $NewSlots_a \gets NewSlots_a \setminus \{slot_a\}$\r
+            \State Continue\r
+        \EndIf\\\r
+    \r
+        \State $\tuple{seq_{a_1}, \tuple{seq_{a_2},id_a,DE_a,hmac_{a_p},hmac_{a_c}}} \gets slot_a$\r
+        \State $LstSlt_a \gets$ \Call{UpdateLastMessage}{$seq_{a_1}, id_a, LstSlt_a, updatinglocal_a$}\\\r
+        \r
+        \ForAll{$de_a \in DE_a$} \Comment{Process each data entry}\r
+            \State $LstSlt_a \gets $ \Call{ProccessDatEntry}{$de_a, NewSlots_a,LstSlt_a$}\r
+        \EndFor\\\r
+    \r
+        %\State $currsize \gets $ \Call{UpdateExpSize}{$currsize$}\\\r
+        \State $LocalSlots \gets LocalSlots \cup \{slot_a\}$ \Comment{Add to local Chain}\r
+    \EndFor\\\r
+    \r
+    \If{$seq_{oldest} > (seq_{local} +1) \land LastSlotTmp \neq \emptyset$}\r
+        \LeftComment{There was a gap so there should be a complete set of information on each previously seen client}\r
+        \State \Call{Error}{"Missing records for machines"}\r
+    \EndIf\\\r
+    \r
+    \State \Call{DeleteLocalSlots}{ } \Comment{Delete old slots from local}\r
+    \State $SpeculatedKV \gets $\Call{SpeculateKV}{ } \Comment{Speculate on what will be latest KV set}\r
+    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Decrypt Validate Insert Slots\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Decrypt Validate Insert Slots:}\\\r
+Decrypts slots, validates (checks for malicious activity) slots and inserts the slots into the local block chain.\\\r
+\begin{algorithmic}[1]\r
+\Function{DecryptValidateInsert}{$NewSlots_a, updatinglocal_a$}\r
+    \State $DecryptedSlots \gets \emptyset$\r
+    \State $DDat \gets NULL$\\\r
+    \r
+    \ForAll{$\tuple{seq', EDat'} \in NewSlots_a$}\r
+        \State $DDat \gets $ \Call{Decrypt}{$EDat'$}\r
+        \State $DecryptedSlots \gets DecryptedSlots \cup \tuple{seq',DDat}$\r
+    \EndFor\\\r
+    \State \Call{ValidateUpdate}{$DecryptedSlots, updatinglocal_a$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Check and Create Last Message Data Entry\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Check and Create Last Message Data Entry:}\\\r
+Check if a last message entry needs to be created for this slot and if so create it.  The check is done by checking if there are any newer slots with the same id or if there is already a last message slot with a newer sequence number\\\r
+\begin{algorithmic}[1]\r
+\Function{CheckCreateLastMsgEntry}{$seq_a, id_a$}\r
+    \State $AllLastMsg \gets$ \Call{GetLastMsg}{}\\\r
+    \r
+    \LeftComment{Already Has one}\r
+    \If{$\exists  \tuple{seq', id'} \in AllLastMsg, id_a=id' \land seq'=seq_a$}\r
+        \State \Return{$\{\}$}\\\r
+    \EndIf\\\r
+    \r
+    \LeftComment{Not latest slot from that client}\r
+    \If{$\exists  \tuple{seq_1', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \in LocalSlots, id_a=id' \land seq_1'>seq_a$}\r
+        \State \Return{$\{\}$}\\\r
+    \EndIf\\\r
+    \r
+    \r
+    \State \Return{$\{\tuple{seq_a, id_a}\}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Mandatory Rescue\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Mandatory Rescue:}\\\r
+This rescue is mandatory before any types of data entries (excpet queue states) can be placed into the data entry section of the new slot.  Returns the data entry Set or null if the first slot could not be cleared (the live data in that slot could not fit in this current slot). \\\r
+\begin{algorithmic}[1]\r
+\Function{MandatoryRescue}{$DE_a$}\r
+    \State $smallestseq \gets seq$ such that $\tuple{seq, DE}\in LocalSlots \land (\forall \tuple{seq', DE'} \in LocalSlots, seq \leq seq')$\r
+    \State $cseq \gets smallestseq$\\\r
+    \r
+    \LeftComment{Check the least slots to rescue and live entries}\r
+    \While{$cseq < (smallestseq + DEAD\_SLOT\_COUNT)$}\r
+        \State $currentslot \gets s'$ such that $\tuple{s',DE'} \in LocalSlots \land s' = cseq$\r
+        \State $\tuple{seq', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \gets currentslot$\r
+        \State $DE' \gets DE' \cup$ \Call{CheckCreateLastMsgEntry}{$seq', id'$} \Comment{Get the last message too if we need it}\\\r
+        \r
+        \ForAll{$de \in DE'$} \Comment{Iterate over all the entries}\r
+            \If{\Call{CheckLive}{$de, cseq$}} \Comment{data entry is live}\r
+                \State $de \gets $ \Call{CreateRescuedEntry}{de} \Comment{Resize entry if needed}\r
+                \If{\Call{DEHasSpace}{$DE_a, de$}}\r
+                    \State $DE_a \gets DE_a \cup de$ \Comment{Had enough space to add it}\r
+                \ElsIf{$currentseq = smallestseq$}\r
+                    \State \Return{$NULL$}\r
+                \Else\r
+                    \State \Return{$DE_a$}\r
+                \EndIf\r
+            \EndIf\r
+        \EndFor\\\r
+        \r
+        \State $cseq \gets cseq+1$ \Comment{Move onto the next slot}\r
+    \EndWhile\r
+    \r
+    \State \Return{$DE_a$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Optional Rescue\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Optional Rescue:}\\\r
+This rescue is not mandatory.  This is trying to fill the remaining portion of the slot with rescued data so that no space is wasted. If we encounter a data entry that does not fit move on to the next, maybe that one will fit.  Do this until we skipped too many live data entries\\\r
+\begin{algorithmic}[1]\r
+\Function{OptionalRescue}{$DE_a$}\r
+    \State $smallestseq \gets seq$ such that $\tuple{seq, DE}\in LocalSlots \land (\forall \tuple{seq', DE'} \in LocalSlots, seq \leq seq')$\r
+    \State $largestseq \gets seq$ such that $\tuple{seq, DE}\in LocalSlots \land (\forall \tuple{seq', DE'} \in LocalSlots, seq \geq seq')$\r
+\r
+    \State $numofskips \gets 0$\r
+    \State $cseq \gets smallestseq$\\\r
+    \r
+    \LeftComment{Check the least slots to rescue and live entries}\r
+    \While{$cseq < largestseq$}\r
+        \State $currentslot \gets s'$ such that $\tuple{s',DE'} \in LocalSlots \land s' = cseq$\r
+        \State $\tuple{seq', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \gets currentslot$\\\r
+        \r
+        \ForAll{$de \in DE'$} \Comment{Iterate over all the entries}\r
+            \If{\Call{CheckLive}{$de, cseq$}} \Comment{data entry is live}\r
+                \State $de \gets $ \Call{CreateRescuedEntry}{de} \Comment{Resize entry if needed}\\\r
+                \r
+                \If{$de \in DE_a$} \Comment{Already being rescued}\r
+                    \State Continue\r
+                \EndIf\\\r
+                \r
+                \If{\Call{DEHasSpace}{$DE_a, de$}}\r
+                    \State $DE_a \gets DE_a \cup de$ \Comment{Had enoug space to add it}\r
+                \ElsIf{$numofskips \geq MAX\_RESCUE\_SKIPS$}\r
+                    \State \Return{$DE_a$}\r
+                \Else\r
+                    $numofskips \gets numofskips +1$\r
+                \EndIf\r
+            \EndIf\r
+        \EndFor\\\r
+        \r
+        \State $cseq \gets cseq+1$ \Comment{Move onto the next slot}\r
+    \EndWhile\r
+    \r
+    \State \Return{$DE_a$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+\r
+% Rejected Messages\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Rejected Messages:}\\\r
+\begin{algorithmic}[1]\r
+\Function{RejectedMessages}{$DE_a$}\r
+    \State $seq_{old} \gets seq$ such that $\tuple{seq} \in RejectedSlotList \land \forall \tuple{seq'} \in RejectedSlotList, seq \geq seq'$\r
+    \State $prev \gets -1$\\\r
+    \r
+    \r
+    \r
+    \If{$|RejectedSlotList| \geq REJECTED\_THRESH$}\r
+        \State $seq_{new} \gets seq$ such that $\tuple{seq} \in RejectedSlotList \land \forall \tuple{seq'} \in RejectedSlotList, seq \leq seq'$\\\r
+        \State $colres \gets $ \Call{CreateColRes}{$LOCAL\_ID, seq_{old}, seq_{new}, false$}    \r
+        \State \Return{$DE_a \cup \{colres\}$}\r
+    \EndIf\\\r
+    \r
+    \ForAll{$\tuple{seq} \in RejectedSlotList$ sorted by $seq$}\r
+        \If{$\exists \tuple{seq',Dat'} \in LocalSlots$}\r
+            \State Break\r
+        \EndIf\r
+        \State $prev \gets seq$\r
+    \EndFor\\\r
+    \r
+    \If{$prev \neq -1$}\r
+        \State $DE_a \gets DE_a \cup$ \Call{CreateColRes}{$LOCAL\_ID, seq_{old}, prev, false$}\r
+    \EndIf\\\r
+    \r
+    \State $RejectedSlotList \gets \{\tuple{seq}| \tuple{seq} \in RejectedSlotList, seq > prev\}$\\\r
+    \r
+    \ForAll{$\tuple{seq} \in RejectedSlotList$ sorted by $seq$}\r
+        \State $DE_a \gets DE_a \cup$ \Call{CreateColRes}{$LOCAL\_ID, seq,seq, false$}\r
+    \EndFor\\\r
+    \r
+    \State \Return{$DE_a$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+\r
+\r
+% Arbitrate\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Arbitrate:}\\\r
+\begin{algorithmic}[1]\r
+\Function{Arbitrate}{$DE_a$}\r
+    \State $AllCommits \gets$ \Call{GetCommits}{}\r
+    \State $AllTrans \gets$ \Call{GetTrans}{}\r
+    \State $LiveCommits \gets \{c| c\in AllCommits, $\Call{CheckCommitLive}{$c$}$\}$\r
+    \State $LiveTrans \gets \{t| t\in AllTrans, $\Call{CheckTransLive}{$t$}$\}$\r
+    \State $KV \gets \emptyset$\r
+    \State $lastcomseq \gets -1$\r
+    \State $CurrKV \gets \emptyset$\r
+    \State $DKV \gets \emptyset$\r
+    \State $KVTmp \gets \emptyset$\\\r
+    \r
+    \LeftComment{Get all the latest commits}\r
+    \ForAll{$\tuple{seq_{trans}',KV'} \in LiveCommits$}\r
+        \State $CurrKV \gets CurrKV \cup KV'$\r
+    \EndFor\\\r
+    \r
+    \ForAll{$\tuple{seq_t, id_t, KV_t, Guard_t} \in LiveTrans$ ordered by $seq'$} \r
+        \If{\Call{GetArbitratorKV}{$KV_t$} $\neq LOCAL\_ID$}\r
+            \State Continue \Comment{Client not arbitrator for this transaction}\r
+        \EndIf\\\r
+    \r
+        \If{$\lnot$\Call{EvaluateGuard}{$Guard_t, CurrKV$}}\r
+            \State $abortde \gets $\Call{CreateAbort}{$seq_t, id_t$}\r
+            \LeftComment{No more space so we cant arbitrate any further}\r
+            \If($lnot$\Call{DeHasSpace}{$DE_a, abortde$})\r
+                \State \Return{$DE_a$}\r
+            \EndIf\r
+            \State $DE_a \gets DE_a \cup abortde$\r
+        \Else\r
+            \State $DKV \gets \{\tuple{k,v}| \tuple{k,v} \in KV \land \tuple{k',v'}\in KV_t \land k'=k\}$\r
+            \State $KVTmp \gets (KV \setminus DKV) \cup KV'$\r
+            \State $DKV \gets \{\tuple{k,v}| \tuple{k,v} \in CurrKV \land \tuple{k',v'}\in KVTmp \land k'=k\}$\r
+            \State $CurrKV \gets (CurrKV \setminus DKV) \cup KVTmp$\r
+            \State $commitde \gets $ \Call{CreateCommit}{$seq_t,KVTmp$}\r
+            \r
+            \If{$\lnot$ \Call{DeHasSpace}{$DE_a, commitde$}}\r
+                \If{$lastcomseq \neq -1$}\r
+                    \State $DE_a \gets DE_a \cup$ \Call{CreateCommit}{$lastcomseq,KV$}\r
+                \EndIf\r
+                \State \Return{$DE_a$}\r
+            \Else\r
+                \State $KV \gets KVTmp$\r
+                \State $lastcomseq \gets seq_t$\r
+            \EndIf\r
+        \EndIf\r
+    \EndFor\r
+    \r
+    \State $DE_a \gets DE_a \cup$ \Call{CreateCommit}{$lastcomseq,KV$}\r
+    \State \Return{$DE_a$}\r
+\r
+    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Create New Slot\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Create New Slot:}\\\r
+Create a slot and encrypt it.\\\r
+\begin{algorithmic}[1]\r
+\Function{CreateNewSlot}{$seq_a, DE_a$}\r
+    \State $\tuple{seq, SDE} \gets \tuple{seq', SDE'}$ such that $\tuple{seq', SDE'}\in LocalSlots \land (\forall \tuple{seq'', DE''} \in LocalSlots, seq' \geq seq'')$\r
+    \State $\tuple{seq,id,DE,hmac_p,hmac_c} \gets SDE$\\\r
+    \r
+    \State $newhmac \gets $ \Call{GenerateHmac}{$seq_a, LOCAL\_ID, DE_a, hmac_p$}\r
+    \State $newSDE \gets \tuple{seq,LOCAL\_ID,DE_a,hmac_c,newhmac}$\r
+    \State $encryptnewSDE \gets $\Call{Encrypt}{newSDE}\\\r
+    \r
+    \State \Return{$\tuple{seq_a, encryptnewSDE}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Send Data to Server\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Send Data to Server:}\\\r
+Send the data to the server.  If this fails then new slots will be returned by the server.\\\r
+\begin{algorithmic}[1]\r
+\Function{SendToServer}{$seq_a, DE_a, newsize_a$}\r
+    \LeftComment{Make the slot and try to send to server}\r
+    \State $newslot \gets $ \Call{CreateNewSlot}{$seq_a, DE_a$}\r
+    \State $\tuple{success, newslots} \gets$ \Call{PutSlot}{$seq_a, newslot, newsize_a$}\\\r
+    \r
+    \If{$success$}\r
+        \State $RejectedSlotList \gets \emptyset$\r
+        \State \Return{$\tuple{true, \{newslot\}}$}\r
+    \Else\r
+        \If{$|newslots| = 0$}\r
+            \State \Call{Error}{"Server rejected but did not send any slots"}\r
+        \EndIf\r
+        \State $RejectedSlotList \gets RejectedSlotList \cup \{seq_a\}$\r
+        \State \Return{$\tuple{false, newslots}$}\r
+    \EndIf\\\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+\r
+% Try Insert Transaction\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Try Insert Transaction:}\\\r
+Try to insert a transaction into the block chain. Does resizing, rescues and insertion of other data entry types as needed. \\\r
+\begin{algorithmic}[1]\r
+\Function{TryInsertTransaction}{$pendingtrans_a, forceresize$}\r
+    \State $DE \gets \emptyset$ \Comment{The data entries for this slot}\r
+    \State $seq \gets $ \Call{GetNextSeq}{} \Comment{Get the sequence number for this slot}\r
+    \State $newsize \gets 0$\r
+    \State $trans \gets$ \Call{CreateTrans}{$pendingtrans_a, seq$}\r
+    \State $transinserted \gets false$\r
+    \State $slotstoinsert \gets \emptyset$\\\r
+    \r
+    \State $resize \gets $ \Call{ShouldResize}{ } \Comment{Check if we should resize}\r
+    \State $resize \gets resize \lor forceresize$\r
+    \If{$resize$}\r
+        \State $newsize \gets$ \Call{CalcNewSize}{$max\_size$}\r
+        \State $DE \gets DE \cup \{$\Call{CreateQState}{$newsize$}$\}$\r
+    \EndIf\\\r
+    \r
+    \If{$RejectedSlotList \neq \emptyset$}   \r
+        \State $DE \gets$ \Call{RejectedMessages}{$DE$}\r
+    \EndIf\\\r
+    \r
+    \State $DE \gets$ \Call{MandatoryRescue}{$DE$} \Comment{Round 1 of rescue}\r
+    \If{$DE = NULL$}\r
+        \LeftComment{Data was going to fall off the end so try again with a forced resize}\r
+        \State \Return{\Call{TryInsertTransaction}{$trans_a, true$}}\r
+    \EndIf\\\r
+    \r
+    \State $DE \gets $\Call{Arbitrate}{$DE$}\\\r
+    \r
+    \If{\Call{DEHasSpace}{$DE, trans$}} \Comment{transaction fits}\r
+        \State $DE \gets DE \cup trans$\r
+        \State $transinserted \gets true$\r
+    \EndIf\\\r
+    \r
+    \LeftComment{Rescue data to fill slot data entry section}\r
+    \State $DE \gets$ \Call{OptionalRescue}{$DE$}\\\r
+    \r
+    \LeftComment{Send to server.}\r
+    \State $\tuple{sendsuccess, newslots} \gets $ \Call{SendToServer}{$seq, DE, newsize$}\\\r
+    \r
+    \LeftComment{Insert the slots into the local bloakc chain}\r
+    \State \Call{DecryptValidateInsert}{$newslots, true$}\\\r
+    \r
+    \State \Return{$transinserted \land success$} \Comment{Return if  succeeded or not}\r
+    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+\r
+% Try Insert New Key\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Try Insert New Key:}\\\r
+Try to insert a new key into the block chain. Does resizing, rescues and insertion of other data entry types as needed. \\\r
+\begin{algorithmic}[1]\r
+\Function{TryInsertNewKey}{$k_a, id_a, forceresize$}\r
+    \State $DE \gets \emptyset$ \Comment{The data entries for this slot}\r
+    \State $seq \gets $ \Call{GetNextSeq}{} \Comment{Get the sequence number for this slot}\r
+    \State $newsize \gets 0$\r
+    \r
+    \r
+    \State $newkey \gets$ \Call{CreateNewKey}{$k_a, id_a$}\r
+    \State $newkeyinserted \gets false$\r
+    \State $slotstoinsert \gets \emptyset$\\\r
+    \r
+    \State $resize \gets $ \Call{ShouldResize}{ } \Comment{Check if we should resize}\r
+    \State $resize \gets resize \lor forceresize$\r
+    \If{$resize$}\r
+        \State $newsize \gets$ \Call{CalcNewSize}{$max\_size$}\r
+        \State $DE \gets DE \cup \{$\Call{CreateQState}{$newsize$}$\}$\r
+    \EndIf\\\r
+    \r
+    \If{$RejectedSlotList \neq \emptyset$}   \r
+        \State $DE \gets$ \Call{RejectedMessages}{$DE$}\r
+    \EndIf\\\r
+    \r
+    \State $DE \gets$ \Call{MandatoryRescue}{$DE$} \Comment{Round 1 of rescue}\r
+    \If{$DE = NULL$}\r
+        \LeftComment{Data was going to fall off the end so try again with a forced resize}\r
+        \State \Return{\Call{TryInsertNewKey}{$k_a, id_a, true$}}\r
+    \EndIf\\\r
+    \r
+    \State $DE \gets $\Call{Arbitrate}{$DE$}\\\r
+    \r
+    \If{\Call{DEHasSpace}{$DE, newkey$}} \Comment{new key fits}\r
+        \State $DE \gets DE \cup newkey$\r
+        \State $newkeyinserted \gets true$\r
+    \EndIf\\\r
+    \r
+    \LeftComment{Rescue data to fill slot data entry section}\r
+    \State $DE \gets$ \Call{OptionalRescue}{$DE$}\\\r
+    \r
+    \LeftComment{Send to server.}\r
+    \State $\tuple{sendsuccess, newslots} \gets $ \Call{SendToServer}{$seq, DE, newsize$}\\\r
+    \r
+    \LeftComment{Insert the slots into the local block chain}\r
+    \State \Call{DecryptValidateInsert}{$newslots, true$}\\\r
+    \r
+    \State \Return{$newkeyinserted \land success$} \Comment{Return if  succeeded or not}\r
+    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+\r
+\r
+\subsection{Client Interfaces}\r
+\r
+% Put KV pair\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Put Key Value Pair:}\\\r
+Puts a key value pair into the key value pair buffer\\\r
+\begin{algorithmic}[1]\r
+\Function{PutKeyValue}{$k,v$}\r
+    \State $\tuple{seq, KV, Guard} \gets PendingTrans$\\\r
+    \r
+    \LeftComment{Check if KV already has a key value pair for the specified key}\r
+    \State $DSet \gets \{\tuple{k_1,v_1} | \tuple{k_1,v_1} \in KV \land k_1 = k\}$\\\r
+    \r
+    \If{$DSet \neq \emptyset$}\r
+        \State \Call{Error}{"Value for key already in most recent update"}\r
+    \EndIf\\\r
+        \r
+    \State $KV \gets KV \cup \{\tuple{k,v}\}$ \Comment{Add key value pair}\r
+    \State $PendingTrans \gets \tuple{seq, KV, Guard}$\r
+    \State \Call{CheckArbitrator}{$PendingTrans$} \Comment{Check that the transaction still valid}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Get KV Pair Speculative\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Get KV Pair Speculative:}\\\r
+Get the value for the key while speculating.\\\r
+\begin{algorithmic}[1]\r
+\Function{GetValueSpeculate}{$k_a$}\r
+    %\State $\tuple{k,v} \gets \tuple{k,v}$ \textit{such that} $\tuple{k,v} \in SpeculatedKV \land k = k_a$\r
+    \r
+    \State $\tuple{k,v} \gets \tuple{k,v}$ \textit{such that} $\tuple{k,v} \in SpeculatedKV \land k = k_a$\r
+\State \Return{$v$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Update\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Update}\\\r
+Sync with the server and get all the latest slots.\\\r
+\begin{algorithmic}[1]\r
+\Function{Update}{$ $}\r
+    \State $\tuple{seq, Dat} \gets $ \Call{MaxSlot}{$LocalSlots$}\r
+    \State $NewSlots \gets$ \Call{GetSlots}{$seq$}\r
+    \State \Call{DecryptValidateInsert}{$NewSlots, false$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Get KV Pair Committed\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Get KV Pair Committed:}\\\r
+Get the value for the key which have been committed.\\\r
+\begin{algorithmic}[1]\r
+\Function{GetValueCommit}{$k_a$}\r
+    \State $\tuple{k,v} \gets \tuple{k,v}$ \textit{such that} $\tuple{k,v} \in Committed \land k = k_a$\r
+    \State \Return{$v$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Put guard condition\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Put Guard:}\\\r
+Puts a guard transaction into the key value update.  A guard is a key value with a logical operator ($lop$).\\\r
+\begin{algorithmic}[1]\r
+\Function{PutGuard}{$k,v, lop$}\r
+    \State $\tuple{seq, KV, Guard} \gets PendingTrans$\\\r
+    \r
+    \If{$\tuple{k,v, lop} \in Guard$}\r
+        \State \Return{} \Comment{Already have guard condition in update}\r
+    \EndIf\\\r
+    \r
+    \State $Guard \gets Guard \cup \{\tuple{k,v,lop}\}$\r
+    \State $PendingTrans \gets \tuple{seq, KV, Guard}$\r
+    \State \Call{CheckArbitrator}{$PendingTrans$} \Comment{Check that the transaction still valid}\r
+\EndFunction    \r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Transaction Start\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{ Transaction Start:}\\\r
+Starts a transaction.  Clears out the key value pair update buffer.\\\r
+\begin{algorithmic}[1]\r
+\Function{TransactionStart}{$ $}\r
+    % \LeftComment{Reset the key value update buffer}\r
+    % \State $KVUpdate \gets \tuple{\emptyset, \emptyset}$\r
+    \State $PendingTrans \gets NULL$\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+% Transaction Commit\r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{ Transaction Commit:}\\\r
+Commits the transaction into the block chain.  Keeps attempting to insert the transaction into the block chain until it succeeds.\\\r
+\begin{algorithmic}[1]\r
+\Function{Transaction Commit}{$ $}\r
+    \State $DKV \gets \emptyset$\r
+    \State $pt \gets NULL$\\\r
+    \r
+    \State $PendingTransQueue.$\Call{push}{$PendingTrans$}\\\r
+        \r
+    \While{\Call{HasConnectionToServer}{ } $\land PendingTransQueue \neq \emptyset$}\r
+        \State $pt \gets PendingTransQueue.$\Call{peak}{ }\\\r
+    \r
+        \If{\Call{TryInsertTransaction}{$pt, false$}}\r
+            \State $PendingTransQueue.$\Call{pop}{ }\r
+        \EndIf\r
+    \EndWhile\\    \r
+    \r
+    \LeftComment{Go Through local pending transactions and speculate}\r
+    \ForAll{$\tuple{KV, Guard} \in PendingTransQueue$}\r
+        \If{\Call{EvaluateGuard}{$Guard, SpeculatedKV$}}\r
+            \State $DKV \gets \{\tuple{k,v}| \tuple{k,v} \in SpeculatedKV \land \tuple{k',v'}\in KV \land k'=k\}$\r
+            \State $SpeculatedKV \gets (SpeculatedKV \setminus DKV) \cup KV$\r
+        \EndIf\r
+    \EndFor\r
+    \r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+\r
+%Create New Key \r
+\noindent\fbox{%\r
+\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
+\textbf{Create New Key:}\\\r
+Creates a new key and specifies which machine ID is the arbitrator. If there is already a new key entry in the block chain for this key name then do not insert into the chain, another client got there first. \\\r
+\begin{algorithmic}[1]\r
+\Function{Transaction Commit}{$k_a, id_a$}\r
+    \State $success \gets false$\\\r
+    \While{$\lnot success$}\r
+        \If{$\exists \tuple{k',id'} \in Arbitrator, k' = k_a$}\r
+            \State \Return{$false$} \Comment{Key already created}\r
+        \EndIf\\\r
+    \r
+        \State $success \gets$ \Call{TryInsertNewKey}{$k_a, id_a, false$}\r
+    \EndWhile\r
+    \r
+    \State \Return{$true$} \Comment{If got here then insertion was correct}\r
+\EndFunction\r
+\end{algorithmic}\r
+\end{varwidth}% \r
+}\r
+\r
+\r
+\end{document}\r
diff --git a/version2/backup/doc/makefile b/version2/backup/doc/makefile
new file mode 100644 (file)
index 0000000..cff4a15
--- /dev/null
@@ -0,0 +1,8 @@
+LATEX := pdflatex -halt-on-error
+
+default:
+       $(LATEX) iotcloud.tex
+
+clean:
+       rm -f *.dvi *.log *.aux *.blg *.bbl *~
+       rm -f iotcloud.ps iotcloud.pdf 
diff --git a/version2/backup/src/java/.dir-locals.el b/version2/backup/src/java/.dir-locals.el
new file mode 100644 (file)
index 0000000..e166a2e
--- /dev/null
@@ -0,0 +1,2 @@
+((nil . ((indent-tabs-mode . t))))
+
diff --git a/version2/backup/src/java/iotcloud/Abort.java b/version2/backup/src/java/iotcloud/Abort.java
new file mode 100644 (file)
index 0000000..327ce33
--- /dev/null
@@ -0,0 +1,63 @@
+package iotcloud;
+
+import java.nio.ByteBuffer;
+
+/**
+ * This Entry records the abort sent by a given machine.
+ * @author Ali Younis <ayounis@uci.edu>
+ * @version 1.0
+ */
+
+
+class Abort extends Entry {
+       private long seqnumtrans;
+       private long machineid;
+       private long transarbitrator;
+
+
+       public Abort(Slot slot, long _seqnumtrans,  long _machineid, long _transarbitrator) {
+               super(slot);
+               seqnumtrans = _seqnumtrans;
+               machineid = _machineid;
+               transarbitrator = _transarbitrator;
+       }
+
+       public long getMachineID() {
+               return machineid;
+       }
+
+       public long getTransSequenceNumber() {
+               return seqnumtrans;
+       }
+
+
+       public long getTransArbitrator() {
+               return transarbitrator;
+       }
+
+       static Entry decode(Slot slot, ByteBuffer bb) {
+               long seqnumtrans = bb.getLong();
+               long machineid = bb.getLong();
+               long transarbitrator = bb.getLong();
+               return new Abort(slot, seqnumtrans,  machineid, transarbitrator);
+       }
+
+       public void encode(ByteBuffer bb) {
+               bb.put(Entry.TypeAbort);
+               bb.putLong(seqnumtrans);
+               bb.putLong(machineid);
+               bb.putLong(transarbitrator);
+       }
+
+       public int getSize() {
+               return (3 * Long.BYTES) + Byte.BYTES;
+       }
+
+       public byte getType() {
+               return Entry.TypeAbort;
+       }
+
+       public Entry getCopy(Slot s) {
+               return new Abort(s, seqnumtrans, machineid, transarbitrator);
+       }
+}
\ No newline at end of file
diff --git a/version2/backup/src/java/iotcloud/CloudComm.java b/version2/backup/src/java/iotcloud/CloudComm.java
new file mode 100644 (file)
index 0000000..6f548af
--- /dev/null
@@ -0,0 +1,261 @@
+package iotcloud;
+import java.io.*;
+import java.net.*;
+import java.util.Arrays;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+import java.security.SecureRandom;
+
+/**
+ * This class provides a communication API to the webserver.  It also
+ * validates the HMACs on the slots and handles encryption.
+ * @author Brian Demsky <bdemsky@uci.edu>
+ * @version 1.0
+ */
+
+
+class CloudComm {
+       String hostname;
+       String baseurl;
+       Cipher encryptCipher;
+       Cipher decryptCipher;
+       Mac mac;
+       String password;
+       SecureRandom random;
+       static final int SALT_SIZE = 8;
+       static final int TIMEOUT_MILLIS = 100;
+       byte salt[];
+       Table table;
+
+       /**
+        * Empty Constructor needed for child class.
+        */
+       CloudComm() {
+       }
+
+       /**
+        * Constructor for actual use. Takes in the url and password.
+        */
+       CloudComm(Table _table, String _hostname, String _baseurl, String _password) {
+               this.table = _table;
+               this.hostname = _hostname;
+               this.baseurl = _baseurl;
+               this.password = _password;
+               this.random = new SecureRandom();
+       }
+
+       /**
+        * Generates Key from password.
+        */
+       private SecretKeySpec initKey() {
+               try {
+                       PBEKeySpec keyspec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
+                       SecretKey tmpkey = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256").generateSecret(keyspec);
+                       return new SecretKeySpec(tmpkey.getEncoded(), "AES");
+               } catch (Exception e) {
+                       e.printStackTrace();
+                       throw new Error("Failed generating key.");
+               }
+       }
+
+       /**
+        * Inits the HMAC generator.
+        */
+       private void initCrypt() {
+               try {
+                       SecretKeySpec key = initKey();
+                       password = null; // drop password
+                       mac = Mac.getInstance("HmacSHA256");
+                       mac.init(key);
+                       encryptCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+                       encryptCipher.init(Cipher.ENCRYPT_MODE, key);
+                       decryptCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+                       decryptCipher.init(Cipher.DECRYPT_MODE, key);
+               } catch (Exception e) {
+                       e.printStackTrace();
+                       throw new Error("Failed To Initialize Ciphers");
+               }
+       }
+
+       /*
+        * Builds the URL for the given request.
+        */
+       private URL buildRequest(boolean isput, long sequencenumber, long maxentries) throws IOException {
+               String reqstring = isput ? "req=putslot" : "req=getslot";
+               String urlstr = baseurl + "?" + reqstring + "&seq=" + sequencenumber;
+               if (maxentries != 0)
+                       urlstr += "&max=" + maxentries;
+               return new URL(urlstr);
+       }
+
+       public void setSalt() throws ServerException {
+               try {
+                       byte[] saltTmp = new byte[SALT_SIZE];
+                       random.nextBytes(saltTmp);
+                       URL url = new URL(baseurl + "?req=setsalt");
+                       URLConnection con = url.openConnection();
+                       HttpURLConnection http = (HttpURLConnection) con;
+                       http.setRequestMethod("POST");
+                       http.setFixedLengthStreamingMode(saltTmp.length);
+                       http.setDoOutput(true);
+                       http.setConnectTimeout(TIMEOUT_MILLIS);
+                       http.connect();
+                       OutputStream os = http.getOutputStream();
+                       os.write(saltTmp);
+                       int responsecode = http.getResponseCode();
+                       if (responsecode != HttpURLConnection.HTTP_OK) {
+                               // TODO: Remove this print
+                               // System.out.println(responsecode);
+                               throw new Error("Invalid response");
+                       }
+
+                       salt = saltTmp;
+               } catch (Exception e) {
+                       throw new ServerException("Failed setting salt");
+               }
+               initCrypt();
+       }
+
+       private void getSalt() throws Exception {
+               URL url = new URL(baseurl + "?req=getsalt");
+               URLConnection con = url.openConnection();
+               HttpURLConnection http = (HttpURLConnection) con;
+               http.setRequestMethod("POST");
+               http.connect();
+
+               InputStream is = http.getInputStream();
+               DataInputStream dis = new DataInputStream(is);
+               int salt_length = dis.readInt();
+               byte [] tmp = new byte[salt_length];
+               dis.readFully(tmp);
+               salt = tmp;
+       }
+
+       /*
+        * API for putting a slot into the queue.  Returns null on success.
+        * On failure, the server will send slots with newer sequence
+        * numbers.
+        */
+
+       Slot[] putSlot(Slot slot, int max) throws ServerException {
+               try {
+                       if (salt == null) {
+                               getSalt();
+                               initCrypt();
+                       }
+
+                       long sequencenumber = slot.getSequenceNumber();
+                       byte[] bytes = slot.encode(mac);
+                       bytes = encryptCipher.doFinal(bytes);
+
+
+                       URL url = buildRequest(true, sequencenumber, max);
+                       URLConnection con = url.openConnection();
+                       HttpURLConnection http = (HttpURLConnection) con;
+
+                       http.setRequestMethod("POST");
+                       http.setFixedLengthStreamingMode(bytes.length);
+                       http.setDoOutput(true);
+                       http.setConnectTimeout(TIMEOUT_MILLIS);
+                       // http.setReadTimeout(TIMEOUT_MILLIS);
+                       http.connect();
+
+                       OutputStream os = http.getOutputStream();
+                       os.write(bytes);
+                       os.flush();
+
+
+                       InputStream is = http.getInputStream();
+                       DataInputStream dis = new DataInputStream(is);
+                       byte[] resptype = new byte[7];
+                       dis.readFully(resptype);
+
+                       if (Arrays.equals(resptype, "getslot".getBytes()))
+                               return processSlots(dis);
+                       else if (Arrays.equals(resptype, "putslot".getBytes()))
+                               return null;
+                       else
+                               throw new Error("Bad response to putslot");
+
+               } catch (Exception e) {
+                       throw new ServerException("putSlot failed");
+               }
+       }
+
+
+       /**
+        * Request the server to send all slots with the given
+        * sequencenumber or newer.
+        */
+       Slot[] getSlots(long sequencenumber) throws ServerException {
+               try {
+                       if (salt == null) {
+                               getSalt();
+                               initCrypt();
+                       }
+
+                       URL url = buildRequest(false, sequencenumber, 0);
+                       URLConnection con = url.openConnection();
+                       HttpURLConnection http = (HttpURLConnection) con;
+                       http.setRequestMethod("POST");
+                       http.setConnectTimeout(TIMEOUT_MILLIS);
+                       // http.setReadTimeout(TIMEOUT_MILLIS);
+                       http.connect();
+                       InputStream is = http.getInputStream();
+                       DataInputStream dis = new DataInputStream(is);
+
+                       int responsecode = http.getResponseCode();
+                       if (responsecode != HttpURLConnection.HTTP_OK) {
+                               // TODO: Remove this print
+                               // System.out.println("Code:  " + responsecode);
+                               throw new ServerException("getSlots failed");
+                       }
+
+                       byte[] resptype = new byte[7];
+                       dis.readFully(resptype);
+                       if (!Arrays.equals(resptype, "getslot".getBytes()))
+                               throw new Error("Bad Response: " + new String(resptype));
+                       else
+                               return processSlots(dis);
+               } catch (Exception e) {
+                       // e.printStackTrace();
+                       throw new ServerException("getSlots failed");
+               }
+       }
+
+       public boolean hasConnection() {
+               try {
+                       InetAddress address = InetAddress.getByName(hostname);
+                       return address.isReachable(TIMEOUT_MILLIS);
+               } catch (Exception e) {
+                       return false;
+               }
+       }
+
+       /**
+        * Method that actually handles building Slot objects from the
+        * server response.  Shared by both putSlot and getSlots.
+        */
+       private Slot[] processSlots(DataInputStream dis) throws Exception {
+               int numberofslots = dis.readInt();
+               int[] sizesofslots = new int[numberofslots];
+               Slot[] slots = new Slot[numberofslots];
+               for (int i = 0; i < numberofslots; i++)
+                       sizesofslots[i] = dis.readInt();
+
+               for (int i = 0; i < numberofslots; i++) {
+                       byte[] data = new byte[sizesofslots[i]];
+                       dis.readFully(data);
+
+                       data = decryptCipher.doFinal(data);
+
+                       slots[i] = Slot.decode(table, data, mac);
+               }
+               dis.close();
+               return slots;
+       }
+
+
+
+
+}
diff --git a/version2/backup/src/java/iotcloud/Commit.java b/version2/backup/src/java/iotcloud/Commit.java
new file mode 100644 (file)
index 0000000..fb52e67
--- /dev/null
@@ -0,0 +1,125 @@
+package iotcloud;
+
+import java.nio.ByteBuffer;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Iterator;
+
+/**
+ * This Entry records the commit of a transaction.
+ * @author Ali Younis <ayounis@uci.edu>
+ * @version 1.0
+ */
+
+
+class Commit extends Entry {
+       private long seqnumtrans;
+       private long seqnumcommit;
+       private long transarbitrator;
+
+       private Set<KeyValue> keyValueUpdateSet = null;
+
+
+       public Commit(Slot slot, long _seqnumtrans,  long _seqnumcommit, long _transarbitrator, Set<KeyValue> _keyValueUpdateSet) {
+               super(slot);
+               seqnumtrans = _seqnumtrans;
+               seqnumcommit = _seqnumcommit;
+               transarbitrator = _transarbitrator;
+
+               keyValueUpdateSet = new HashSet<KeyValue>();
+
+               for (KeyValue kv : _keyValueUpdateSet) {
+                       KeyValue kvCopy = kv.getCopy();
+                       keyValueUpdateSet.add(kvCopy);
+               }
+       }
+
+       public long getTransSequenceNumber() {
+               return seqnumtrans;
+       }
+       public long getSequenceNumber() {
+               return seqnumcommit;
+       }
+
+       public long getTransArbitrator() {
+               return transarbitrator;
+       }
+
+       public Set<KeyValue> getkeyValueUpdateSet() {
+               return keyValueUpdateSet;
+       }
+
+       public byte getType() {
+               return Entry.TypeCommit;
+       }
+
+       public int getSize() {
+               int size = 3 * Long.BYTES + Byte.BYTES; // seq id, entry type
+               size += Integer.BYTES; // number of KV's
+
+               // Size of each KV
+               for (KeyValue kv : keyValueUpdateSet) {
+                       size += kv.getSize();
+               }
+
+               return size;
+       }
+
+       static Entry decode(Slot slot, ByteBuffer bb) {
+               long seqnumtrans = bb.getLong();
+               long seqnumcommit = bb.getLong();
+               long transarbitrator = bb.getLong();
+               int numberOfKeys = bb.getInt();
+
+               Set<KeyValue> kvSet = new HashSet<KeyValue>();
+               for (int i = 0; i < numberOfKeys; i++) {
+                       KeyValue kv = KeyValue.decode(bb);
+                       kvSet.add(kv);
+               }
+
+               return new Commit(slot, seqnumtrans, seqnumcommit, transarbitrator, kvSet);
+       }
+
+       public void encode(ByteBuffer bb) {
+               bb.put(Entry.TypeCommit);
+               bb.putLong(seqnumtrans);
+               bb.putLong(seqnumcommit);
+               bb.putLong(transarbitrator);
+
+               bb.putInt(keyValueUpdateSet.size());
+
+               for (KeyValue kv : keyValueUpdateSet) {
+                       kv.encode(bb);
+               }
+       }
+
+       public Entry getCopy(Slot s) {
+               return new Commit(s, seqnumtrans, seqnumcommit, transarbitrator, keyValueUpdateSet);
+       }
+
+       public Set<KeyValue> updateLiveKeys(Set<KeyValue> kvSet) {
+
+               if (!this.isLive())
+                       return new HashSet<KeyValue>();
+
+               Set<KeyValue> toDelete = new HashSet<KeyValue>();
+
+               for (KeyValue kv1 : kvSet) {
+                       for (Iterator<KeyValue> i = keyValueUpdateSet.iterator(); i.hasNext();) {
+                               KeyValue kv2 = i.next();
+
+                               if (kv1.getKey().equals(kv2.getKey())) {
+                                       toDelete.add(kv2);
+                                       i.remove();
+                                       break;
+                               }
+                       }
+               }
+
+               if (keyValueUpdateSet.size() == 0) {
+                       this.setDead();
+               }
+
+               return toDelete;
+       }
+}
\ No newline at end of file
diff --git a/version2/backup/src/java/iotcloud/Entry.java b/version2/backup/src/java/iotcloud/Entry.java
new file mode 100644 (file)
index 0000000..8395dec
--- /dev/null
@@ -0,0 +1,119 @@
+package iotcloud;
+import java.nio.ByteBuffer;
+
+/**
+ * Generic class that wraps all the different types of information
+ * that can be stored in a Slot.
+ * @author Brian Demsky <bdemsky@uci.edu>
+ * @version 1.0
+ */
+
+abstract class Entry implements Liveness {
+
+
+       static final byte TypeCommit = 1;
+       static final byte TypeAbort = 2;
+       static final byte TypeTransaction = 3;
+       static final byte TypeNewKey = 4;
+       static final byte TypeLastMessage = 5;
+       static final byte TypeRejectedMessage = 6;
+       static final byte TypeTableStatus = 7;
+
+
+
+       /* Records whether the information is still live or has been
+                superceded by a newer update.  */
+
+       private boolean islive = true;
+       private Slot parentslot;
+
+       public Entry(Slot _parentslot) {
+               parentslot = _parentslot;
+       }
+
+       /**
+        * Static method for decoding byte array into Entry objects.  First
+        * byte tells the type of entry.
+        */
+
+       static Entry decode(Slot slot, ByteBuffer bb) {
+               byte type = bb.get();
+               switch (type) {
+
+               case TypeCommit:
+                       return Commit.decode(slot, bb);
+
+               case TypeAbort:
+                       return Abort.decode(slot, bb);
+
+               case TypeTransaction:
+                       return Transaction.decode(slot, bb);
+
+               case TypeNewKey:
+                       return NewKey.decode(slot, bb);
+
+               case TypeLastMessage:
+                       return LastMessage.decode(slot, bb);
+
+               case TypeRejectedMessage:
+                       return RejectedMessage.decode(slot, bb);
+
+               case TypeTableStatus:
+                       return TableStatus.decode(slot, bb);
+
+               default:
+                       throw new Error("Unrecognized Entry Type: " + type);
+               }
+       }
+
+       /**
+        * Returns true if the Entry object is still live.
+        */
+
+       public boolean isLive() {
+               return islive;
+       }
+
+       /**
+        * Flags the entry object as dead.  Also decrements the live count
+        * of the parent slot.
+        */
+
+       public void setDead() {
+
+               if (!islive ) {
+                       return; // already dead
+               }
+
+               islive = false;
+
+               if (parentslot != null) {
+                       parentslot.decrementLiveCount();
+               }
+       }
+
+       /**
+        * Serializes the Entry object into the byte buffer.
+        */
+
+       abstract void encode(ByteBuffer bb);
+
+       /**
+        * Returns the size in bytes the entry object will take in the byte
+        * array.
+        */
+
+       abstract int getSize();
+
+       /**
+        * Returns a byte encoding the type of the entry object.
+        */
+
+       abstract byte getType();
+
+       /**
+        * Returns a copy of the Entry that can be added to a different slot.
+        */
+       abstract Entry getCopy(Slot s);
+
+}
diff --git a/version2/backup/src/java/iotcloud/Guard.java_backup b/version2/backup/src/java/iotcloud/Guard.java_backup
new file mode 100644 (file)
index 0000000..f768b7f
--- /dev/null
@@ -0,0 +1,163 @@
+package iotcloud;
+
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collection;
+import java.util.List;
+import java.util.ArrayList;
+
+import java.nio.ByteBuffer;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import java.lang.NullPointerException;
+
+
+class Guard {
+
+    static final byte Equal = 1;
+    static final byte NotEqual = 2;
+    private IoTString booleanExpression;
+    private List<KeyValue> keyValsNeeded = null;
+
+    public Guard() {
+        booleanExpression = null;
+    }
+
+    public Guard(IoTString _booleanExpression) {
+        booleanExpression = _booleanExpression;
+    }
+
+    /**
+     * Create an equality expression for a key value.
+     *
+     */
+    public static String createExpression(IoTString keyName, IoTString keyValue, byte op) {
+        if (op == Equal) {
+            return keyName.toString() + "=='" + keyValue.toString() + "'";
+        } else if (op == NotEqual) {
+            return keyName.toString() + "!='" + keyValue.toString() + "'";
+        }
+
+        // Unrecognized op
+        return null;
+    }
+
+    /**
+     * Add a boolean expression to the guard.
+     *
+     */
+    public void setGuardExpression(String expr) {
+        booleanExpression = new IoTString(expr);
+    }
+
+    /**
+     * Evaluate the guard expression for a given set of key value pairs.
+     *
+     */
+    public boolean evaluate(Collection<KeyValue> kvSet) throws ScriptException, NullPointerException {
+
+        // There are no conditions to evaluate
+        if (booleanExpression == null) {
+            return true;
+        }
+
+        ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
+
+        if (keyValsNeeded == null) {
+            keyValsNeeded = new ArrayList<KeyValue>();
+
+            String booleanExprString = booleanExpression.toString();
+            for (KeyValue kv : kvSet) {
+                if (booleanExprString.contains(kv.getKey().toString())) {
+                    keyValsNeeded.add(kv);
+                }
+            }
+        }
+
+        // All the current key value pairs that we need to evaluate the condition
+        // String[] variables = new String[kvSet.size()];
+
+        // Fill the variables array
+        // int i = 0;
+        // for (KeyValue kv : kvSet) {
+        // for (KeyValue kv : keyValsNeeded) {
+        //     variables[i] = kv.getKey() + " ='" + kv.getValue() + "'";
+        //     i++;
+        // }
+
+        String varEval = "";
+        for (KeyValue kv : keyValsNeeded) {
+            varEval += "var " + kv.getKey() + " ='" + kv.getValue() + "'; \n";
+        }
+
+        varEval += booleanExpression.toString();
+
+        // Prep the evaluation engine (script engine)
+
+        // for (String s : variables) {
+        //     engine.eval(s);
+        // }
+        // engine.eval(varEval);
+
+
+
+        // boolean engineEval = (Boolean)engine.eval(booleanExpression.toString());
+        boolean engineEval = false;
+
+        try {
+            engineEval = (Boolean)engine.eval(varEval);
+        } catch (Exception e) {
+            // If there was an error then the script evaluated to false 
+            engineEval = false;
+        }
+
+        // Evaluate the guard condition
+        // return 1 == (Integer)engine.eval(booleanExpression.toString());
+        return engineEval;
+    }
+
+    /**
+     * Get the size of the guard condition
+     *
+     */
+    public int getSize() {
+
+        if (booleanExpression == null) {
+            return Integer.BYTES;
+        }
+
+        return Integer.BYTES + booleanExpression.length();
+    }
+
+    public void encode(ByteBuffer bb) {
+        if (booleanExpression == null) {
+            bb.putInt(0);
+        } else {
+            bb.putInt(booleanExpression.length());
+            bb.put(booleanExpression.internalBytes());
+        }
+    }
+
+    static Guard decode(ByteBuffer bb) {
+        int exprLength = bb.getInt();
+
+        if (exprLength != 0) {
+            byte[] expr = new byte[exprLength];
+            bb.get(expr);
+            return new Guard(IoTString.shallow(expr));
+        }
+        return new Guard(null);
+    }
+
+    public Guard getCopy() {
+
+        if (booleanExpression == null) {
+            return new Guard(null);
+        }
+
+        return new Guard(IoTString.shallow(booleanExpression.internalBytes()));
+    }
+
+}
\ No newline at end of file
diff --git a/version2/backup/src/java/iotcloud/IoTString.java b/version2/backup/src/java/iotcloud/IoTString.java
new file mode 100644 (file)
index 0000000..83a3fa1
--- /dev/null
@@ -0,0 +1,105 @@
+package iotcloud;
+
+import java.util.Arrays;
+
+/**
+ * IoTString is wraps the underlying byte string.  We don't use the
+ * standard String class as we have bytes and not chars.
+ * @author Brian Demsky <bdemsky@uci.edu>
+ * @version 1.0
+ */
+
+
+final public class IoTString {
+       byte[] array;
+       int hashcode;
+
+       private IoTString() {
+       }
+
+       /**
+        * Builds an IoTString object around the byte array.  This
+        * constructor makes a copy, so the caller is free to modify the byte array.
+        */
+
+       public IoTString(byte[] _array) {
+               array=(byte[]) _array.clone();
+               hashcode=Arrays.hashCode(array);
+       }
+
+       /**
+        * Converts the String object to a byte representation and stores it
+        * into the IoTString object.
+        */
+
+       public IoTString(String str) {
+               array=str.getBytes();
+               hashcode=Arrays.hashCode(array);
+       }
+
+        /**
+        * Internal methods to build an IoTString using the byte[] passed
+        * in.  Caller is responsible for ensuring the byte[] is never
+        * modified.
+        */
+
+       static IoTString shallow(byte[] _array) {
+               IoTString i=new IoTString();
+               i.array = _array;
+               i.hashcode = Arrays.hashCode(_array);
+               return i;
+       }
+
+       /**
+        * Internal method to grab a reference to our byte array.  Caller
+        * must not modify it.
+        */
+
+       byte[] internalBytes() {
+               return array;
+       }
+
+       /**
+        * Returns the hashCode as computed by Arrays.hashcode(byte[]).
+        */
+
+       public int hashCode() {
+               return hashcode;
+       }
+
+       /**
+        * Returns a String representation of the IoTString.
+        */
+
+       public String toString() {
+               return new String(array);
+       }
+
+       /**
+        * Returns a copy of the underlying byte string.
+        */
+
+       public byte[] getBytes() {
+               return (byte[]) array.clone();
+       }
+
+       /**
+        * Returns true if two byte strings have the same content.
+        */
+
+       public boolean equals(Object o) {
+               if (o instanceof IoTString) {
+                       IoTString i=(IoTString)o;
+                       return Arrays.equals(array, i.array);
+               }
+               return false;
+       }
+
+       /**
+        * Returns the length in bytes of the IoTString.
+        */
+
+       public int length() {
+               return array.length;
+       }
+}
diff --git a/version2/backup/src/java/iotcloud/KeyValue.java b/version2/backup/src/java/iotcloud/KeyValue.java
new file mode 100644 (file)
index 0000000..cd4821a
--- /dev/null
@@ -0,0 +1,76 @@
+package iotcloud;
+import java.nio.ByteBuffer;
+
+/**
+ * KeyValue entry for Slot.
+ * @author Brian Demsky <bdemsky@uci.edu>
+ * @version 1.0
+ */
+
+class KeyValue { /*extends Entry */
+       private IoTString key;
+       private IoTString value;
+
+       public KeyValue(IoTString _key, IoTString _value) {
+               key = _key;
+               value = _value;
+       }
+
+       public IoTString getKey() {
+               return key;
+       }
+
+       public IoTString getValue() {
+               return value;
+       }
+
+       static KeyValue decode(ByteBuffer bb) {
+               int keylength = bb.getInt();
+               int valuelength = bb.getInt();
+               byte[] key = new byte[keylength];
+               bb.get(key);
+
+               if (valuelength != 0) {
+                       byte[] value = new byte[valuelength];
+                       bb.get(value);
+                       return new KeyValue(IoTString.shallow(key), IoTString.shallow(value));
+               }
+
+               return new KeyValue(IoTString.shallow(key), null);
+       }
+
+       public void encode(ByteBuffer bb) {
+               bb.putInt(key.length());
+
+               if (value != null) {
+                       bb.putInt(value.length());
+               } else {
+                       bb.putInt(0);
+               }
+
+               bb.put(key.internalBytes());
+
+               if (value != null) {
+                       bb.put(value.internalBytes());
+               }
+       }
+
+       public int getSize() {
+               if (value != null) {
+                       return 2 * Integer.BYTES + key.length() + value.length();
+               }
+
+               return 2 * Integer.BYTES + key.length();
+       }
+
+       public String toString() {
+               if (value == null) {
+                       return "null";
+               }
+               return value.toString();
+       }
+
+       public KeyValue getCopy() {
+               return new KeyValue(key, value);
+       }
+}
diff --git a/version2/backup/src/java/iotcloud/LastMessage.java b/version2/backup/src/java/iotcloud/LastMessage.java
new file mode 100644 (file)
index 0000000..738dff6
--- /dev/null
@@ -0,0 +1,55 @@
+package iotcloud;
+
+import java.nio.ByteBuffer;
+
+/**
+ * This Entry records the last message sent by a given machine.
+ * @author Brian Demsky <bdemsky@uci.edu>
+ * @version 1.0
+ */
+
+
+class LastMessage extends Entry {
+       private long machineid;
+       private long seqnum;
+
+       public LastMessage(Slot slot, long _machineid, long _seqnum) {
+               super(slot);
+               machineid=_machineid;
+               seqnum=_seqnum;
+       }
+
+       public long getMachineID() {
+               return machineid;
+       }
+
+       public long getSequenceNumber() {
+               return seqnum;
+       }
+
+       static Entry decode(Slot slot, ByteBuffer bb) {
+               long machineid=bb.getLong();
+               long seqnum=bb.getLong();
+               return new LastMessage(slot, machineid, seqnum);
+       }
+
+       public void encode(ByteBuffer bb) {
+               bb.put(Entry.TypeLastMessage);
+               bb.putLong(machineid);
+               bb.putLong(seqnum);
+       }
+
+       public int getSize() {
+               return 2*Long.BYTES+Byte.BYTES;
+       }
+
+       public byte getType() {
+               return Entry.TypeLastMessage;
+       }
+
+       public Entry getCopy(Slot s) {
+               return new LastMessage(s, machineid, seqnum);
+       }
+}
+
+
diff --git a/version2/backup/src/java/iotcloud/Liveness.java b/version2/backup/src/java/iotcloud/Liveness.java
new file mode 100644 (file)
index 0000000..2c840e4
--- /dev/null
@@ -0,0 +1,11 @@
+package iotcloud;
+
+/**
+ * Interface common to both classes that record information about the
+ * last message sent by a machine.  (Either a Slot or a LastMessage.
+ * @author Brian Demsky <bdemsky@uci.edu>
+ * @version 1.0
+ */
+
+interface Liveness {
+}
diff --git a/version2/backup/src/java/iotcloud/LocalComm.java b/version2/backup/src/java/iotcloud/LocalComm.java
new file mode 100644 (file)
index 0000000..17e3c05
--- /dev/null
@@ -0,0 +1,23 @@
+package iotcloud;
+
+class LocalComm {
+    private Table t1;
+    private Table t2;
+
+    public LocalComm(Table _t1, Table _t2) {
+        t1 = _t1;
+        t2 = _t2;
+    }
+
+    public byte[] sendDataToLocalDevice(Long deviceId, byte[] data) throws InterruptedException{
+        System.out.println("Passing Locally");
+
+        if (deviceId == t1.getId()) {
+            return t1.localCommInput(data);
+        } else if (deviceId == t2.getId()) {
+            return t2.localCommInput(data);
+        } else {
+            throw new Error("Cannot send to " + deviceId + " using this local comm");
+        }
+    }
+}
\ No newline at end of file
diff --git a/version2/backup/src/java/iotcloud/Makefile b/version2/backup/src/java/iotcloud/Makefile
new file mode 100644 (file)
index 0000000..2d45b63
--- /dev/null
@@ -0,0 +1,17 @@
+all: server
+
+JAVAC = javac
+JAVADOC = javadoc
+BIN_DIR = bin
+DOCS_DIR = docs
+
+server:
+       $(JAVAC) -d $(BIN_DIR) *.java
+
+doc: server
+       $(JAVADOC) -private -d $(DOCS_DIR) *.java
+
+clean:
+       rm -r bin/*
+       rm -r docs/*
+       rm *~
diff --git a/version2/backup/src/java/iotcloud/NewKey.java b/version2/backup/src/java/iotcloud/NewKey.java
new file mode 100644 (file)
index 0000000..0970016
--- /dev/null
@@ -0,0 +1,57 @@
+package iotcloud;
+
+import java.nio.ByteBuffer;
+
+/**
+ * This Entry records the abort sent by a given machine.
+ * @author Ali Younis <ayounis@uci.edu>
+ * @version 1.0
+ */
+
+
+class NewKey extends Entry {
+       private IoTString key;
+       private long machineid;
+
+       public NewKey(Slot slot, IoTString _key, long _machineid) {
+               super(slot);
+               key = _key;
+               machineid = _machineid;
+       }
+
+       public long getMachineID() {
+               return machineid;
+       }
+
+       public IoTString getKey() {
+               return key;
+       }
+
+       static Entry decode(Slot slot, ByteBuffer bb) {
+               int keylength = bb.getInt();
+               byte[] key = new byte[keylength];
+               bb.get(key);
+               long machineid = bb.getLong();
+
+               return new NewKey(slot, IoTString.shallow(key), machineid);
+       }
+
+       public void encode(ByteBuffer bb) {
+               bb.put(Entry.TypeNewKey);
+               bb.putInt(key.length());
+               bb.put(key.internalBytes());
+               bb.putLong(machineid);
+       }
+
+       public int getSize() {
+               return Long.BYTES + Byte.BYTES + Integer.BYTES + key.length();
+       }
+
+       public byte getType() {
+               return Entry.TypeNewKey;
+       }
+
+       public Entry getCopy(Slot s) {
+               return new NewKey(s, key, machineid);
+       }
+}
\ No newline at end of file
diff --git a/version2/backup/src/java/iotcloud/Pair.java b/version2/backup/src/java/iotcloud/Pair.java
new file mode 100644 (file)
index 0000000..73ed6bd
--- /dev/null
@@ -0,0 +1,23 @@
+package iotcloud;
+
+class Pair<A,B> {
+       private A a;
+       private B b;
+
+       Pair(A a, B b) {
+               this.a=a;
+               this.b=b;
+       }
+
+       A getFirst() {
+               return a;
+       }
+
+       B getSecond() {
+               return b;
+       }
+
+       public String toString() {
+               return "<"+a+","+b+">";
+       }
+}
diff --git a/version2/backup/src/java/iotcloud/PendingTransaction.java b/version2/backup/src/java/iotcloud/PendingTransaction.java
new file mode 100644 (file)
index 0000000..1a14674
--- /dev/null
@@ -0,0 +1,138 @@
+package iotcloud;
+
+import java.util.Set;
+import java.util.Map;
+import java.util.HashSet;
+
+import javax.script.ScriptException;
+import java.lang.NullPointerException;
+
+
+class PendingTransaction {
+
+    private Set<KeyValue> keyValueUpdateSet = null;
+    private Set<KeyValue> keyValueGuardSet = null;
+    private long arbitrator = -1;
+    private long machineLocalTransSeqNum = -1;
+
+    public PendingTransaction() {
+        keyValueUpdateSet = new HashSet<KeyValue>();
+        keyValueGuardSet = new HashSet<KeyValue>();
+    }
+
+    /**
+     * Add a new key value to the updates
+     *
+     */
+    public void addKV(KeyValue newKV) {
+
+        KeyValue rmKV = null;
+
+        // Make sure there are no duplicates
+        for (KeyValue kv : keyValueUpdateSet) {
+            if (kv.getKey().equals(newKV.getKey())) {
+
+                // Remove key if we are adding a newer version of the same key
+                rmKV = kv;
+                break;
+            }
+        }
+
+        // Remove key if we are adding a newer version of the same key
+        if (rmKV != null) {
+            keyValueUpdateSet.remove(rmKV);
+        }
+
+        // Add the key to the hash set
+        keyValueUpdateSet.add(newKV);
+    }
+
+
+    /**
+     * Add a new key value to the guard set
+     *
+     */
+    public void addKVGuard(KeyValue newKV) {
+        // Add the key to the hash set
+        keyValueGuardSet.add(newKV);
+    }
+
+    /**
+     * Checks if the arbitrator is the same
+     *
+     */
+    public boolean checkArbitrator(long arb) {
+        if (arbitrator == -1) {
+            arbitrator = arb;
+            return true;
+        }
+
+        return arb == arbitrator;
+    }
+
+    /**
+     * Get the transaction arbitrator
+     *
+     */
+    public long getArbitrator() {
+        return arbitrator;
+    }
+
+    /**
+     * Get the key value update set
+     *
+     */
+    public Set<KeyValue> getKVUpdates() {
+        return keyValueUpdateSet;
+    }
+
+
+    /**
+       * Get the key value update set
+       *
+       */
+    public Set<KeyValue> getKVGuard() {
+        return keyValueGuardSet;
+    }
+
+    public void setMachineLocalTransSeqNum(long _machineLocalTransSeqNum) {
+        machineLocalTransSeqNum = _machineLocalTransSeqNum;
+    }
+
+    public long getMachineLocalTransSeqNum() {
+        return machineLocalTransSeqNum;
+    }
+
+    public boolean evaluateGuard(Map<IoTString, KeyValue> keyValTableCommitted, Map<IoTString, KeyValue> keyValTableSpeculative, Map<IoTString, KeyValue> keyValTablePendingTransSpeculative) {
+        for (KeyValue kvGuard : keyValueGuardSet) {
+
+            // First check if the key is in the speculative table, this is the value of the latest assumption
+            KeyValue kv = keyValTablePendingTransSpeculative.get(kvGuard.getKey());
+
+
+            if (kv == null) {
+                // if it is not in the pending trans table then check the speculative table and use that
+                // value as our latest assumption
+                kv = keyValTableSpeculative.get(kvGuard.getKey());
+            }
+
+
+            if (kv == null) {
+                // if it is not in the speculative table then check the committed table and use that
+                // value as our latest assumption
+                kv = keyValTableCommitted.get(kvGuard.getKey());
+            }
+
+            if (kvGuard.getValue() != null) {
+                if ((kv == null) || (!kvGuard.getValue().equals(kv.getValue()))) {
+                    return false;
+                }
+            } else {
+                if (kv != null) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/version2/backup/src/java/iotcloud/RejectedMessage.java b/version2/backup/src/java/iotcloud/RejectedMessage.java
new file mode 100644 (file)
index 0000000..9c84f18
--- /dev/null
@@ -0,0 +1,88 @@
+package iotcloud;
+import java.nio.ByteBuffer;
+import java.util.HashSet;
+
+/**
+ * Entry for tracking messages that the server rejected.  We have to
+ * make sure that all clients know that this message was rejected to
+ * prevent the server from reusing these messages in an attack.
+ * @author Brian Demsky
+ * @version 1.0
+ */
+
+
+class RejectedMessage extends Entry {
+       /* Machine identifier */
+       private long machineid;
+       /* Oldest sequence number in range */
+       private long oldseqnum;
+       /* Newest sequence number in range */
+       private long newseqnum;
+       /* Is the machine identifier of the relevant slots equal to (or not
+        * equal to) the specified machine identifier. */
+       private boolean equalto;
+       /* Set of machines that have not received notification. */
+       private HashSet<Long> watchset;
+
+       RejectedMessage(Slot slot, long _machineid, long _oldseqnum, long _newseqnum, boolean _equalto) {
+               super(slot);
+               machineid=_machineid;
+               oldseqnum=_oldseqnum;
+               newseqnum=_newseqnum;
+               equalto=_equalto;
+       }
+
+       long getOldSeqNum() {
+               return oldseqnum;
+       }
+
+       long getNewSeqNum() {
+               return newseqnum;
+       }
+
+       boolean getEqual() {
+               return equalto;
+       }
+
+       long getMachineID() {
+               return machineid;
+       }
+
+       static Entry decode(Slot slot, ByteBuffer bb) {
+               long machineid=bb.getLong();
+               long oldseqnum=bb.getLong();
+               long newseqnum=bb.getLong();
+               byte equalto=bb.get();
+               return new RejectedMessage(slot, machineid, oldseqnum, newseqnum, equalto==1);
+       }
+
+       void setWatchSet(HashSet<Long> _watchset) {
+               watchset=_watchset;
+       }
+
+       void removeWatcher(long machineid) {
+               if (watchset.remove(machineid))
+                       if (watchset.isEmpty())
+                               setDead();
+       }
+
+       void encode(ByteBuffer bb) {
+               bb.put(Entry.TypeRejectedMessage);
+               bb.putLong(machineid);
+               bb.putLong(oldseqnum);
+               bb.putLong(newseqnum);
+               bb.put(equalto?(byte)1:(byte)0);
+       }
+
+       int getSize() {
+               return 3*Long.BYTES + 2*Byte.BYTES;
+       }
+
+       byte getType() {
+               return Entry.TypeRejectedMessage;
+       }
+       
+       Entry getCopy(Slot s) {
+               return new RejectedMessage(s, machineid, oldseqnum, newseqnum, equalto);
+       }
+}
diff --git a/version2/backup/src/java/iotcloud/ServerException.java b/version2/backup/src/java/iotcloud/ServerException.java
new file mode 100644 (file)
index 0000000..6d35c43
--- /dev/null
@@ -0,0 +1,8 @@
+package iotcloud;
+
+public class ServerException extends Exception {
+    
+    public ServerException(String message) {
+        super(message);
+    }
+}
diff --git a/version2/backup/src/java/iotcloud/Slot.java b/version2/backup/src/java/iotcloud/Slot.java
new file mode 100644 (file)
index 0000000..ab04359
--- /dev/null
@@ -0,0 +1,222 @@
+package iotcloud;
+import java.util.Vector;
+import java.nio.ByteBuffer;
+import javax.crypto.Mac;
+import java.util.Arrays;
+
+/**
+ * Data structuring for holding Slot information.
+ * @author Brian Demsky
+ * @version 1.0
+ */
+
+class Slot implements Liveness {
+       /** Sets the slot size. */
+       static final int SLOT_SIZE = 2048;
+       /** Sets the size for the HMAC. */
+       static final int HMAC_SIZE = 32;
+
+       /** Sequence number of the slot. */
+       private long seqnum;
+       /** HMAC of previous slot. */
+       private byte[] prevhmac;
+       /** HMAC of this slot. */
+       private byte[] hmac;
+       /** Machine that sent this slot. */
+       private long machineid;
+       /** Vector of entries in this slot. */
+       private Vector<Entry> entries;
+       /** Pieces of information that are live. */
+       private int livecount;
+       /** Flag that indicates whether this slot is still live for
+        * recording the machine that sent it. */
+       private boolean seqnumlive;
+       /** Number of bytes of free space. */
+       private int freespace;
+       /** Reference to Table */
+       private Table table;
+
+       Slot(Table _table, long _seqnum, long _machineid, byte[] _prevhmac, byte[] _hmac) {
+               seqnum = _seqnum;
+               machineid = _machineid;
+               prevhmac = _prevhmac;
+               hmac = _hmac;
+               entries = new Vector<Entry>();
+               livecount = 1;
+               seqnumlive = true;
+               freespace = SLOT_SIZE - getBaseSize();
+               table = _table;
+       }
+
+       Slot(Table _table, long _seqnum, long _machineid, byte[] _prevhmac) {
+               this(_table, _seqnum, _machineid, _prevhmac, null);
+       }
+
+       Slot(Table _table, long _seqnum, long _machineid) {
+               this(_table, _seqnum, _machineid, new byte[HMAC_SIZE], null);
+       }
+
+       byte[] getHMAC() {
+               return hmac;
+       }
+
+       byte[] getPrevHMAC() {
+               return prevhmac;
+       }
+
+       Entry addEntry(Entry e) {
+               e = e.getCopy(this);
+               entries.add(e);
+               livecount++;
+               freespace -= e.getSize();
+               return e;
+       }
+
+       void removeEntry(Entry e) {
+               entries.remove(e);
+               livecount--;
+               freespace += e.getSize();
+       }
+
+       private void addShallowEntry(Entry e) {
+               entries.add(e);
+               livecount++;
+               freespace -= e.getSize();
+       }
+
+       /**
+        * Returns true if the slot has free space to hold the entry without
+        * using its reserved space. */
+
+       boolean hasSpace(Entry e) {
+               int newfreespace = freespace - e.getSize();
+               return newfreespace >= 0;
+       }
+
+       Vector<Entry> getEntries() {
+               return entries;
+       }
+
+       static Slot decode(Table table, byte[] array, Mac mac) {
+               mac.update(array, HMAC_SIZE, array.length - HMAC_SIZE);
+               byte[] realmac = mac.doFinal();
+
+               ByteBuffer bb = ByteBuffer.wrap(array);
+               byte[] hmac = new byte[HMAC_SIZE];
+               byte[] prevhmac = new byte[HMAC_SIZE];
+               bb.get(hmac);
+               bb.get(prevhmac);
+               if (!Arrays.equals(realmac, hmac))
+                       throw new Error("Server Error: Invalid HMAC!  Potential Attack!");
+
+               long seqnum = bb.getLong();
+               long machineid = bb.getLong();
+               int numentries = bb.getInt();
+               Slot slot = new Slot(table, seqnum, machineid, prevhmac, hmac);
+
+               for (int i = 0; i < numentries; i++) {
+                       slot.addShallowEntry(Entry.decode(slot, bb));
+               }
+
+               return slot;
+       }
+
+       byte[] encode(Mac mac) {
+               byte[] array = new byte[SLOT_SIZE];
+               ByteBuffer bb = ByteBuffer.wrap(array);
+               /* Leave space for the slot HMAC.  */
+               bb.position(HMAC_SIZE);
+               bb.put(prevhmac);
+               bb.putLong(seqnum);
+               bb.putLong(machineid);
+               bb.putInt(entries.size());
+               for (Entry entry : entries) {
+                       entry.encode(bb);
+               }
+               /* Compute our HMAC */
+               mac.update(array, HMAC_SIZE, array.length - HMAC_SIZE);
+               byte[] realmac = mac.doFinal();
+               hmac = realmac;
+               bb.position(0);
+               bb.put(realmac);
+               return array;
+       }
+
+       /**
+        * Returns the empty size of a Slot. Includes 2 HMACs, the machine
+        * identifier, the sequence number, and the number of entries.
+        */
+       int getBaseSize() {
+               return 2 * HMAC_SIZE + 2 * Long.BYTES + Integer.BYTES;
+       }
+
+       /**
+        * Returns the live set of entries for this Slot.  Generates a fake
+        * LastMessage entry to represent the information stored by the slot
+        * itself.
+        */
+
+       Vector<Entry> getLiveEntries(boolean resize) {
+               Vector<Entry> liveEntries = new Vector<Entry>();
+               for (Entry entry : entries) {
+                       if (entry.isLive()) {
+                               if (!resize || entry.getType() != Entry.TypeTableStatus)
+                                       liveEntries.add(entry);
+                       }
+               }
+
+               if (seqnumlive && !resize)
+                       liveEntries.add(new LastMessage(this, machineid, seqnum));
+
+               return liveEntries;
+       }
+
+       /**
+        * Returns the sequence number of the slot.
+        */
+
+       long getSequenceNumber() {
+               return seqnum;
+       }
+
+       /**
+        * Returns the machine that sent this slot.
+        */
+
+       long getMachineID() {
+               return machineid;
+       }
+
+       /**
+        * Records that a newer slot records the fact that this slot was
+        * sent by the relevant machine.
+        */
+
+       void setDead() {
+               seqnumlive = false;
+               decrementLiveCount();
+       }
+
+       /**
+        * Update the count of live entries.
+        */
+
+       void decrementLiveCount() {
+               livecount--;
+               if (livecount == 0) {
+                       table.decrementLiveCount();
+               }
+       }
+
+       /**
+        * Returns whether the slot stores any live information.
+        */
+
+       boolean isLive() {
+               return livecount > 0;
+       }
+
+       public String toString() {
+               return "<" + getSequenceNumber() + ">";
+       }
+}
diff --git a/version2/backup/src/java/iotcloud/SlotBuffer.java b/version2/backup/src/java/iotcloud/SlotBuffer.java
new file mode 100644 (file)
index 0000000..716d0f2
--- /dev/null
@@ -0,0 +1,122 @@
+package iotcloud;
+
+/**
+ * Circular buffer that holds the live set of slots.
+ * @author Brian Demsky
+ * @version 1.0
+ */
+
+class SlotBuffer {
+       static final int DEFAULT_SIZE = 128;
+
+       private Slot[] array;
+       private int head;
+       private int tail;
+       public long oldestseqn;
+
+       SlotBuffer() {
+               array = new Slot[DEFAULT_SIZE + 1];
+               head = tail = 0;
+               oldestseqn = 0;
+       }
+
+       int size() {
+               if (head >= tail)
+                       return head - tail;
+               return (array.length + head) - tail;
+       }
+
+       int capacity() {
+               return array.length - 1;
+       }
+
+       void resize(int newsize) {
+               if (newsize == (array.length - 1))
+                       return;
+
+               Slot[] newarray = new Slot[newsize + 1];
+               int currsize = size();
+               int index = tail;
+               for (int i = 0; i < currsize; i++) {
+                       newarray[i] = array[index];
+                       if ((++index) == array.length)
+                               index = 0;
+               }
+               array = newarray;
+               tail = 0;
+               head = currsize;
+       }
+
+       private void incrementHead() {
+               head++;
+               if (head >= array.length)
+                       head = 0;
+       }
+
+       private void incrementTail() {
+               tail++;
+               if (tail >= array.length)
+                       tail = 0;
+       }
+
+       void putSlot(Slot s) {
+
+               long checkNum = (getNewestSeqNum() + 1);
+
+               if (checkNum != s.getSequenceNumber()) {
+                       // We have a gap so expunge all our slots
+                       oldestseqn = s.getSequenceNumber();
+                       tail = 0;
+                       head = 1;
+                       array[0] = s;
+                       return;
+               }
+
+               array[head] = s;
+               incrementHead();
+
+               if (oldestseqn == 0) {
+                       oldestseqn = s.getSequenceNumber();
+               }
+
+               if (head == tail) {
+                       incrementTail();
+                       oldestseqn++;
+               }
+       }
+
+       Slot getSlot(long seqnum) {
+               int diff = (int) (seqnum - oldestseqn);
+               int index = diff + tail;
+
+               if (index < 0) {
+                       // Really old message so we dont have it anymore
+                       return null;
+               }
+
+               if (index >= array.length) {
+                       if (head >= tail) {
+                               return null;
+                       }
+                       index -= array.length;
+               }
+
+               if (index >= array.length) {
+
+                       return null;
+               }
+               if (head >= tail && index >= head) {
+                       return null;
+               }
+
+               return array[index];
+       }
+
+       long getOldestSeqNum() {
+               return oldestseqn;
+       }
+
+       long getNewestSeqNum() {
+               return oldestseqn + size() - 1;
+       }
+}
diff --git a/version2/backup/src/java/iotcloud/SlotIndexer.java b/version2/backup/src/java/iotcloud/SlotIndexer.java
new file mode 100644 (file)
index 0000000..cecdf2d
--- /dev/null
@@ -0,0 +1,31 @@
+package iotcloud;
+
+/**
+ * Slot indexer allows slots in both the slot buffer and the new
+ * server response to looked up in a consistent fashion.
+ * @author Brian Demsky
+ * @version 1.0
+ */
+
+class SlotIndexer {
+       private Slot[] updates;
+       private SlotBuffer buffer;
+       private long firstslotseqnum;
+
+       SlotIndexer(Slot[] _updates, SlotBuffer _buffer) {
+               buffer = _buffer;
+               updates = _updates;
+               firstslotseqnum = updates[0].getSequenceNumber();
+       }
+
+       Slot getSlot(long seqnum) {
+               if (seqnum >= firstslotseqnum) {
+                       int offset = (int) (seqnum - firstslotseqnum);
+                       if (offset >= updates.length)
+                               throw new Error("Invalid Slot Sequence Number Reference");
+                       else
+                               return updates[offset];
+               } else
+                       return buffer.getSlot(seqnum);
+       }
+}
diff --git a/version2/backup/src/java/iotcloud/Table.java b/version2/backup/src/java/iotcloud/Table.java
new file mode 100644 (file)
index 0000000..f6d699b
--- /dev/null
@@ -0,0 +1,1728 @@
+package iotcloud;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.HashSet;
+import java.util.Arrays;
+import java.util.Vector;
+import java.util.Random;
+import java.util.Queue;
+import java.util.LinkedList;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.Collection;
+import java.util.Collections;
+import java.nio.ByteBuffer;
+import java.util.concurrent.Semaphore;
+
+
+/**
+ * IoTTable data structure.  Provides client inferface.
+ * @author Brian Demsky
+ * @version 1.0
+ */
+
+final public class Table {
+       private int numslots;   //number of slots stored in buffer
+
+       // machine id -> (sequence number, Slot or LastMessage); records last message by each client
+       private HashMap<Long, Pair<Long, Liveness> > lastmessagetable = new HashMap<Long, Pair<Long, Liveness> >();
+       // machine id -> ...
+       private HashMap<Long, HashSet<RejectedMessage> > watchlist = new HashMap<Long, HashSet<RejectedMessage> >();
+       private Vector<Long> rejectedmessagelist = new Vector<Long>();
+       private SlotBuffer buffer;
+       private CloudComm cloud;
+       private long sequencenumber; //Largest sequence number a client has received
+       private long localmachineid;
+       private TableStatus lastTableStatus;
+       static final int FREE_SLOTS = 10; //number of slots that should be kept free
+       static final int SKIP_THRESHOLD = 10;
+       private long liveslotcount = 0;
+       private int chance;
+       static final double RESIZE_MULTIPLE = 1.2;
+       static final double RESIZE_THRESHOLD = 0.75;
+       static final int REJECTED_THRESHOLD = 5;
+       private int resizethreshold;
+       private long lastliveslotseqn;  //smallest sequence number with a live entry
+       private Random random = new Random();
+       private long lastUncommittedTransaction = 0;
+
+       private int smallestTableStatusSeen = -1;
+       private int largestTableStatusSeen = -1;
+       private int lastSeenPendingTransactionSpeculateIndex = 0;
+       private int commitSequenceNumber = 0;
+       private long localTransactionSequenceNumber = 0;
+
+       private PendingTransaction pendingTransBuild = null; // Pending Transaction used in building
+       private LinkedList<PendingTransaction> pendingTransQueue = null; // Queue of pending transactions
+       private Map<Long, Map<Long, Commit>> commitMap = null; // List of all the most recent live commits
+       private Map<Long, Abort> abortMap = null; // Set of the live aborts
+       private Map<IoTString, Commit> committedMapByKey = null; // Table of committed KV
+       private Map<IoTString, KeyValue> commitedTable = null; // Table of committed KV
+       private Map<IoTString, KeyValue> speculativeTable = null; // Table of speculative KV
+       private Map<Long, Transaction> uncommittedTransactionsMap = null;
+       private Map<IoTString, Long> arbitratorTable = null; // Table of arbitrators
+       private Map<IoTString, NewKey> newKeyTable = null; // Table of speculative KV
+       private Map<Long, Map<Long, Commit>> newCommitMap = null; // Map of all the new commits
+       private Map<Long, Long> lastCommitSeenSeqNumMap = null; // sequence number of the last commit that was seen grouped by arbitrator
+       private Map<Long, Long> lastCommitSeenTransSeqNumMap = null; // transaction sequence number of the last commit that was seen grouped by arbitrator
+       private Map<Long, Long> lastAbortSeenSeqNumMap = null; // sequence number of the last abort that was seen grouped by arbitrator
+       private Map<IoTString, KeyValue> pendingTransSpeculativeTable = null;
+       private List<Commit> pendingCommitsList = null;
+       private List<Commit> pendingCommitsToDelete = null;
+       private Map<Long, LocalComm> localCommunicationChannels;
+       private Map<Long, TransactionStatus> transactionStatusMap = null;
+       private Map<Long, TransactionStatus> transactionStatusNotSentMap = null;
+
+       private Semaphore mutex = null;
+
+
+
+       public Table(String hostname, String baseurl, String password, long _localmachineid) {
+               localmachineid = _localmachineid;
+               buffer = new SlotBuffer();
+               numslots = buffer.capacity();
+               setResizeThreshold();
+               sequencenumber = 0;
+               cloud = new CloudComm(this, hostname, baseurl, password);
+               lastliveslotseqn = 1;
+
+               setupDataStructs();
+       }
+
+       public Table(CloudComm _cloud, long _localmachineid) {
+               localmachineid = _localmachineid;
+               buffer = new SlotBuffer();
+               numslots = buffer.capacity();
+               setResizeThreshold();
+               sequencenumber = 0;
+               cloud = _cloud;
+
+               setupDataStructs();
+       }
+
+       private void setupDataStructs() {
+               pendingTransQueue = new LinkedList<PendingTransaction>();
+               commitMap = new HashMap<Long, Map<Long, Commit>>();
+               abortMap = new HashMap<Long, Abort>();
+               committedMapByKey = new HashMap<IoTString, Commit>();
+               commitedTable = new HashMap<IoTString, KeyValue>();
+               speculativeTable = new HashMap<IoTString, KeyValue>();
+               uncommittedTransactionsMap = new HashMap<Long, Transaction>();
+               arbitratorTable = new HashMap<IoTString, Long>();
+               newKeyTable = new HashMap<IoTString, NewKey>();
+               newCommitMap = new HashMap<Long, Map<Long, Commit>>();
+               lastCommitSeenSeqNumMap = new HashMap<Long, Long>();
+               lastCommitSeenTransSeqNumMap = new HashMap<Long, Long>();
+               lastAbortSeenSeqNumMap = new HashMap<Long, Long>();
+               pendingTransSpeculativeTable = new HashMap<IoTString, KeyValue>();
+               pendingCommitsList = new LinkedList<Commit>();
+               pendingCommitsToDelete = new LinkedList<Commit>();
+               localCommunicationChannels = new HashMap<Long, LocalComm>();
+               transactionStatusMap = new HashMap<Long, TransactionStatus>();
+               transactionStatusNotSentMap = new HashMap<Long, TransactionStatus>();
+               mutex = new Semaphore(1);
+       }
+
+       public void initTable() throws ServerException {
+               cloud.setSalt();//Set the salt
+               Slot s = new Slot(this, 1, localmachineid);
+               TableStatus status = new TableStatus(s, numslots);
+               s.addEntry(status);
+               Slot[] array = cloud.putSlot(s, numslots);
+               if (array == null) {
+                       array = new Slot[] {s};
+                       /* update data structure */
+                       validateandupdate(array, true);
+               } else {
+                       throw new Error("Error on initialization");
+               }
+       }
+
+       public void rebuild() throws ServerException, InterruptedException {
+               mutex.acquire();
+               Slot[] newslots = cloud.getSlots(sequencenumber + 1);
+               validateandupdate(newslots, true);
+               mutex.release();
+       }
+
+       // TODO: delete method
+       public void printSlots() {
+               long o = buffer.getOldestSeqNum();
+               long n = buffer.getNewestSeqNum();
+
+               int[] types = new int[10];
+
+               int num = 0;
+
+               int livec = 0;
+               int deadc = 0;
+               for (long i = o; i < (n + 1); i++) {
+                       Slot s = buffer.getSlot(i);
+
+                       Vector<Entry> entries = s.getEntries();
+
+                       for (Entry e : entries) {
+                               if (e.isLive()) {
+                                       int type = e.getType();
+                                       types[type] = types[type] + 1;
+                                       num++;
+                                       livec++;
+                               } else {
+                                       deadc++;
+                               }
+                       }
+               }
+
+               for (int i = 0; i < 10; i++) {
+                       System.out.println(i + "    " + types[i]);
+               }
+               System.out.println("Live count:   " + livec);
+               System.out.println("Dead count:   " + deadc);
+               System.out.println("Old:   " + o);
+               System.out.println("New:   " + n);
+               System.out.println("Size:   " + buffer.size());
+               System.out.println("Commits Key Map:   " + commitedTable.size());
+               // System.out.println("Commits Live Map:   " + commitMap.size());
+               System.out.println("Pending:   " + pendingTransQueue.size());
+
+               // List<IoTString> strList = new ArrayList<IoTString>();
+               // for (int i = 0; i < 100; i++) {
+               //      String keyA = "a" + i;
+               //      String keyB = "b" + i;
+               //      String keyC = "c" + i;
+               //      String keyD = "d" + i;
+
+               //      IoTString iKeyA = new IoTString(keyA);
+               //      IoTString iKeyB = new IoTString(keyB);
+               //      IoTString iKeyC = new IoTString(keyC);
+               //      IoTString iKeyD = new IoTString(keyD);
+
+               //      strList.add(iKeyA);
+               //      strList.add(iKeyB);
+               //      strList.add(iKeyC);
+               //      strList.add(iKeyD);
+               // }
+
+
+               // for (Long l : commitMap.keySet()) {
+               //      for (Long l2 : commitMap.get(l).keySet()) {
+               //              for (KeyValue kv : commitMap.get(l).get(l2).getkeyValueUpdateSet()) {
+               //                      strList.remove(kv.getKey());
+               //                      System.out.print(kv.getKey() + "    ");
+               //              }
+               //      }
+               // }
+
+               // System.out.println();
+               // System.out.println();
+
+               // for (IoTString s : strList) {
+               //      System.out.print(s + "    ");
+               // }
+               // System.out.println();
+               // System.out.println(strList.size());
+       }
+
+       public long getId() {
+               return localmachineid;
+       }
+
+       public boolean hasConnection() {
+               return cloud.hasConnection();
+       }
+
+       public String toString() {
+               String retString = " Committed Table: \n";
+               retString += "---------------------------\n";
+               retString += commitedTable.toString();
+
+               retString += "\n\n";
+
+               retString += " Speculative Table: \n";
+               retString += "---------------------------\n";
+               retString += speculativeTable.toString();
+
+               return retString;
+       }
+
+       public void addLocalComm(long machineId, LocalComm lc) {
+               localCommunicationChannels.put(machineId, lc);
+       }
+       public Long getArbitrator(IoTString key) throws InterruptedException {
+
+               mutex.acquire();
+               Long arb = arbitratorTable.get(key);
+               mutex.release();
+
+               return arb;
+       }
+
+       public IoTString getCommitted(IoTString key) throws InterruptedException {
+
+               mutex.acquire();
+               KeyValue kv = commitedTable.get(key);
+               mutex.release();
+
+
+               if (kv != null) {
+                       return kv.getValue();
+               } else {
+                       return null;
+               }
+       }
+
+       public IoTString getSpeculative(IoTString key) throws InterruptedException {
+
+               mutex.acquire();
+
+               KeyValue kv = pendingTransSpeculativeTable.get(key);
+
+               if (kv == null) {
+                       kv = speculativeTable.get(key);
+               }
+
+               if (kv == null) {
+                       kv = commitedTable.get(key);
+               }
+               mutex.release();
+
+
+               if (kv != null) {
+                       return kv.getValue();
+               } else {
+                       return null;
+               }
+       }
+
+       public IoTString getCommittedAtomic(IoTString key) throws InterruptedException {
+
+               mutex.acquire();
+
+               KeyValue kv = commitedTable.get(key);
+
+               if (arbitratorTable.get(key) == null) {
+                       throw new Error("Key not Found.");
+               }
+
+               // Make sure new key value pair matches the current arbitrator
+               if (!pendingTransBuild.checkArbitrator(arbitratorTable.get(key))) {
+                       // TODO: Maybe not throw en error
+                       throw new Error("Not all Key Values Match Arbitrator.");
+               }
+
+               mutex.release();
+
+               if (kv != null) {
+                       pendingTransBuild.addKVGuard(new KeyValue(key, kv.getValue()));
+                       return kv.getValue();
+               } else {
+                       pendingTransBuild.addKVGuard(new KeyValue(key, null));
+                       return null;
+               }
+       }
+
+       public IoTString getSpeculativeAtomic(IoTString key) throws InterruptedException {
+
+               mutex.acquire();
+
+               if (arbitratorTable.get(key) == null) {
+                       throw new Error("Key not Found.");
+               }
+
+               // Make sure new key value pair matches the current arbitrator
+               if (!pendingTransBuild.checkArbitrator(arbitratorTable.get(key))) {
+                       // TODO: Maybe not throw en error
+                       throw new Error("Not all Key Values Match Arbitrator.");
+               }
+
+               KeyValue kv = pendingTransSpeculativeTable.get(key);
+
+               if (kv == null) {
+                       kv = speculativeTable.get(key);
+               }
+
+               if (kv == null) {
+                       kv = commitedTable.get(key);
+               }
+
+               mutex.release();
+
+               if (kv != null) {
+                       pendingTransBuild.addKVGuard(new KeyValue(key, kv.getValue()));
+                       return kv.getValue();
+               } else {
+                       pendingTransBuild.addKVGuard(new KeyValue(key, null));
+                       return null;
+               }
+       }
+
+       public Pair<Boolean, Boolean> update() throws InterruptedException {
+
+               mutex.acquire();
+
+               boolean gotLatestFromServer = false;
+               boolean didSendLocal = false;
+
+               try {
+                       Slot[] newslots = cloud.getSlots(sequencenumber + 1);
+                       validateandupdate(newslots, false);
+                       gotLatestFromServer = true;
+
+                       if (!pendingTransQueue.isEmpty()) {
+
+                               // We have a pending transaction so do full insertion
+                               processPendingTrans();
+                       } else {
+
+                               // We dont have a pending transaction so do minimal effort
+                               updateWithNotPendingTrans();
+                       }
+
+                       didSendLocal = true;
+
+
+               } catch (Exception e) {
+                       // could not update so do nothing
+               }
+
+
+               mutex.release();
+               return new Pair<Boolean, Boolean>(gotLatestFromServer, didSendLocal);
+       }
+
+       public Boolean updateFromLocal(long arb) throws InterruptedException {
+               LocalComm lc = localCommunicationChannels.get(arb);
+               if (lc == null) {
+                       // Cant talk directly to arbitrator so cant do anything
+                       return false;
+               }
+
+               byte[] array = new byte[Long.BYTES ];
+               ByteBuffer bbEncode = ByteBuffer.wrap(array);
+               Long lastSeenCommit = lastCommitSeenSeqNumMap.get(arb);
+               if (lastSeenCommit != null) {
+                       bbEncode.putLong(lastSeenCommit);
+               } else {
+                       bbEncode.putLong(0);
+               }
+
+               mutex.acquire();
+               byte[] data = lc.sendDataToLocalDevice(arb, bbEncode.array());
+
+               // Decode the data
+               ByteBuffer bbDecode = ByteBuffer.wrap(data);
+               boolean didCommit = bbDecode.get() == 1;
+               int numberOfCommites = bbDecode.getInt();
+
+               List<Commit> newCommits = new LinkedList<Commit>();
+               for (int i = 0; i < numberOfCommites; i++ ) {
+                       bbDecode.get();
+                       Commit com = (Commit)Commit.decode(null, bbDecode);
+                       newCommits.add(com);
+               }
+
+               for (Commit commit : newCommits) {
+                       // Prepare to process the commit
+                       processEntry(commit);
+               }
+
+               boolean didCommitOrSpeculate = proccessAllNewCommits();
+
+               // Go through all uncommitted transactions and kill the ones that are dead
+               deleteDeadUncommittedTransactions();
+
+               // Speculate on key value pairs
+               didCommitOrSpeculate |= createSpeculativeTable();
+               createPendingTransactionSpeculativeTable(didCommitOrSpeculate);
+
+
+               mutex.release();
+
+               return true;
+       }
+
+       public void startTransaction() throws InterruptedException {
+               // Create a new transaction, invalidates any old pending transactions.
+               pendingTransBuild = new PendingTransaction();
+       }
+
+       public void addKV(IoTString key, IoTString value) {
+
+               if (arbitratorTable.get(key) == null) {
+                       throw new Error("Key not Found.");
+               }
+
+               // Make sure new key value pair matches the current arbitrator
+               if (!pendingTransBuild.checkArbitrator(arbitratorTable.get(key))) {
+                       // TODO: Maybe not throw en error
+                       throw new Error("Not all Key Values Match Arbitrator.");
+               }
+
+               KeyValue kv = new KeyValue(key, value);
+               pendingTransBuild.addKV(kv);
+       }
+
+       public TransactionStatus commitTransaction() throws InterruptedException {
+
+               if (pendingTransBuild.getKVUpdates().size() == 0) {
+
+                       // transaction with no updates will have no effect on the system
+                       return new TransactionStatus(TransactionStatus.StatusNoEffect, -1);
+               }
+
+               mutex.acquire();
+
+               TransactionStatus transStatus = null;
+
+               if (pendingTransBuild.getArbitrator() != localmachineid) {
+
+                       // set the local sequence number so we can recognize this transaction later
+                       pendingTransBuild.setMachineLocalTransSeqNum(localTransactionSequenceNumber);
+                       localTransactionSequenceNumber++;
+
+                       transStatus = new TransactionStatus(TransactionStatus.StatusPending, pendingTransBuild.getArbitrator());
+                       transactionStatusNotSentMap.put(pendingTransBuild.getMachineLocalTransSeqNum(), transStatus);
+
+                       // Add the pending transaction to the queue
+                       pendingTransQueue.add(pendingTransBuild);
+
+
+                       for (int i = lastSeenPendingTransactionSpeculateIndex; i < pendingTransQueue.size(); i++) {
+                               PendingTransaction pt = pendingTransQueue.get(i);
+
+                               if (pt.evaluateGuard(commitedTable, speculativeTable, pendingTransSpeculativeTable)) {
+
+                                       lastSeenPendingTransactionSpeculateIndex = i;
+
+                                       for (KeyValue kv : pt.getKVUpdates()) {
+                                               pendingTransSpeculativeTable.put(kv.getKey(), kv);
+                                       }
+
+                               }
+                       }
+               } else {
+                       Transaction ut = new Transaction(null,
+                                                        -1,
+                                                        localmachineid,
+                                                        pendingTransBuild.getArbitrator(),
+                                                        pendingTransBuild.getKVUpdates(),
+                                                        pendingTransBuild.getKVGuard());
+
+                       Pair<Boolean, List<Commit>> retData = doLocalUpdateAndArbitrate(ut, lastCommitSeenSeqNumMap.get(localmachineid));
+
+                       if (retData.getFirst()) {
+                               transStatus = new TransactionStatus(TransactionStatus.StatusCommitted, pendingTransBuild.getArbitrator());
+                       } else {
+                               transStatus = new TransactionStatus(TransactionStatus.StatusAborted, pendingTransBuild.getArbitrator());
+                       }
+               }
+
+               // Try to insert transactions if possible
+               if (!pendingTransQueue.isEmpty()) {
+                       // We have a pending transaction so do full insertion
+                       processPendingTrans();
+               } else {
+                       try {
+                               // We dont have a pending transaction so do minimal effort
+                               updateWithNotPendingTrans();
+                       } catch (Exception e) {
+                               // Do nothing
+                       }
+               }
+
+               // reset it so next time is fresh
+               pendingTransBuild = new PendingTransaction();
+
+
+               mutex.release();
+               return transStatus;
+       }
+
+       public boolean createNewKey(IoTString keyName, long machineId) throws ServerException, InterruptedException {
+               try {
+                       mutex.acquire();
+
+                       while (true) {
+                               if (arbitratorTable.get(keyName) != null) {
+                                       // There is already an arbitrator
+                                       mutex.release();
+                                       return false;
+                               }
+
+                               if (tryput(keyName, machineId, false)) {
+                                       // If successfully inserted
+                                       mutex.release();
+                                       return true;
+                               }
+                       }
+               } catch (ServerException e) {
+                       mutex.release();
+                       throw e;
+               }
+       }
+
+       private void processPendingTrans() throws InterruptedException {
+
+               boolean sentAllPending = false;
+               try {
+                       while (!pendingTransQueue.isEmpty()) {
+                               if (tryput( pendingTransQueue.peek(), false)) {
+                                       pendingTransQueue.poll();
+                               }
+                       }
+
+                       // if got here then all pending transactions were sent
+                       sentAllPending = true;
+               } catch (Exception e) {
+                       // There was a connection error
+                       sentAllPending = false;
+               }
+
+               if (!sentAllPending) {
+
+                       for (Iterator<PendingTransaction> i = pendingTransQueue.iterator(); i.hasNext(); ) {
+                               PendingTransaction pt = i.next();
+                               LocalComm lc = localCommunicationChannels.get(pt.getArbitrator());
+                               if (lc == null) {
+                                       // Cant talk directly to arbitrator so cant do anything
+                                       continue;
+                               }
+
+
+                               Transaction ut = new Transaction(null,
+                                                                -1,
+                                                                localmachineid,
+                                                                pendingTransBuild.getArbitrator(),
+                                                                pendingTransBuild.getKVUpdates(),
+                                                                pendingTransBuild.getKVGuard());
+
+
+                               Pair<Boolean, List<Commit>> retData = sendTransactionToLocal(ut, lc);
+
+                               for (Commit commit : retData.getSecond()) {
+                                       // Prepare to process the commit
+                                       processEntry(commit);
+                               }
+
+                               boolean didCommitOrSpeculate = proccessAllNewCommits();
+
+                               // Go through all uncommitted transactions and kill the ones that are dead
+                               deleteDeadUncommittedTransactions();
+
+                               // Speculate on key value pairs
+                               didCommitOrSpeculate |= createSpeculativeTable();
+                               createPendingTransactionSpeculativeTable(didCommitOrSpeculate);
+
+                               if (retData.getFirst()) {
+                                       TransactionStatus transStatus = transactionStatusNotSentMap.remove(pendingTransBuild.getMachineLocalTransSeqNum());
+                                       if (transStatus != null) {
+                                               transStatus.setStatus(TransactionStatus.StatusCommitted);
+                                       }
+
+                               } else {
+                                       TransactionStatus transStatus = transactionStatusNotSentMap.remove(pendingTransBuild.getMachineLocalTransSeqNum());
+                                       if (transStatus != null) {
+                                               transStatus.setStatus(TransactionStatus.StatusAborted);
+                                       }
+                               }
+                               i.remove();
+                       }
+               }
+       }
+
+       private void updateWithNotPendingTrans() throws ServerException, InterruptedException {
+               boolean doEnd = false;
+               boolean needResize = false;
+               while (!doEnd && ((uncommittedTransactionsMap.keySet().size() > 0)  || (pendingCommitsList.size() > 0))   ) {
+                       boolean resize = needResize;
+                       needResize = false;
+
+                       Slot s = new Slot(this, sequencenumber + 1, localmachineid, buffer.getSlot(sequencenumber).getHMAC());
+                       int newsize = 0;
+                       if (liveslotcount > resizethreshold) {
+                               resize = true; //Resize is forced
+                       }
+
+                       if (resize) {
+                               newsize = (int) (numslots * RESIZE_MULTIPLE);
+                               TableStatus status = new TableStatus(s, newsize);
+                               s.addEntry(status);
+                       }
+
+                       doRejectedMessages(s);
+
+                       ThreeTuple<Boolean, Boolean, Long> retTup = doMandatoryResuce(s, resize);
+
+                       // Resize was needed so redo call
+                       if (retTup.getFirst()) {
+                               needResize = true;
+                               continue;
+                       }
+
+                       // Extract working variables
+                       boolean seenliveslot = retTup.getSecond();
+                       long seqn = retTup.getThird();
+
+                       // Did need to arbitrate
+                       doEnd = !doArbitration(s);
+
+                       doOptionalRescue(s, seenliveslot, seqn, resize);
+
+                       int max = 0;
+                       if (resize) {
+                               max = newsize;
+                       }
+
+                       Slot[] array = cloud.putSlot(s, max);
+                       if (array == null) {
+                               array = new Slot[] {s};
+                               rejectedmessagelist.clear();
+
+                               // Delete pending commits that were sent to the cloud
+                               deletePendingCommits();
+
+                       }       else {
+                               if (array.length == 0)
+                                       throw new Error("Server Error: Did not send any slots");
+                               rejectedmessagelist.add(s.getSequenceNumber());
+                               doEnd = false;
+                       }
+
+                       /* update data structure */
+                       validateandupdate(array, true);
+               }
+       }
+
+       private Pair<Boolean, List<Commit>> sendTransactionToLocal(Transaction ut, LocalComm lc) throws InterruptedException {
+
+               // encode the request
+               byte[] array = new byte[Long.BYTES + ut.getSize()];
+               ByteBuffer bbEncode = ByteBuffer.wrap(array);
+               Long lastSeenCommit = lastCommitSeenSeqNumMap.get(ut.getArbitrator());
+               if (lastSeenCommit != null) {
+                       bbEncode.putLong(lastSeenCommit);
+               } else {
+                       bbEncode.putLong(0);
+               }
+               ut.encode(bbEncode);
+
+               byte[] data = lc.sendDataToLocalDevice(ut.getArbitrator(), bbEncode.array());
+
+               // Decode the data
+               ByteBuffer bbDecode = ByteBuffer.wrap(data);
+               boolean didCommit = bbDecode.get() == 1;
+               int numberOfCommites = bbDecode.getInt();
+
+               List<Commit> newCommits = new LinkedList<Commit>();
+               for (int i = 0; i < numberOfCommites; i++ ) {
+                       bbDecode.get();
+                       Commit com = (Commit)Commit.decode(null, bbDecode);
+                       newCommits.add(com);
+               }
+
+               return new Pair<Boolean, List<Commit>>(didCommit, newCommits);
+       }
+
+       public byte[] localCommInput(byte[] data) throws InterruptedException {
+
+
+
+               // Decode the data
+               ByteBuffer bbDecode = ByteBuffer.wrap(data);
+               long lastSeenCommit = bbDecode.getLong();
+
+               Transaction ut = null;
+               if (data.length != Long.BYTES) {
+                       bbDecode.get();
+                       ut = (Transaction)Transaction.decode(null, bbDecode);
+               }
+
+               mutex.acquire();
+               // Do the local update and arbitrate
+               Pair<Boolean, List<Commit>> returnData = doLocalUpdateAndArbitrate(ut, lastSeenCommit);
+               mutex.release();
+
+
+               // Calculate the size of the response
+               int size = Byte.BYTES + Integer.BYTES;
+               for (Commit com : returnData.getSecond()) {
+                       size += com.getSize();
+               }
+
+               // encode the response
+               byte[] array = new byte[size];
+               ByteBuffer bbEncode = ByteBuffer.wrap(array);
+               if (returnData.getFirst()) {
+                       bbEncode.put((byte)1);
+               } else {
+                       bbEncode.put((byte)0);
+               }
+               bbEncode.putInt(returnData.getSecond().size());
+
+               for (Commit com : returnData.getSecond()) {
+                       com.encode(bbEncode);
+               }
+
+               return bbEncode.array();
+       }
+
+       private Pair<Boolean, List<Commit>> doLocalUpdateAndArbitrate(Transaction ut, Long lastCommitSeen) {
+
+               List<Commit> returnCommits = new ArrayList<Commit>();
+
+               if ((lastCommitSeenSeqNumMap.get(localmachineid) != null) && (lastCommitSeenSeqNumMap.get(localmachineid) > lastCommitSeen)) {
+                       // There is a commit that the other client has not seen yet
+
+                       Map<Long, Commit> cm = commitMap.get(localmachineid);
+                       if (cm != null) {
+
+                               List<Long> commitKeys = new ArrayList<Long>(cm.keySet());
+                               Collections.sort(commitKeys);
+
+
+                               for (int i = (commitKeys.size() - 1); i >= 0; i--) {
+                                       Commit com = cm.get(commitKeys.get(i));
+
+                                       if (com.getSequenceNumber() <= lastCommitSeen) {
+                                               break;
+                                       }
+                                       returnCommits.add((Commit)com.getCopy(null));
+                               }
+                       }
+               }
+
+
+               if ((ut == null) || (ut.getArbitrator() != localmachineid)) {
+                       // We are not the arbitrator for that transaction so the other device is talking to the wrong arbitrator
+                       // or there is no transaction to process
+                       return new Pair<Boolean, List<Commit>>(false, returnCommits);
+               }
+
+               if (!ut.evaluateGuard(commitedTable, null)) {
+                       // Guard evaluated as false so return only the commits that the other device has not seen yet
+                       return new Pair<Boolean, List<Commit>>(false, returnCommits);
+               }
+
+               // create the commit
+               Commit commit = new Commit(null,
+                                          -1,
+                                          commitSequenceNumber,
+                                          ut.getArbitrator(),
+                                          ut.getkeyValueUpdateSet());
+               commitSequenceNumber = commitSequenceNumber + 1;
+
+               // Add to the pending commits list
+               pendingCommitsList.add(commit);
+
+               // Add this commit so we can send it back
+               returnCommits.add(commit);
+
+               // Prepare to process the commit
+               processEntry(commit);
+
+               boolean didCommitOrSpeculate = proccessAllNewCommits();
+
+               // Go through all uncommitted transactions and kill the ones that are dead
+               deleteDeadUncommittedTransactions();
+
+               // Speculate on key value pairs
+               didCommitOrSpeculate |= createSpeculativeTable();
+               createPendingTransactionSpeculativeTable(didCommitOrSpeculate);
+
+               return new Pair<Boolean, List<Commit>>(true, returnCommits);
+       }
+
+       public void decrementLiveCount() {
+               liveslotcount--;
+       }
+
+       private void setResizeThreshold() {
+               int resize_lower = (int) (RESIZE_THRESHOLD * numslots);
+               resizethreshold = resize_lower - 1 + random.nextInt(numslots - resize_lower);
+       }
+
+       private boolean tryput(PendingTransaction pendingTrans, boolean resize) throws ServerException {
+               Slot s = new Slot(this, sequencenumber + 1, localmachineid, buffer.getSlot(sequencenumber).getHMAC());
+
+               int newsize = 0;
+               if (liveslotcount > resizethreshold) {
+                       resize = true; //Resize is forced
+               }
+
+               if (resize) {
+                       newsize = (int) (numslots * RESIZE_MULTIPLE);
+                       TableStatus status = new TableStatus(s, newsize);
+                       s.addEntry(status);
+               }
+
+               doRejectedMessages(s);
+
+               ThreeTuple<Boolean, Boolean, Long> retTup = doMandatoryResuce(s, resize);
+
+               // Resize was needed so redo call
+               if (retTup.getFirst()) {
+                       return tryput(pendingTrans, true);
+               }
+
+               // Extract working variables
+               boolean seenliveslot = retTup.getSecond();
+               long seqn = retTup.getThird();
+
+               doArbitration(s);
+
+               Transaction trans = new Transaction(s,
+                                                   s.getSequenceNumber(),
+                                                   localmachineid,
+                                                   pendingTrans.getArbitrator(),
+                                                   pendingTrans.getKVUpdates(),
+                                                   pendingTrans.getKVGuard());
+               boolean insertedTrans = false;
+               if (s.hasSpace(trans)) {
+                       s.addEntry(trans);
+                       insertedTrans = true;
+               }
+
+               doOptionalRescue(s, seenliveslot, seqn, resize);
+               Pair<Boolean, Slot[]> sendRetData = doSendSlots(s, insertedTrans, resize, newsize);
+
+               if (sendRetData.getFirst()) {
+                       // update the status and change what the sequence number is for the
+                       TransactionStatus transStatus = transactionStatusNotSentMap.remove(pendingTrans.getMachineLocalTransSeqNum());
+                       transStatus.setStatus(TransactionStatus.StatusSent);
+                       transStatus.setSentTransaction();
+                       transactionStatusMap.put(trans.getSequenceNumber(), transStatus);
+               }
+
+
+               if (sendRetData.getSecond().length != 0) {
+                       // insert into the local block chain
+                       validateandupdate(sendRetData.getSecond(), true);
+               }
+
+               return sendRetData.getFirst();
+       }
+
+       private boolean tryput(IoTString keyName, long arbMachineid, boolean resize) throws ServerException {
+               Slot s = new Slot(this, sequencenumber + 1, localmachineid, buffer.getSlot(sequencenumber).getHMAC());
+               int newsize = 0;
+               if (liveslotcount > resizethreshold) {
+                       resize = true; //Resize is forced
+               }
+
+               if (resize) {
+                       newsize = (int) (numslots * RESIZE_MULTIPLE);
+                       TableStatus status = new TableStatus(s, newsize);
+                       s.addEntry(status);
+               }
+
+               doRejectedMessages(s);
+               ThreeTuple<Boolean, Boolean, Long> retTup = doMandatoryResuce(s, resize);
+
+               // Resize was needed so redo call
+               if (retTup.getFirst()) {
+                       return tryput(keyName, arbMachineid, true);
+               }
+
+               // Extract working variables
+               boolean seenliveslot = retTup.getSecond();
+               long seqn = retTup.getThird();
+
+               doArbitration(s);
+
+               NewKey newKey = new NewKey(s, keyName, arbMachineid);
+
+               boolean insertedNewKey = false;
+               if (s.hasSpace(newKey)) {
+                       s.addEntry(newKey);
+                       insertedNewKey = true;
+               }
+
+               doOptionalRescue(s, seenliveslot, seqn, resize);
+               Pair<Boolean, Slot[]> sendRetData = doSendSlots(s, insertedNewKey, resize, newsize);
+
+               if (sendRetData.getSecond().length != 0) {
+                       // insert into the local block chain
+                       validateandupdate(sendRetData.getSecond(), true);
+               }
+
+               return sendRetData.getFirst();
+       }
+
+       private void doRejectedMessages(Slot s) {
+               if (! rejectedmessagelist.isEmpty()) {
+                       /* TODO: We should avoid generating a rejected message entry if
+                        * there is already a sufficient entry in the queue (e.g.,
+                        * equalsto value of true and same sequence number).  */
+
+                       long old_seqn = rejectedmessagelist.firstElement();
+                       if (rejectedmessagelist.size() > REJECTED_THRESHOLD) {
+                               long new_seqn = rejectedmessagelist.lastElement();
+                               RejectedMessage rm = new RejectedMessage(s, localmachineid, old_seqn, new_seqn, false);
+                               s.addEntry(rm);
+                       } else {
+                               long prev_seqn = -1;
+                               int i = 0;
+                               /* Go through list of missing messages */
+                               for (; i < rejectedmessagelist.size(); i++) {
+                                       long curr_seqn = rejectedmessagelist.get(i);
+                                       Slot s_msg = buffer.getSlot(curr_seqn);
+                                       if (s_msg != null)
+                                               break;
+                                       prev_seqn = curr_seqn;
+                               }
+                               /* Generate rejected message entry for missing messages */
+                               if (prev_seqn != -1) {
+                                       RejectedMessage rm = new RejectedMessage(s, localmachineid, old_seqn, prev_seqn, false);
+                                       s.addEntry(rm);
+                               }
+                               /* Generate rejected message entries for present messages */
+                               for (; i < rejectedmessagelist.size(); i++) {
+                                       long curr_seqn = rejectedmessagelist.get(i);
+                                       Slot s_msg = buffer.getSlot(curr_seqn);
+                                       long machineid = s_msg.getMachineID();
+                                       RejectedMessage rm = new RejectedMessage(s, machineid, curr_seqn, curr_seqn, true);
+                                       s.addEntry(rm);
+                               }
+                       }
+               }
+       }
+
+       private ThreeTuple<Boolean, Boolean, Long> doMandatoryResuce(Slot s, boolean resize) {
+               long newestseqnum = buffer.getNewestSeqNum();
+               long oldestseqnum = buffer.getOldestSeqNum();
+               if (lastliveslotseqn < oldestseqnum)
+                       lastliveslotseqn = oldestseqnum;
+
+               long seqn = lastliveslotseqn;
+               boolean seenliveslot = false;
+               long firstiffull = newestseqnum + 1 - numslots; // smallest seq number in the buffer if it is full
+               long threshold = firstiffull + FREE_SLOTS;      // we want the buffer to be clear of live entries up to this point
+
+
+               // Mandatory Rescue
+               for (; seqn < threshold; seqn++) {
+                       Slot prevslot = buffer.getSlot(seqn);
+                       // Push slot number forward
+                       if (! seenliveslot)
+                               lastliveslotseqn = seqn;
+
+                       if (! prevslot.isLive())
+                               continue;
+                       seenliveslot = true;
+                       Vector<Entry> liveentries = prevslot.getLiveEntries(resize);
+                       for (Entry liveentry : liveentries) {
+                               if (s.hasSpace(liveentry)) {
+                                       s.addEntry(liveentry);
+                               } else if (seqn == firstiffull) { //if there's no space but the entry is about to fall off the queue
+                                       if (!resize) {
+                                               System.out.println("B"); //?
+                                               return new ThreeTuple<Boolean, Boolean, Long>(true, seenliveslot, seqn);
+                                       }
+                               }
+                       }
+               }
+
+               // Did not resize
+               return new ThreeTuple<Boolean, Boolean, Long>(false, seenliveslot, seqn);
+       }
+
+       private boolean doArbitration(Slot s) {
+
+               // flag whether we have finished all arbitration
+               boolean stillHasArbitration = false;
+
+               pendingCommitsToDelete.clear();
+
+               // First add queue commits
+               for (Commit commit : pendingCommitsList) {
+                       if (s.hasSpace(commit)) {
+                               s.addEntry(commit);
+                               pendingCommitsToDelete.add(commit);
+                       } else {
+                               // Ran out of space so move on but still not done
+                               stillHasArbitration = true;
+                               return stillHasArbitration;
+                       }
+               }
+
+               // Arbitrate
+               Map<IoTString, KeyValue> speculativeTableTmp = new HashMap<IoTString, KeyValue>();
+               List<Long> transSeqNums = new ArrayList<Long>(uncommittedTransactionsMap.keySet());
+
+               // Sort from oldest to newest
+               Collections.sort(transSeqNums);
+
+               for (Long transNum : transSeqNums) {
+                       Transaction ut = uncommittedTransactionsMap.get(transNum);
+
+                       // Check if this machine arbitrates for this transaction
+                       if (ut.getArbitrator() != localmachineid ) {
+                               continue;
+                       }
+
+                       // we did have something to arbitrate on
+                       stillHasArbitration = true;
+
+                       Entry newEntry = null;
+
+                       if (ut.evaluateGuard(commitedTable, speculativeTableTmp)) {
+                               // Guard evaluated as true
+
+                               // update the local tmp current key set
+                               for (KeyValue kv : ut.getkeyValueUpdateSet()) {
+                                       speculativeTableTmp.put(kv.getKey(), kv);
+                               }
+
+                               // create the commit
+                               newEntry = new Commit(s,
+                                                     ut.getSequenceNumber(),
+                                                     commitSequenceNumber,
+                                                     ut.getArbitrator(),
+                                                     ut.getkeyValueUpdateSet());
+                               commitSequenceNumber = commitSequenceNumber + 1;
+                       } else {
+                               // Guard was false
+
+                               // create the abort
+                               newEntry = new Abort(s,
+                                                    ut.getSequenceNumber(),
+                                                    ut.getMachineID(),
+                                                    ut.getArbitrator());
+                       }
+
+                       if ((newEntry != null) && s.hasSpace(newEntry)) {
+                               s.addEntry(newEntry);
+                       } else {
+                               break;
+                       }
+               }
+
+               return stillHasArbitration;
+       }
+
+       private void deletePendingCommits() {
+               for (Commit com : pendingCommitsToDelete) {
+                       pendingCommitsList.remove(com);
+               }
+               pendingCommitsToDelete.clear();
+       }
+
+       private void  doOptionalRescue(Slot s, boolean seenliveslot, long seqn, boolean resize) {
+               /* now go through live entries from least to greatest sequence number until
+                * either all live slots added, or the slot doesn't have enough room
+                * for SKIP_THRESHOLD consecutive entries*/
+               int skipcount = 0;
+               long newestseqnum = buffer.getNewestSeqNum();
+               search:
+               for (; seqn <= newestseqnum; seqn++) {
+                       Slot prevslot = buffer.getSlot(seqn);
+                       //Push slot number forward
+                       if (!seenliveslot)
+                               lastliveslotseqn = seqn;
+
+                       if (!prevslot.isLive())
+                               continue;
+                       seenliveslot = true;
+                       Vector<Entry> liveentries = prevslot.getLiveEntries(resize);
+                       for (Entry liveentry : liveentries) {
+                               if (s.hasSpace(liveentry))
+                                       s.addEntry(liveentry);
+                               else {
+                                       skipcount++;
+                                       if (skipcount > SKIP_THRESHOLD)
+                                               break search;
+                               }
+                       }
+               }
+       }
+
+       private Pair<Boolean, Slot[]> doSendSlots(Slot s, boolean inserted, boolean resize, int newsize)  throws ServerException {
+               int max = 0;
+               if (resize)
+                       max = newsize;
+
+               Slot[] array = cloud.putSlot(s, max);
+               if (array == null) {
+                       array = new Slot[] {s};
+                       rejectedmessagelist.clear();
+
+                       // Delete pending commits that were sent to the cloud
+                       deletePendingCommits();
+               }       else {
+                       // if (array.length == 0)
+                       // throw new Error("Server Error: Did not send any slots");
+                       rejectedmessagelist.add(s.getSequenceNumber());
+                       inserted = false;
+               }
+
+               return new Pair<Boolean, Slot[]>(inserted, array);
+       }
+
+       private void validateandupdate(Slot[] newslots, boolean acceptupdatestolocal) {
+               /* The cloud communication layer has checked slot HMACs already
+                        before decoding */
+               if (newslots.length == 0) return;
+
+               // Reset the table status declared sizes
+               smallestTableStatusSeen = -1;
+               largestTableStatusSeen = -1;
+
+               long firstseqnum = newslots[0].getSequenceNumber();
+               if (firstseqnum <= sequencenumber) {
+                       throw new Error("Server Error: Sent older slots!");
+               }
+
+               SlotIndexer indexer = new SlotIndexer(newslots, buffer);
+               checkHMACChain(indexer, newslots);
+
+               HashSet<Long> machineSet = new HashSet<Long>(lastmessagetable.keySet()); //
+
+               // initExpectedSize(firstseqnum);
+               for (Slot slot : newslots) {
+                       processSlot(indexer, slot, acceptupdatestolocal, machineSet);
+                       // updateExpectedSize();
+               }
+
+               /* If there is a gap, check to see if the server sent us everything. */
+               if (firstseqnum != (sequencenumber + 1)) {
+
+                       // TODO: Check size
+                       checkNumSlots(newslots.length);
+                       if (!machineSet.isEmpty()) {
+                               throw new Error("Missing record for machines: " + machineSet);
+                       }
+               }
+
+
+               commitNewMaxSize();
+
+               /* Commit new to slots. */
+               for (Slot slot : newslots) {
+                       buffer.putSlot(slot);
+                       liveslotcount++;
+               }
+               sequencenumber = newslots[newslots.length - 1].getSequenceNumber();
+
+               // Process all on key value pairs
+               boolean didCommitOrSpeculate = proccessAllNewCommits();
+
+               // Go through all uncommitted transactions and kill the ones that are dead
+               deleteDeadUncommittedTransactions();
+
+               // Speculate on key value pairs
+               didCommitOrSpeculate |= createSpeculativeTable();
+
+               createPendingTransactionSpeculativeTable(didCommitOrSpeculate);
+       }
+
+       private boolean proccessAllNewCommits() {
+               // Process only if there are commit
+               if (newCommitMap.keySet().size() == 0) {
+                       return false;
+               }
+               boolean didProcessNewCommit = false;
+
+               for (Long arb : newCommitMap.keySet()) {
+
+                       List<Long> commitSeqNums = new ArrayList<Long>(newCommitMap.get(arb).keySet());
+
+                       // Sort from oldest to newest commit
+                       Collections.sort(commitSeqNums);
+
+                       // Go through each new commit one by one
+                       for (Long entrySeqNum : commitSeqNums) {
+                               Commit entry = newCommitMap.get(arb).get(entrySeqNum);
+
+                               long lastCommitSeenSeqNum = -1;
+                               if (lastCommitSeenSeqNumMap.get(entry.getTransArbitrator()) != null) {
+                                       lastCommitSeenSeqNum = lastCommitSeenSeqNumMap.get(entry.getTransArbitrator());
+                               }
+
+                               if (entry.getSequenceNumber() <= lastCommitSeenSeqNum) {
+                                       Map<Long, Commit> cm = commitMap.get(arb);
+                                       if (cm == null) {
+                                               cm = new HashMap<Long, Commit>();
+                                       }
+
+                                       Commit prevCommit = cm.put(entry.getSequenceNumber(), entry);
+                                       commitMap.put(arb, cm);
+
+                                       if (prevCommit != null) {
+                                               prevCommit.setDead();
+
+                                               for (KeyValue kv : prevCommit.getkeyValueUpdateSet()) {
+                                                       committedMapByKey.put(kv.getKey(), entry);
+                                               }
+                                       }
+
+                                       continue;
+                               }
+
+                               Set<Commit> commitsToEditSet = new HashSet<Commit>();
+
+                               for (KeyValue kv : entry.getkeyValueUpdateSet()) {
+                                       commitsToEditSet.add(committedMapByKey.get(kv.getKey()));
+                               }
+
+                               commitsToEditSet.remove(null);
+
+                               for (Commit prevCommit : commitsToEditSet) {
+
+                                       Set<KeyValue> deletedKV = prevCommit.updateLiveKeys(entry.getkeyValueUpdateSet());
+
+                                       if (!prevCommit.isLive()) {
+                                               Map<Long, Commit> cm = commitMap.get(arb);
+
+                                               // remove it from the map so that it can be set as dead
+                                               if (cm != null) {
+                                                       cm.remove(prevCommit.getSequenceNumber());
+                                                       commitMap.put(arb, cm);
+                                               }
+                                       }
+                               }
+
+                               // Add the new commit
+                               Map<Long, Commit> cm = commitMap.get(arb);
+                               if (cm == null) {
+                                       cm = new HashMap<Long, Commit>();
+                               }
+                               cm.put(entry.getSequenceNumber(), entry);
+                               commitMap.put(arb, cm);
+
+                               lastCommitSeenSeqNumMap.put(entry.getTransArbitrator(), entry.getSequenceNumber());
+
+                               // set the trans sequence number if we are able to
+                               if (entry.getTransSequenceNumber() != -1) {
+                                       lastCommitSeenTransSeqNumMap.put(entry.getTransArbitrator(), entry.getTransSequenceNumber());
+                               }
+
+                               didProcessNewCommit = true;
+
+                               // Update the committed table list
+                               for (KeyValue kv : entry.getkeyValueUpdateSet()) {
+                                       IoTString key = kv.getKey();
+                                       commitedTable.put(key, kv);
+                                       committedMapByKey.put(key, entry);
+                               }
+                       }
+               }
+               // Clear the new commits storage so we can use it later
+               newCommitMap.clear();
+
+
+               // go through all saved transactions and update the status of those that can be updated
+               for (Iterator<Map.Entry<Long, TransactionStatus>> i = transactionStatusMap.entrySet().iterator(); i.hasNext();) {
+                       Map.Entry<Long, TransactionStatus> entry = i.next();
+                       long seqnum = entry.getKey();
+                       TransactionStatus status = entry.getValue();
+
+                       if (status.getSentTransaction()) {
+
+                               Long commitSeqNum = lastCommitSeenTransSeqNumMap.get(status.getArbitrator());
+                               Long abortSeqNum = lastAbortSeenSeqNumMap.get(status.getArbitrator());
+
+                               if (((commitSeqNum != null) && (seqnum <= commitSeqNum)) ||
+                                       ((abortSeqNum != null) && (seqnum <= abortSeqNum))) {
+                                       status.setStatus(TransactionStatus.StatusCommitted);
+                                       i.remove();
+                               }
+                       }
+               }
+
+               return didProcessNewCommit;
+       }
+
+       private void deleteDeadUncommittedTransactions() {
+               // Make dead the transactions
+               for (Iterator<Map.Entry<Long, Transaction>> i = uncommittedTransactionsMap.entrySet().iterator(); i.hasNext();) {
+                       Transaction prevtrans = i.next().getValue();
+                       long transArb = prevtrans.getArbitrator();
+
+                       Long commitSeqNum = lastCommitSeenTransSeqNumMap.get(transArb);
+                       Long abortSeqNum = lastAbortSeenSeqNumMap.get(transArb);
+
+                       if (((commitSeqNum != null) && (prevtrans.getSequenceNumber() <= commitSeqNum)) ||
+                               ((abortSeqNum != null) && (prevtrans.getSequenceNumber() <= abortSeqNum))) {
+                               i.remove();
+                               prevtrans.setDead();
+                       }
+               }
+       }
+
+       private boolean createSpeculativeTable() {
+               if (uncommittedTransactionsMap.keySet().size() == 0) {
+                       return false;
+               }
+
+               Map<IoTString, KeyValue> speculativeTableTmp = new HashMap<IoTString, KeyValue>();
+               List<Long> utSeqNums = new ArrayList<Long>(uncommittedTransactionsMap.keySet());
+
+               // Sort from oldest to newest commit
+               Collections.sort(utSeqNums);
+
+               if (utSeqNums.get(0) > (lastUncommittedTransaction)) {
+
+                       speculativeTable.clear();
+                       lastUncommittedTransaction = -1;
+
+                       for (Long key : utSeqNums) {
+                               Transaction trans = uncommittedTransactionsMap.get(key);
+
+                               lastUncommittedTransaction = key;
+
+                               if (trans.evaluateGuard(commitedTable, speculativeTableTmp)) {
+                                       for (KeyValue kv : trans.getkeyValueUpdateSet()) {
+                                               speculativeTableTmp.put(kv.getKey(), kv);
+                                       }
+                               }
+
+                       }
+               } else {
+                       for (Long key : utSeqNums) {
+
+                               if (key <= lastUncommittedTransaction) {
+                                       continue;
+                               }
+
+                               lastUncommittedTransaction = key;
+
+                               Transaction trans = uncommittedTransactionsMap.get(key);
+
+                               if (trans.evaluateGuard(speculativeTable, speculativeTableTmp)) {
+                                       for (KeyValue kv : trans.getkeyValueUpdateSet()) {
+                                               speculativeTableTmp.put(kv.getKey(), kv);
+                                       }
+                               }
+                       }
+               }
+
+               for (IoTString key : speculativeTableTmp.keySet()) {
+                       speculativeTable.put(key, speculativeTableTmp.get(key));
+               }
+
+               return true;
+       }
+
+       private void createPendingTransactionSpeculativeTable(boolean didCommitOrSpeculate) {
+
+               if (didCommitOrSpeculate) {
+                       pendingTransSpeculativeTable.clear();
+                       lastSeenPendingTransactionSpeculateIndex = 0;
+
+                       int index = 0;
+                       for (PendingTransaction pt : pendingTransQueue) {
+                               if (pt.evaluateGuard(commitedTable, speculativeTable, pendingTransSpeculativeTable)) {
+
+                                       lastSeenPendingTransactionSpeculateIndex = index;
+                                       index++;
+
+                                       for (KeyValue kv : pt.getKVUpdates()) {
+                                               pendingTransSpeculativeTable.put(kv.getKey(), kv);
+                                       }
+
+                               }
+                       }
+               }
+       }
+
+       private int expectedsize, currmaxsize;
+
+       private void checkNumSlots(int numslots) {
+
+
+               // We only have 1 size so we must have this many slots
+               if (largestTableStatusSeen == smallestTableStatusSeen) {
+                       if (numslots != smallestTableStatusSeen) {
+                               throw new Error("Server Error: Server did not send all slots.  Expected: " + smallestTableStatusSeen + " Received:" + numslots);
+                       }
+               } else {
+                       // We have more than 1
+                       if (numslots < smallestTableStatusSeen) {
+                               throw new Error("Server Error: Server did not send all slots.  Expected at least: " + smallestTableStatusSeen + " Received:" + numslots);
+                       }
+               }
+
+               // if (numslots != expectedsize) {
+               // throw new Error("Server Error: Server did not send all slots.  Expected: " + expectedsize + " Received:" + numslots);
+               // }
+       }
+
+       private void initExpectedSize(long firstsequencenumber) {
+               long prevslots = firstsequencenumber;
+               expectedsize = (prevslots < ((long) numslots)) ? (int) prevslots : numslots;
+               currmaxsize = numslots;
+       }
+
+       private void updateExpectedSize() {
+               expectedsize++;
+               if (expectedsize > currmaxsize) {
+                       expectedsize = currmaxsize;
+               }
+       }
+
+       private void updateCurrMaxSize(int newmaxsize) {
+               currmaxsize = newmaxsize;
+       }
+
+       private void commitNewMaxSize() {
+
+               if (largestTableStatusSeen == -1) {
+                       currmaxsize = numslots;
+               } else {
+                       currmaxsize = largestTableStatusSeen;
+               }
+
+               if (numslots != currmaxsize) {
+                       buffer.resize(currmaxsize);
+               }
+
+               numslots = currmaxsize;
+               setResizeThreshold();
+       }
+
+       private void processEntry(LastMessage entry, HashSet<Long> machineSet) {
+               updateLastMessage(entry.getMachineID(), entry.getSequenceNumber(), entry, false, machineSet);
+       }
+
+       private void processEntry(RejectedMessage entry, SlotIndexer indexer) {
+               long oldseqnum = entry.getOldSeqNum();
+               long newseqnum = entry.getNewSeqNum();
+               boolean isequal = entry.getEqual();
+               long machineid = entry.getMachineID();
+               for (long seqnum = oldseqnum; seqnum <= newseqnum; seqnum++) {
+                       Slot slot = indexer.getSlot(seqnum);
+                       if (slot != null) {
+                               long slotmachineid = slot.getMachineID();
+                               if (isequal != (slotmachineid == machineid)) {
+                                       throw new Error("Server Error: Trying to insert rejected message for slot " + seqnum);
+                               }
+                       }
+               }
+
+               HashSet<Long> watchset = new HashSet<Long>();
+               for (Map.Entry<Long, Pair<Long, Liveness> > lastmsg_entry : lastmessagetable.entrySet()) {
+                       long entry_mid = lastmsg_entry.getKey();
+                       /* We've seen it, don't need to continue to watch.  Our next
+                        * message will implicitly acknowledge it. */
+                       if (entry_mid == localmachineid)
+                               continue;
+                       Pair<Long, Liveness> v = lastmsg_entry.getValue();
+                       long entry_seqn = v.getFirst();
+                       if (entry_seqn < newseqnum) {
+                               addWatchList(entry_mid, entry);
+                               watchset.add(entry_mid);
+                       }
+               }
+               if (watchset.isEmpty())
+                       entry.setDead();
+               else
+                       entry.setWatchSet(watchset);
+       }
+
+       private void processEntry(NewKey entry) {
+               arbitratorTable.put(entry.getKey(), entry.getMachineID());
+
+               NewKey oldNewKey = newKeyTable.put(entry.getKey(), entry);
+
+               if (oldNewKey != null) {
+                       oldNewKey.setDead();
+               }
+       }
+
+       private void processEntry(Transaction entry) {
+
+               long arb = entry.getArbitrator();
+               Long comLast = lastCommitSeenTransSeqNumMap.get(arb);
+               Long abLast = lastAbortSeenSeqNumMap.get(arb);
+
+               Transaction prevTrans = null;
+
+               if ((comLast != null) && (comLast >= entry.getSequenceNumber())) {
+                       prevTrans = uncommittedTransactionsMap.remove(entry.getSequenceNumber());
+               } else if ((abLast != null) && (abLast >= entry.getSequenceNumber())) {
+                       prevTrans = uncommittedTransactionsMap.remove(entry.getSequenceNumber());
+               } else {
+                       prevTrans = uncommittedTransactionsMap.put(entry.getSequenceNumber(), entry);
+               }
+
+               // Duplicate so delete old copy
+               if (prevTrans != null) {
+                       prevTrans.setDead();
+               }
+       }
+
+       private void processEntry(Abort entry) {
+               if (lastmessagetable.get(entry.getMachineID()).getFirst() < entry.getTransSequenceNumber()) {
+                       // Abort has not been seen yet so we need to keep track of it
+
+                       Abort prevAbort = abortMap.put(entry.getTransSequenceNumber(), entry);
+                       if (prevAbort != null) {
+                               prevAbort.setDead(); // delete old version of the duplicate
+                       }
+
+                       if ((lastAbortSeenSeqNumMap.get(entry.getTransArbitrator()) != null) &&   (entry.getTransSequenceNumber() > lastAbortSeenSeqNumMap.get(entry.getTransArbitrator()))) {
+                               lastAbortSeenSeqNumMap.put(entry.getTransArbitrator(), entry.getTransSequenceNumber());
+                       }
+               } else {
+                       // The machine already saw this so it is dead
+                       entry.setDead();
+               }
+
+               // Update the status of the transaction and remove it since we are done with this transaction
+               TransactionStatus status = transactionStatusMap.remove(entry.getTransSequenceNumber());
+               if (status != null) {
+                       status.setStatus(TransactionStatus.StatusAborted);
+               }
+       }
+
+       private void processEntry(Commit entry) {
+               Map<Long, Commit> arbMap = newCommitMap.get(entry.getTransArbitrator());
+
+               if (arbMap == null) {
+                       arbMap = new HashMap<Long, Commit>();
+               }
+
+               Commit prevCommit = arbMap.put(entry.getSequenceNumber(), entry);
+               newCommitMap.put(entry.getTransArbitrator(), arbMap);
+
+               if (prevCommit != null) {
+                       prevCommit.setDead();
+               }
+       }
+
+       private void processEntry(TableStatus entry) {
+               int newnumslots = entry.getMaxSlots();
+               // updateCurrMaxSize(newnumslots);
+               if (lastTableStatus != null)
+                       lastTableStatus.setDead();
+               lastTableStatus = entry;
+
+               if ((smallestTableStatusSeen == -1) || (newnumslots < smallestTableStatusSeen)) {
+                       smallestTableStatusSeen = newnumslots;
+               }
+
+               if ((largestTableStatusSeen == -1) || (newnumslots > largestTableStatusSeen)) {
+                       largestTableStatusSeen = newnumslots;
+               }
+       }
+
+       private void addWatchList(long machineid, RejectedMessage entry) {
+               HashSet<RejectedMessage> entries = watchlist.get(machineid);
+               if (entries == null)
+                       watchlist.put(machineid, entries = new HashSet<RejectedMessage>());
+               entries.add(entry);
+       }
+
+       private void updateLastMessage(long machineid, long seqnum, Liveness liveness, boolean acceptupdatestolocal, HashSet<Long> machineSet) {
+               machineSet.remove(machineid);
+
+               HashSet<RejectedMessage> watchset = watchlist.get(machineid);
+               if (watchset != null) {
+                       for (Iterator<RejectedMessage> rmit = watchset.iterator(); rmit.hasNext(); ) {
+                               RejectedMessage rm = rmit.next();
+                               if (rm.getNewSeqNum() <= seqnum) {
+                                       /* Remove it from our watchlist */
+                                       rmit.remove();
+                                       /* Decrement machines that need to see this notification */
+                                       rm.removeWatcher(machineid);
+                               }
+                       }
+               }
+
+               if (machineid == localmachineid) {
+                       /* Our own messages are immediately dead. */
+                       if (liveness instanceof LastMessage) {
+                               ((LastMessage)liveness).setDead();
+                       } else if (liveness instanceof Slot) {
+                               ((Slot)liveness).setDead();
+                       } else {
+                               throw new Error("Unrecognized type");
+                       }
+               }
+
+               // Set dead the abort
+               for (Iterator<Map.Entry<Long, Abort>> i = abortMap.entrySet().iterator(); i.hasNext();) {
+                       Abort abort = i.next().getValue();
+
+                       if ((abort.getMachineID() == machineid) && (abort.getTransSequenceNumber() <= seqnum)) {
+                               abort.setDead();
+                               i.remove();
+                       }
+               }
+
+               Pair<Long, Liveness> lastmsgentry = lastmessagetable.put(machineid, new Pair<Long, Liveness>(seqnum, liveness));
+               if (lastmsgentry == null)
+                       return;
+
+               long lastmsgseqnum = lastmsgentry.getFirst();
+               Liveness lastentry = lastmsgentry.getSecond();
+               if (machineid != localmachineid) {
+                       if (lastentry instanceof LastMessage) {
+                               ((LastMessage)lastentry).setDead();
+                       } else if (lastentry instanceof Slot) {
+                               ((Slot)lastentry).setDead();
+                       } else {
+                               throw new Error("Unrecognized type");
+                       }
+               }
+
+               if (machineid == localmachineid) {
+                       if (lastmsgseqnum != seqnum && !acceptupdatestolocal)
+                               throw new Error("Server Error: Mismatch on local machine sequence number, needed: " +  seqnum + " got: " + lastmsgseqnum);
+               } else {
+                       if (lastmsgseqnum > seqnum)
+                               throw new Error("Server Error: Rollback on remote machine sequence number");
+               }
+       }
+
+       private void processSlot(SlotIndexer indexer, Slot slot, boolean acceptupdatestolocal, HashSet<Long> machineSet) {
+               updateLastMessage(slot.getMachineID(), slot.getSequenceNumber(), slot, acceptupdatestolocal, machineSet);
+               for (Entry entry : slot.getEntries()) {
+                       switch (entry.getType()) {
+
+                       case Entry.TypeNewKey:
+                               processEntry((NewKey)entry);
+                               break;
+
+                       case Entry.TypeCommit:
+                               processEntry((Commit)entry);
+                               break;
+
+                       case Entry.TypeAbort:
+                               processEntry((Abort)entry);
+                               break;
+
+                       case Entry.TypeTransaction:
+                               processEntry((Transaction)entry);
+                               break;
+
+                       case Entry.TypeLastMessage:
+                               processEntry((LastMessage)entry, machineSet);
+                               break;
+
+                       case Entry.TypeRejectedMessage:
+                               processEntry((RejectedMessage)entry, indexer);
+                               break;
+
+                       case Entry.TypeTableStatus:
+                               processEntry((TableStatus)entry);
+                               break;
+
+                       default:
+                               throw new Error("Unrecognized type: " + entry.getType());
+                       }
+               }
+       }
+
+       private void checkHMACChain(SlotIndexer indexer, Slot[] newslots) {
+               for (int i = 0; i < newslots.length; i++) {
+                       Slot currslot = newslots[i];
+                       Slot prevslot = indexer.getSlot(currslot.getSequenceNumber() - 1);
+                       if (prevslot != null &&
+                               !Arrays.equals(prevslot.getHMAC(), currslot.getPrevHMAC()))
+                               throw new Error("Server Error: Invalid HMAC Chain" + currslot + " " + prevslot);
+               }
+       }
+}
\ No newline at end of file
diff --git a/version2/backup/src/java/iotcloud/TableStatus.java b/version2/backup/src/java/iotcloud/TableStatus.java
new file mode 100644 (file)
index 0000000..62f3a6d
--- /dev/null
@@ -0,0 +1,45 @@
+package iotcloud;
+import java.nio.ByteBuffer;
+
+/**
+ * TableStatus entries record the current size of the data structure
+ * in slots.  Used to remember the size and to perform resizes.
+ * @author Brian Demsky
+ * @version 1.0
+ */
+
+
+class TableStatus extends Entry {
+       private int maxslots;
+
+       TableStatus(Slot slot, int _maxslots) {
+               super(slot);
+               maxslots=_maxslots;
+       }
+
+       int getMaxSlots() {
+               return maxslots;
+       }
+
+       static Entry decode(Slot slot, ByteBuffer bb) {
+               int maxslots=bb.getInt();
+               return new TableStatus(slot, maxslots);
+       }
+
+       void encode(ByteBuffer bb) {
+               bb.put(Entry.TypeTableStatus);
+               bb.putInt(maxslots);
+       }
+
+       int getSize() {
+               return Integer.BYTES+Byte.BYTES;
+       }
+
+       byte getType() {
+               return Entry.TypeTableStatus;
+       }
+
+       Entry getCopy(Slot s) {
+               return new TableStatus(s, maxslots);
+       }
+}
diff --git a/version2/backup/src/java/iotcloud/Test.java b/version2/backup/src/java/iotcloud/Test.java
new file mode 100644 (file)
index 0000000..0de2e5c
--- /dev/null
@@ -0,0 +1,1878 @@
+package iotcloud;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Test cases.
+ * @author Brian Demsky
+ * @version 1.0
+ */
+
+public class Test {
+
+       public static final  int NUMBER_OF_TESTS = 100;
+
+       public static void main(String[] args)  throws ServerException, InterruptedException {
+               if (args[0].equals("2")) {
+                       test2();
+               } else if (args[0].equals("3")) {
+                       test3();
+               } else if (args[0].equals("4")) {
+                       test4();
+               } else if (args[0].equals("5")) {
+                       test5();
+               } else if (args[0].equals("6")) {
+                       test6();
+               } else if (args[0].equals("7")) {
+                       test7();
+               } else if (args[0].equals("8")) {
+                       test8();
+               } else if (args[0].equals("9")) {
+                       test9();
+               } else if (args[0].equals("10")) {
+                       test10();
+               } else if (args[0].equals("11")) {
+                       test11();
+               }
+       }
+
+
+       static void test11() throws InterruptedException {
+
+               boolean foundError = false;
+
+               // Setup the 2 clients
+               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+               while (true) {
+                       try {
+                               t1.initTable();
+                               break;
+                       } catch (Exception e) {}
+               }
+
+               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+               while (t2.update().getFirst() == false) {}
+
+               LocalComm lc = new LocalComm(t1, t2);
+               t1.addLocalComm(t2.getId(), lc);
+               t2.addLocalComm(t1.getId(), lc);
+
+               // Make the Keys
+               System.out.println("Setting up keys");
+               for (int i = 0; i < 4; i++) {
+                       String a = "a" + i;
+                       String b = "b" + i;
+                       String c = "c" + i;
+                       String d = "d" + i;
+                       IoTString ia = new IoTString(a);
+                       IoTString ib = new IoTString(b);
+                       IoTString ic = new IoTString(c);
+                       IoTString id = new IoTString(d);
+                       while (true) {
+                               try {
+                                       t1.createNewKey(ia, 321);
+                                       break;
+                               } catch (Exception e) {}
+                       }
+
+                       while (true) {
+                               try {
+                                       t1.createNewKey(ib, 351);
+                                       break;
+                               } catch (Exception e) {}
+                       }
+
+                       while (true) {
+                               try {
+                                       t2.createNewKey(ic, 321);
+                                       break;
+                               } catch (Exception e) {}
+                       }
+
+                       while (true) {
+                               try {
+                                       t2.createNewKey(id, 351);
+                                       break;
+                               } catch (Exception e) {}
+                       }
+               }
+
+               // Do Updates for the keys
+               System.out.println("Setting Key-Values...");
+               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+                       for (int i = 0; i < 4; i++) {
+                               String keyA = "a" + i;
+                               String valueA = "a" + (i + t);
+
+                               IoTString iKeyA = new IoTString(keyA);
+                               IoTString iValueA = new IoTString(valueA);
+
+                               t1.startTransaction();
+                               t1.addKV(iKeyA, iValueA);
+                               t1.commitTransaction();
+                       }
+               }
+
+               t2.updateFromLocal(321);
+
+               System.out.println("Checking Key-Values...");
+               for (int i = 0; i < 4; i++) {
+
+                       String keyA = "a" + i;
+                       String valueA = "a" + (i + NUMBER_OF_TESTS - 1);
+
+                       IoTString iKeyA = new IoTString(keyA);
+                       IoTString iValueA = new IoTString(valueA);
+
+                       IoTString testValA1 = t1.getCommitted(iKeyA);
+                       IoTString testValA2 = t2.getCommitted(iKeyA);
+
+                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyA + "    " + testValA1 + "    " + iValueA);
+                               foundError = true;
+                       }
+
+                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2 + "    " + iValueA);
+                               foundError = true;
+                       }
+               }
+
+               if (foundError) {
+                       System.out.println("Found Errors...");
+               } else {
+                       System.out.println("No Errors Found...");
+               }
+       }
+
+       static void test10() throws InterruptedException {
+
+               boolean foundError = false;
+
+               // Setup the 2 clients
+               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+               while (true) {
+                       try {
+                               t1.rebuild();
+                               break;
+                       } catch (Exception e) {}
+               }
+
+               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+               while (true) {
+                       try {
+                               t2.rebuild();
+                               break;
+                       } catch (Exception e) {}
+               }
+
+               LocalComm lc = new LocalComm(t1, t2);
+               t1.addLocalComm(t2.getId(), lc);
+               t2.addLocalComm(t1.getId(), lc);
+
+
+               System.out.println("Checking Key-Values...");
+               for (int i = 0; i < 4; i++) {
+
+                       String keyA = "a" + i;
+                       String keyB = "b" + i;
+                       String keyC = "c" + i;
+                       String keyD = "d" + i;
+                       String valueA = "a" + (i + NUMBER_OF_TESTS - 1);
+                       String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
+                       String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
+                       String valueD = "d" + (i + NUMBER_OF_TESTS - 1);
+
+                       IoTString iKeyA = new IoTString(keyA);
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iKeyD = new IoTString(keyD);
+                       IoTString iValueA = new IoTString(valueA);
+                       IoTString iValueB = new IoTString(valueB);
+                       IoTString iValueC = new IoTString(valueC);
+                       IoTString iValueD = new IoTString(valueD);
+
+
+                       IoTString testValA1 = t1.getCommitted(iKeyA);
+                       IoTString testValB1 = t1.getCommitted(iKeyB);
+                       IoTString testValC1 = t1.getCommitted(iKeyC);
+                       IoTString testValD1 = t1.getCommitted(iKeyD);
+
+                       IoTString testValA2 = t2.getCommitted(iKeyA);
+                       IoTString testValB2 = t2.getCommitted(iKeyB);
+                       IoTString testValC2 = t2.getCommitted(iKeyC);
+                       IoTString testValD2 = t2.getCommitted(iKeyD);
+
+                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyA + "    " + testValA1 + "    " + iValueA);
+                               foundError = true;
+                       }
+
+                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1 + "    " + iValueB);
+                               foundError = true;
+                       }
+
+                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyC + "    " + testValC1 + "    " + iValueC);
+                               foundError = true;
+                       }
+
+                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyD + "    " + testValD1 + "    " + iValueD);
+                               foundError = true;
+                       }
+
+                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2 + "    " + iValueA);
+                               foundError = true;
+                       }
+
+                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2 + "    " + iValueB);
+                               foundError = true;
+                       }
+
+                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2 + "    " + iValueC);
+                               foundError = true;
+                       }
+
+                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2 + "    " + iValueD);
+                               foundError = true;
+                       }
+               }
+
+               if (foundError) {
+                       System.out.println("Found Errors...");
+               } else {
+                       System.out.println("No Errors Found...");
+               }
+       }
+
+       static void test9() throws InterruptedException {
+
+               boolean foundError = false;
+               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+               // Setup the 2 clients
+               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+               while (true) {
+                       try {
+                               t1.initTable();
+                               break;
+                       } catch (Exception e) {}
+               }
+
+               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+               while (t2.update().getFirst() == false) {}
+
+               // LocalComm lc = new LocalComm(t1, t2);
+               // t1.addLocalComm(t2.getId(), lc);
+               // t2.addLocalComm(t1.getId(), lc);
+
+
+
+               // Make the Keys
+               System.out.println("Setting up keys");
+               for (int i = 0; i < 4; i++) {
+                       String a = "a" + i;
+                       String b = "b" + i;
+                       String c = "c" + i;
+                       String d = "d" + i;
+                       IoTString ia = new IoTString(a);
+                       IoTString ib = new IoTString(b);
+                       IoTString ic = new IoTString(c);
+                       IoTString id = new IoTString(d);
+                       while (true) {
+                               try {
+                                       t1.createNewKey(ia, 321);
+                                       break;
+                               } catch (Exception e) {}
+                       }
+
+                       while (true) {
+                               try {
+                                       t1.createNewKey(ib, 351);
+                                       break;
+                               } catch (Exception e) {}
+                       }
+
+                       while (true) {
+                               try {
+                                       t2.createNewKey(ic, 321);
+                                       break;
+                               } catch (Exception e) {}
+                       }
+
+                       while (true) {
+                               try {
+                                       t2.createNewKey(id, 351);
+                                       break;
+                               } catch (Exception e) {}
+                       }
+               }
+
+               // Do Updates for the keys
+               System.out.println("Setting Key-Values...");
+
+               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+                       for (int i = 0; i < 4; i++) {
+                               String keyB = "b" + i;
+                               String valueB = "b" + (i + t);
+
+                               IoTString iKeyB = new IoTString(keyB);
+                               IoTString iValueB = new IoTString(valueB);
+
+
+                               t1.startTransaction();
+                               t1.getSpeculativeAtomic(iKeyB);
+                               t1.addKV(iKeyB, iValueB);
+                               transStatusList.add(t1.commitTransaction());
+                       }
+               }
+
+               while (t1.update().getFirst() == false) {}
+
+
+               for (int i = 0; i < 4; i++) {
+
+                       String keyB = "b" + i;
+                       String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iValueB = new IoTString(valueB);
+
+                       IoTString testValB1 = t1.getSpeculative(iKeyB);
+                       IoTString testValB2 = t2.getSpeculative(iKeyB);
+
+                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1);
+                               foundError = true;
+                       }
+
+                       if ((testValB2 != null)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                               foundError = true;
+                       }
+               }
+
+               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+                       for (int i = 0; i < 4; i++) {
+                               String keyC = "c" + i;
+                               String valueC = "c" + (i + t);
+
+                               IoTString iKeyC = new IoTString(keyC);
+                               IoTString iValueC = new IoTString(valueC);
+
+                               t2.startTransaction();
+                               t2.getSpeculativeAtomic(iKeyC);
+                               t2.addKV(iKeyC, iValueC);
+                               transStatusList.add(t2.commitTransaction());
+                       }
+               }
+
+               while (t2.update().getFirst() == false) {}
+
+               for (int i = 0; i < 4; i++) {
+                       String keyC = "c" + i;
+                       String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iValueC = new IoTString(valueC);
+
+                       IoTString testValC1 = t1.getSpeculative(iKeyC);
+                       IoTString testValC2 = t2.getSpeculative(iKeyC);
+
+                       if ((testValC1 != null)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyC + "   " + testValC1);
+                               foundError = true;
+                       }
+
+                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyC + "   " + testValC2);
+                               foundError = true;
+                       }
+               }
+
+               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+                       for (int i = 0; i < 4; i++) {
+                               String keyA = "a" + i;
+                               String keyD = "d" + i;
+                               String valueA = "a" + (i + t);
+                               String valueD = "d" + (i + t);
+
+                               IoTString iKeyA = new IoTString(keyA);
+                               IoTString iKeyD = new IoTString(keyD);
+                               IoTString iValueA = new IoTString(valueA);
+                               IoTString iValueD = new IoTString(valueD);
+
+
+                               t1.startTransaction();
+                               t1.addKV(iKeyA, iValueA);
+                               transStatusList.add(t1.commitTransaction());
+
+                               t2.startTransaction();
+                               t2.addKV(iKeyD, iValueD);
+                               transStatusList.add(t2.commitTransaction());
+                       }
+               }
+
+               System.out.println("Updating Clients...");
+               while (t1.update().getFirst() == false) {}
+               while (t2.update().getFirst() == false) {}
+
+               System.out.println("Checking Key-Values...");
+               for (int i = 0; i < 4; i++) {
+
+                       String keyA = "a" + i;
+                       String keyB = "b" + i;
+                       String keyC = "c" + i;
+                       String keyD = "d" + i;
+                       String valueA = "a" + (i + NUMBER_OF_TESTS - 1);
+                       String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
+                       String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
+                       String valueD = "d" + (i + NUMBER_OF_TESTS - 1);
+
+                       IoTString iKeyA = new IoTString(keyA);
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iKeyD = new IoTString(keyD);
+                       IoTString iValueA = new IoTString(valueA);
+                       IoTString iValueB = new IoTString(valueB);
+                       IoTString iValueC = new IoTString(valueC);
+                       IoTString iValueD = new IoTString(valueD);
+
+
+                       IoTString testValA1 = t1.getCommitted(iKeyA);
+                       IoTString testValB1 = t1.getCommitted(iKeyB);
+                       IoTString testValC1 = t1.getCommitted(iKeyC);
+                       IoTString testValD1 = t1.getCommitted(iKeyD);
+
+                       IoTString testValA2 = t2.getCommitted(iKeyA);
+                       IoTString testValB2 = t2.getCommitted(iKeyB);
+                       IoTString testValC2 = t2.getCommitted(iKeyC);
+                       IoTString testValD2 = t2.getCommitted(iKeyD);
+
+                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyA + "    " + testValA1 + "    " + iValueA);
+                               foundError = true;
+                       }
+
+                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1 + "    " + iValueB);
+                               foundError = true;
+                       }
+
+                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyC + "    " + testValC1 + "    " + iValueC);
+                               foundError = true;
+                       }
+
+                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyD + "    " + testValD1 + "    " + iValueD);
+                               foundError = true;
+                       }
+
+                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2 + "    " + iValueA);
+                               foundError = true;
+                       }
+
+                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2 + "    " + iValueB);
+                               foundError = true;
+                       }
+
+                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2 + "    " + iValueC);
+                               foundError = true;
+                       }
+
+                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2 + "    " + iValueD);
+                               foundError = true;
+                       }
+               }
+
+               for (TransactionStatus status : transStatusList) {
+                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
+                               foundError = true;
+                               System.out.println(status.getStatus());
+                       }
+               }
+
+               if (foundError) {
+                       System.out.println("Found Errors...");
+               } else {
+                       System.out.println("No Errors Found...");
+               }
+       }
+
+       static void test8() throws InterruptedException {
+
+               boolean foundError = false;
+               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+               // Setup the 2 clients
+               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+               while (true) {
+                       try {
+                               t1.initTable();
+                               break;
+                       } catch (Exception e) {}
+               }
+
+               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+               while (t2.update().getFirst() == false) {}
+
+               LocalComm lc = new LocalComm(t1, t2);
+               t1.addLocalComm(t2.getId(), lc);
+               t2.addLocalComm(t1.getId(), lc);
+
+               // Make the Keys
+               System.out.println("Setting up keys");
+               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+                       System.out.println(i);
+
+                       String a = "a" + i;
+                       String b = "b" + i;
+                       String c = "c" + i;
+                       String d = "d" + i;
+                       IoTString ia = new IoTString(a);
+                       IoTString ib = new IoTString(b);
+                       IoTString ic = new IoTString(c);
+                       IoTString id = new IoTString(d);
+
+                       while (true) {
+                               try {
+                                       t1.createNewKey(ia, 321);
+                                       break;
+                               } catch (Exception e) {}
+                       }
+
+                       while (true) {
+                               try {
+                                       t1.createNewKey(ib, 351);
+                                       break;
+                               } catch (Exception e) {}
+                       }
+
+                       while (true) {
+                               try {
+                                       t2.createNewKey(ic, 321);
+                                       break;
+                               } catch (Exception e) {}
+                       }
+
+                       while (true) {
+                               try {
+                                       t2.createNewKey(id, 351);
+                                       break;
+                               } catch (Exception e) {}
+                       }
+               }
+
+               // Do Updates for the keys
+               System.out.println("Setting Key-Values...");
+               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+                       System.out.println(i);
+                       String keyA = "a" + i;
+                       String keyB = "b" + i;
+                       String keyC = "c" + i;
+                       String keyD = "d" + i;
+                       String valueA = "a" + i;
+                       String valueB = "b" + i;
+                       String valueC = "c" + i;
+                       String valueD = "d" + i;
+
+                       IoTString iKeyA = new IoTString(keyA);
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iKeyD = new IoTString(keyD);
+                       IoTString iValueA = new IoTString(valueA);
+                       IoTString iValueB = new IoTString(valueB);
+                       IoTString iValueC = new IoTString(valueC);
+                       IoTString iValueD = new IoTString(valueD);
+
+
+                       String keyAPrev = "a" + (i - 1);
+                       String keyBPrev = "b" + (i - 1);
+                       String keyCPrev = "c" + (i - 1);
+                       String keyDPrev = "d" + (i - 1);
+                       String valueAPrev = "a" + (i - 1);
+                       String valueBPrev = "b" + (i - 1);
+                       String valueCPrev = "c" + (i - 1);
+                       String valueDPrev = "d" + (i - 1);
+
+                       IoTString iKeyAPrev = new IoTString(keyAPrev);
+                       IoTString iKeyBPrev = new IoTString(keyBPrev);
+                       IoTString iKeyCPrev = new IoTString(keyCPrev);
+                       IoTString iKeyDPrev = new IoTString(keyDPrev);
+                       IoTString iValueAPrev = new IoTString(valueAPrev);
+                       IoTString iValueBPrev = new IoTString(valueBPrev);
+                       IoTString iValueCPrev = new IoTString(valueCPrev);
+                       IoTString iValueDPrev = new IoTString(valueDPrev);
+
+                       t1.startTransaction();
+                       if (i != 0) {
+                               IoTString tmp = t1.getSpeculative(iKeyAPrev);
+                               if ((tmp == null) || !tmp.equals(iValueAPrev)) {
+                                       System.out.println("Key a Error: " + i);
+                                       foundError = true;
+                               }
+                       }
+                       t1.addKV(iKeyA, iValueA);
+                       transStatusList.add(t1.commitTransaction());
+
+
+
+                       t1.startTransaction();
+                       if (i != 0) {
+                               IoTString tmp = t1.getSpeculative(iKeyBPrev);
+                               if ((tmp == null) || !tmp.equals(iValueBPrev)) {
+                                       System.out.println("Key b Error: " + i);
+                                       foundError = true;
+                               }
+                       }
+                       t1.addKV(iKeyB, iValueB);
+                       transStatusList.add(t1.commitTransaction());
+
+
+                       t2.startTransaction();
+                       if (i != 0) {
+                               IoTString tmp = t2.getSpeculative(iKeyCPrev);
+                               if ((tmp == null) || !tmp.equals(iValueCPrev)) {
+                                       System.out.println("Key c Error: " + i);
+                                       foundError = true;
+                               }
+                       }
+                       t2.addKV(iKeyC, iValueC);
+                       transStatusList.add(t2.commitTransaction());
+
+                       t2.startTransaction();
+                       if (i != 0) {
+                               IoTString tmp = t2.getSpeculative(iKeyDPrev);
+                               if ((tmp == null) || !tmp.equals(iValueDPrev)) {
+                                       System.out.println("Key d Error: " + i);
+                                       foundError = true;
+                               }
+                       }
+                       t2.addKV(iKeyD, iValueD);
+                       transStatusList.add(t2.commitTransaction());
+               }
+
+
+               System.out.println("Updating...");
+               while (t1.update().getFirst() == false) {}
+               while (t2.update().getFirst() == false) {}
+
+
+               System.out.println("Checking Key-Values...");
+               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+
+                       String keyA = "a" + i;
+                       String keyB = "b" + i;
+                       String keyC = "c" + i;
+                       String keyD = "d" + i;
+                       String valueA = "a" + i;
+                       String valueB = "b" + i;
+                       String valueC = "c" + i;
+                       String valueD = "d" + i;
+
+                       IoTString iKeyA = new IoTString(keyA);
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iKeyD = new IoTString(keyD);
+                       IoTString iValueA = new IoTString(valueA);
+                       IoTString iValueB = new IoTString(valueB);
+                       IoTString iValueC = new IoTString(valueC);
+                       IoTString iValueD = new IoTString(valueD);
+
+
+                       IoTString testValA1 = t1.getCommitted(iKeyA);
+                       IoTString testValB1 = t1.getCommitted(iKeyB);
+                       IoTString testValC1 = t1.getCommitted(iKeyC);
+                       IoTString testValD1 = t1.getCommitted(iKeyD);
+
+                       IoTString testValA2 = t2.getCommitted(iKeyA);
+                       IoTString testValB2 = t2.getCommitted(iKeyB);
+                       IoTString testValC2 = t2.getCommitted(iKeyC);
+                       IoTString testValD2 = t2.getCommitted(iKeyD);
+
+                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyA);
+                               foundError = true;
+                       }
+
+                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyB);
+                               foundError = true;
+                       }
+
+                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyC);
+                               foundError = true;
+                       }
+
+                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyD);
+                               foundError = true;
+                       }
+
+
+                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
+                               foundError = true;
+                       }
+
+                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                               foundError = true;
+                       }
+
+                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
+                               foundError = true;
+                       }
+
+                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
+                               foundError = true;
+                       }
+               }
+
+               for (TransactionStatus status : transStatusList) {
+                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
+                               foundError = true;
+                       }
+               }
+               if (foundError) {
+                       System.out.println("Found Errors...");
+               } else {
+                       System.out.println("No Errors Found...");
+               }
+       }
+
+       static void test7() throws ServerException, InterruptedException {
+
+               boolean foundError = false;
+               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+               // Setup the 2 clients
+               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+               t1.initTable();
+               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+               t2.update();
+
+               // Make the Keys
+               System.out.println("Setting up keys");
+               for (int i = 0; i < 4; i++) {
+                       String a = "a" + i;
+                       String b = "b" + i;
+                       String c = "c" + i;
+                       String d = "d" + i;
+                       IoTString ia = new IoTString(a);
+                       IoTString ib = new IoTString(b);
+                       IoTString ic = new IoTString(c);
+                       IoTString id = new IoTString(d);
+                       t1.createNewKey(ia, 321);
+                       t1.createNewKey(ib, 351);
+                       t2.createNewKey(ic, 321);
+                       t2.createNewKey(id, 351);
+               }
+
+               // Do Updates for the keys
+               System.out.println("Setting Key-Values...");
+
+               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+                       for (int i = 0; i < 4; i++) {
+                               String keyB = "b" + i;
+                               String valueB = "b" + (i + t);
+
+                               IoTString iKeyB = new IoTString(keyB);
+                               IoTString iValueB = new IoTString(valueB);
+
+                               t1.startTransaction();
+                               t1.getSpeculativeAtomic(iKeyB);
+                               t1.addKV(iKeyB, iValueB);
+                               transStatusList.add(t1.commitTransaction());
+                       }
+               }
+
+               for (int i = 0; i < 4; i++) {
+
+                       String keyB = "b" + i;
+                       String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iValueB = new IoTString(valueB);
+
+                       IoTString testValB1 = t1.getSpeculative(iKeyB);
+                       IoTString testValB2 = t2.getSpeculative(iKeyB);
+
+                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1);
+                               foundError = true;
+                       }
+
+                       if ((testValB2 != null)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                               foundError = true;
+                       }
+               }
+
+               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+                       for (int i = 0; i < 4; i++) {
+                               String keyC = "c" + i;
+                               String valueC = "c" + (i + t);
+
+                               IoTString iKeyC = new IoTString(keyC);
+                               IoTString iValueC = new IoTString(valueC);
+
+                               t2.startTransaction();
+                               t2.getSpeculativeAtomic(iKeyC);
+                               t2.addKV(iKeyC, iValueC);
+                               transStatusList.add(t2.commitTransaction());
+                       }
+               }
+
+               for (int i = 0; i < 4; i++) {
+                       String keyC = "c" + i;
+                       String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iValueC = new IoTString(valueC);
+
+                       IoTString testValC1 = t1.getSpeculative(iKeyC);
+                       IoTString testValC2 = t2.getSpeculative(iKeyC);
+
+                       if ((testValC1 != null)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyC + "   " + testValC1);
+                               foundError = true;
+                       }
+
+                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyC + "   " + testValC2);
+                               foundError = true;
+                       }
+               }
+
+               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+                       for (int i = 0; i < 4; i++) {
+                               String keyA = "a" + i;
+                               String keyD = "d" + i;
+                               String valueA = "a" + (i + t);
+                               String valueD = "d" + (i + t);
+
+                               IoTString iKeyA = new IoTString(keyA);
+                               IoTString iKeyD = new IoTString(keyD);
+                               IoTString iValueA = new IoTString(valueA);
+                               IoTString iValueD = new IoTString(valueD);
+
+                               t1.startTransaction();
+                               t1.addKV(iKeyA, iValueA);
+                               transStatusList.add(t1.commitTransaction());
+
+                               t2.startTransaction();
+                               t2.addKV(iKeyD, iValueD);
+                               transStatusList.add(t2.commitTransaction());
+                       }
+               }
+
+               System.out.println("Updating Clients...");
+               t1.update();
+               t2.update();
+               t1.update();
+               t2.update();
+
+               System.out.println("Checking Key-Values...");
+               for (int i = 0; i < 4; i++) {
+
+                       String keyA = "a" + i;
+                       String keyB = "b" + i;
+                       String keyC = "c" + i;
+                       String keyD = "d" + i;
+                       String valueA = "a" + (i + NUMBER_OF_TESTS - 1);
+                       String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
+                       String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
+                       String valueD = "d" + (i + NUMBER_OF_TESTS - 1);
+
+                       IoTString iKeyA = new IoTString(keyA);
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iKeyD = new IoTString(keyD);
+                       IoTString iValueA = new IoTString(valueA);
+                       IoTString iValueB = new IoTString(valueB);
+                       IoTString iValueC = new IoTString(valueC);
+                       IoTString iValueD = new IoTString(valueD);
+
+
+                       IoTString testValA1 = t1.getCommitted(iKeyA);
+                       IoTString testValB1 = t1.getCommitted(iKeyB);
+                       IoTString testValC1 = t1.getCommitted(iKeyC);
+                       IoTString testValD1 = t1.getCommitted(iKeyD);
+
+                       IoTString testValA2 = t2.getCommitted(iKeyA);
+                       IoTString testValB2 = t2.getCommitted(iKeyB);
+                       IoTString testValC2 = t2.getCommitted(iKeyC);
+                       IoTString testValD2 = t2.getCommitted(iKeyD);
+
+                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyA + "    " + testValA1);
+                               foundError = true;
+                       }
+
+                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1);
+                               foundError = true;
+                       }
+
+                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyC + "    " + testValC1);
+                               foundError = true;
+                       }
+
+                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyD + "    " + testValD1);
+                               foundError = true;
+                       }
+
+                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
+                               foundError = true;
+                       }
+
+                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                               foundError = true;
+                       }
+
+                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
+                               foundError = true;
+                       }
+
+                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
+                               foundError = true;
+                       }
+               }
+
+               for (TransactionStatus status : transStatusList) {
+                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
+                               foundError = true;
+                       }
+               }
+
+               if (foundError) {
+                       System.out.println("Found Errors...");
+               } else {
+                       System.out.println("No Errors Found...");
+               }
+       }
+
+       static void test6() throws ServerException, InterruptedException {
+
+               boolean foundError = false;
+               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+               // Setup the 2 clients
+               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+               t1.initTable();
+               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+               t2.update();
+
+               // Make the Keys
+               System.out.println("Setting up keys");
+               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+                       String a = "a" + i;
+                       String b = "b" + i;
+                       String c = "c" + i;
+                       String d = "d" + i;
+                       IoTString ia = new IoTString(a);
+                       IoTString ib = new IoTString(b);
+                       IoTString ic = new IoTString(c);
+                       IoTString id = new IoTString(d);
+                       t1.createNewKey(ia, 321);
+                       t1.createNewKey(ib, 351);
+                       t2.createNewKey(ic, 321);
+                       t2.createNewKey(id, 351);
+               }
+
+               // Do Updates for the keys
+               System.out.println("Setting Key-Values...");
+               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+                       String keyA = "a" + i;
+                       String keyB = "b" + i;
+                       String keyC = "c" + i;
+                       String keyD = "d" + i;
+                       String valueA = "a" + i;
+                       String valueB = "b" + i;
+                       String valueC = "c" + i;
+                       String valueD = "d" + i;
+
+                       IoTString iKeyA = new IoTString(keyA);
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iKeyD = new IoTString(keyD);
+                       IoTString iValueA = new IoTString(valueA);
+                       IoTString iValueB = new IoTString(valueB);
+                       IoTString iValueC = new IoTString(valueC);
+                       IoTString iValueD = new IoTString(valueD);
+
+                       t1.startTransaction();
+                       t1.getCommittedAtomic(iKeyA);
+                       t1.addKV(iKeyA, iValueA);
+                       transStatusList.add(t1.commitTransaction());
+
+                       t1.startTransaction();
+                       t1.getCommittedAtomic(iKeyB);
+                       t1.addKV(iKeyB, iValueB);
+                       transStatusList.add(t1.commitTransaction());
+
+                       t2.startTransaction();
+                       t2.getCommittedAtomic(iKeyC);
+                       t2.addKV(iKeyC, iValueC);
+                       transStatusList.add(t2.commitTransaction());
+
+                       t2.startTransaction();
+                       t2.getCommittedAtomic(iKeyD);
+                       t2.addKV(iKeyD, iValueD);
+                       transStatusList.add(t2.commitTransaction());
+               }
+
+               System.out.println("Updating Clients...");
+               t1.update();
+               t2.update();
+
+               System.out.println("Checking Key-Values...");
+               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+
+                       String keyA = "a" + i;
+                       String keyB = "b" + i;
+                       String keyC = "c" + i;
+                       String keyD = "d" + i;
+                       String valueA = "a" + i;
+                       String valueB = "b" + i;
+                       String valueC = "c" + i;
+                       String valueD = "d" + i;
+
+                       IoTString iKeyA = new IoTString(keyA);
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iKeyD = new IoTString(keyD);
+                       IoTString iValueA = new IoTString(valueA);
+                       IoTString iValueB = new IoTString(valueB);
+                       IoTString iValueC = new IoTString(valueC);
+                       IoTString iValueD = new IoTString(valueD);
+
+
+                       IoTString testValA1 = t1.getCommitted(iKeyA);
+                       IoTString testValB1 = t1.getCommitted(iKeyB);
+                       IoTString testValC1 = t1.getCommitted(iKeyC);
+                       IoTString testValD1 = t1.getCommitted(iKeyD);
+
+                       IoTString testValA2 = t2.getCommitted(iKeyA);
+                       IoTString testValB2 = t2.getCommitted(iKeyB);
+                       IoTString testValC2 = t2.getCommitted(iKeyC);
+                       IoTString testValD2 = t2.getCommitted(iKeyD);
+
+                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyA);
+                               foundError = true;
+                       }
+
+                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyB);
+                               foundError = true;
+                       }
+
+                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyC);
+                               foundError = true;
+                       }
+
+                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyD);
+                               foundError = true;
+                       }
+
+
+                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
+                               foundError = true;
+                       }
+
+                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                               foundError = true;
+                       }
+
+                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
+                               foundError = true;
+                       }
+
+                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
+                               foundError = true;
+                       }
+               }
+
+               for (TransactionStatus status : transStatusList) {
+                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
+                               foundError = true;
+                       }
+               }
+
+               if (foundError) {
+                       System.out.println("Found Errors...");
+               } else {
+                       System.out.println("No Errors Found...");
+               }
+       }
+
+       static void test5() throws ServerException, InterruptedException {
+
+               boolean foundError = false;
+               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+               // Setup the 2 clients
+               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+               t1.initTable();
+               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+               t2.update();
+
+
+               // Make the Keys
+               System.out.println("Setting up keys");
+               for (int i = 0; i < 4; i++) {
+                       String a = "a" + i;
+                       String b = "b" + i;
+                       String c = "c" + i;
+                       String d = "d" + i;
+                       IoTString ia = new IoTString(a);
+                       IoTString ib = new IoTString(b);
+                       IoTString ic = new IoTString(c);
+                       IoTString id = new IoTString(d);
+                       t1.createNewKey(ia, 321);
+                       t1.createNewKey(ib, 351);
+                       t2.createNewKey(ic, 321);
+                       t2.createNewKey(id, 351);
+               }
+
+               // Do Updates for the keys
+               System.out.println("Setting Key-Values...");
+
+               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+                       for (int i = 0; i < 4; i++) {
+                               String keyB = "b" + i;
+                               String valueB = "b" + (i + t);
+
+                               IoTString iKeyB = new IoTString(keyB);
+                               IoTString iValueB = new IoTString(valueB);
+
+                               t1.startTransaction();
+                               t1.addKV(iKeyB, iValueB);
+                               transStatusList.add(t1.commitTransaction());
+                       }
+               }
+
+               for (int i = 0; i < 4; i++) {
+
+                       String keyB = "b" + i;
+                       String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iValueB = new IoTString(valueB);
+
+                       IoTString testValB1 = t1.getSpeculative(iKeyB);
+                       IoTString testValB2 = t2.getSpeculative(iKeyB);
+
+                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyB);
+                               foundError = true;
+                       }
+
+                       if ((testValB2 != null)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyB);
+                               foundError = true;
+                       }
+               }
+
+               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+                       for (int i = 0; i < 4; i++) {
+                               String keyC = "c" + i;
+                               String valueC = "c" + (i + t);
+
+                               IoTString iKeyC = new IoTString(keyC);
+                               IoTString iValueC = new IoTString(valueC);
+
+                               t2.startTransaction();
+                               t2.addKV(iKeyC, iValueC);
+                               transStatusList.add(t2.commitTransaction());
+                       }
+               }
+
+               for (int i = 0; i < 4; i++) {
+                       String keyC = "c" + i;
+                       String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iValueC = new IoTString(valueC);
+
+                       IoTString testValC1 = t1.getSpeculative(iKeyC);
+                       IoTString testValC2 = t2.getSpeculative(iKeyC);
+
+                       if ((testValC1 != null)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyC + "   " + testValC1);
+                               foundError = true;
+                       }
+
+                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyC + "   " + testValC2);
+                               foundError = true;
+                       }
+               }
+
+               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+                       for (int i = 0; i < 4; i++) {
+                               String keyA = "a" + i;
+                               String keyD = "d" + i;
+                               String valueA = "a" + (i + t);
+                               String valueD = "d" + (i + t);
+
+                               IoTString iKeyA = new IoTString(keyA);
+                               IoTString iKeyD = new IoTString(keyD);
+                               IoTString iValueA = new IoTString(valueA);
+                               IoTString iValueD = new IoTString(valueD);
+
+                               t1.startTransaction();
+                               t1.addKV(iKeyA, iValueA);
+                               transStatusList.add(t1.commitTransaction());
+
+                               t2.startTransaction();
+                               t2.addKV(iKeyD, iValueD);
+                               transStatusList.add(t2.commitTransaction());
+                       }
+               }
+
+               System.out.println("Updating Clients...");
+               t1.update();
+               t2.update();
+
+
+               System.out.println("Checking Key-Values...");
+               for (int i = 0; i < 4; i++) {
+
+                       String keyA = "a" + i;
+                       String keyB = "b" + i;
+                       String keyC = "c" + i;
+                       String keyD = "d" + i;
+                       String valueA = "a" + (i + NUMBER_OF_TESTS - 1);
+                       String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
+                       String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
+                       String valueD = "d" + (i + NUMBER_OF_TESTS - 1);
+
+                       IoTString iKeyA = new IoTString(keyA);
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iKeyD = new IoTString(keyD);
+                       IoTString iValueA = new IoTString(valueA);
+                       IoTString iValueB = new IoTString(valueB);
+                       IoTString iValueC = new IoTString(valueC);
+                       IoTString iValueD = new IoTString(valueD);
+
+
+                       IoTString testValA1 = t1.getCommitted(iKeyA);
+                       IoTString testValB1 = t1.getCommitted(iKeyB);
+                       IoTString testValC1 = t1.getCommitted(iKeyC);
+                       IoTString testValD1 = t1.getCommitted(iKeyD);
+
+                       IoTString testValA2 = t2.getCommitted(iKeyA);
+                       IoTString testValB2 = t2.getCommitted(iKeyB);
+                       IoTString testValC2 = t2.getCommitted(iKeyC);
+                       IoTString testValD2 = t2.getCommitted(iKeyD);
+
+                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyA + "    " + testValA1);
+                               foundError = true;
+                       }
+
+                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1);
+                               foundError = true;
+                       }
+
+                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyC + "    " + testValC1);
+                               foundError = true;
+                       }
+
+                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyD + "    " + testValD1);
+                               foundError = true;
+                       }
+
+
+                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
+                               foundError = true;
+                       }
+
+                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                               foundError = true;
+                       }
+
+                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
+                               foundError = true;
+                       }
+
+                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
+                               foundError = true;
+                       }
+               }
+
+               for (TransactionStatus status : transStatusList) {
+                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
+                               foundError = true;
+                       }
+               }
+
+               if (foundError) {
+                       System.out.println("Found Errors...");
+               } else {
+                       System.out.println("No Errors Found...");
+               }
+       }
+
+       static void test4() throws ServerException, InterruptedException {
+
+               boolean foundError = false;
+               long startTime = 0;
+               long endTime = 0;
+               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+               // Setup the 2 clients
+               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+               t1.initTable();
+               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+               t2.update();
+
+               // Make the Keys
+               System.out.println("Setting up keys");
+               startTime = System.currentTimeMillis();
+               for (int i = 0; i < 4; i++) {
+                       String a = "a" + i;
+                       String b = "b" + i;
+                       String c = "c" + i;
+                       String d = "d" + i;
+                       IoTString ia = new IoTString(a);
+                       IoTString ib = new IoTString(b);
+                       IoTString ic = new IoTString(c);
+                       IoTString id = new IoTString(d);
+                       t1.createNewKey(ia, 321);
+                       t1.createNewKey(ib, 351);
+                       t2.createNewKey(ic, 321);
+                       t2.createNewKey(id, 351);
+               }
+               endTime = System.currentTimeMillis();
+               System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
+               System.out.println("Time Taken Per Key: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
+               System.out.println();
+
+
+               // Do Updates for the keys
+               System.out.println("Setting Key-Values...");
+               startTime = System.currentTimeMillis();
+               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+                       for (int i = 0; i < 4; i++) {
+                               String keyA = "a" + i;
+                               String keyB = "b" + i;
+                               String keyC = "c" + i;
+                               String keyD = "d" + i;
+                               String valueA = "a" + i;
+                               String valueB = "b" + i;
+                               String valueC = "c" + i;
+                               String valueD = "d" + i;
+
+                               IoTString iKeyA = new IoTString(keyA);
+                               IoTString iKeyB = new IoTString(keyB);
+                               IoTString iKeyC = new IoTString(keyC);
+                               IoTString iKeyD = new IoTString(keyD);
+                               IoTString iValueA = new IoTString(valueA);
+                               IoTString iValueB = new IoTString(valueB);
+                               IoTString iValueC = new IoTString(valueC);
+                               IoTString iValueD = new IoTString(valueD);
+
+                               t1.startTransaction();
+                               t1.addKV(iKeyA, iValueA);
+                               transStatusList.add(t1.commitTransaction());
+
+                               t1.startTransaction();
+                               t1.addKV(iKeyB, iValueB);
+                               transStatusList.add(t1.commitTransaction());
+
+                               t2.startTransaction();
+                               t2.addKV(iKeyC, iValueC);
+                               transStatusList.add(t2.commitTransaction());
+
+                               t2.startTransaction();
+                               t2.addKV(iKeyD, iValueD);
+                               transStatusList.add(t2.commitTransaction());
+                       }
+               }
+               endTime = System.currentTimeMillis();
+               System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
+               System.out.println("Time Taken Per Update: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 16))   );
+               System.out.println();
+
+
+               System.out.println("Updating Clients...");
+               t1.update();
+               t2.update();
+
+
+               System.out.println("Checking Key-Values...");
+               for (int i = 0; i < 4; i++) {
+
+                       String keyA = "a" + i;
+                       String keyB = "b" + i;
+                       String keyC = "c" + i;
+                       String keyD = "d" + i;
+                       String valueA = "a" + i;
+                       String valueB = "b" + i;
+                       String valueC = "c" + i;
+                       String valueD = "d" + i;
+
+                       IoTString iKeyA = new IoTString(keyA);
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iKeyD = new IoTString(keyD);
+                       IoTString iValueA = new IoTString(valueA);
+                       IoTString iValueB = new IoTString(valueB);
+                       IoTString iValueC = new IoTString(valueC);
+                       IoTString iValueD = new IoTString(valueD);
+
+
+                       IoTString testValA1 = t1.getCommitted(iKeyA);
+                       IoTString testValB1 = t1.getCommitted(iKeyB);
+                       IoTString testValC1 = t1.getCommitted(iKeyC);
+                       IoTString testValD1 = t1.getCommitted(iKeyD);
+
+                       IoTString testValA2 = t2.getCommitted(iKeyA);
+                       IoTString testValB2 = t2.getCommitted(iKeyB);
+                       IoTString testValC2 = t2.getCommitted(iKeyC);
+                       IoTString testValD2 = t2.getCommitted(iKeyD);
+
+                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyA);
+                               foundError = true;
+                       }
+
+                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyB);
+                               foundError = true;
+                       }
+
+                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyC);
+                               foundError = true;
+                       }
+
+                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyD);
+                               foundError = true;
+                       }
+
+
+                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
+                               foundError = true;
+                       }
+
+                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                               foundError = true;
+                       }
+
+                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
+                               foundError = true;
+                       }
+
+                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
+                               foundError = true;
+                       }
+               }
+
+               for (TransactionStatus status : transStatusList) {
+                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
+                               foundError = true;
+                       }
+               }
+
+               if (foundError) {
+                       System.out.println("Found Errors...");
+               } else {
+                       System.out.println("No Errors Found...");
+               }
+       }
+
+       static void test3() throws ServerException, InterruptedException {
+
+               long startTime = 0;
+               long endTime = 0;
+               boolean foundError = false;
+
+               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+               // Setup the 2 clients
+               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+               t1.initTable();
+               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+               t2.update();
+
+
+               // Make the Keys
+               System.out.println("Setting up keys");
+               startTime = System.currentTimeMillis();
+               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+                       String a = "a" + i;
+                       String b = "b" + i;
+                       String c = "c" + i;
+                       String d = "d" + i;
+                       IoTString ia = new IoTString(a);
+                       IoTString ib = new IoTString(b);
+                       IoTString ic = new IoTString(c);
+                       IoTString id = new IoTString(d);
+                       t1.createNewKey(ia, 321);
+                       t1.createNewKey(ib, 351);
+                       t2.createNewKey(ic, 321);
+                       t2.createNewKey(id, 351);
+               }
+               endTime = System.currentTimeMillis();
+               System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
+               System.out.println("Time Taken Per Key: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
+               System.out.println();
+
+
+               // Do Updates for the keys
+               System.out.println("Setting Key-Values...");
+               startTime = System.currentTimeMillis();
+               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+                       String keyB = "b" + i;
+                       String valueB = "b" + i;
+
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iValueB = new IoTString(valueB);
+
+                       t1.startTransaction();
+                       t1.addKV(iKeyB, iValueB);
+                       transStatusList.add(t1.commitTransaction());
+               }
+
+               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+                       String keyC = "c" + i;
+                       String valueC = "c" + i;
+
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iValueC = new IoTString(valueC);
+
+                       t2.startTransaction();
+                       t2.addKV(iKeyC, iValueC);
+                       transStatusList.add(t2.commitTransaction());
+               }
+
+               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+                       String keyA = "a" + i;
+                       String keyD = "d" + i;
+                       String valueA = "a" + i;
+                       String valueD = "d" + i;
+
+                       IoTString iKeyA = new IoTString(keyA);
+                       IoTString iKeyD = new IoTString(keyD);
+                       IoTString iValueA = new IoTString(valueA);
+                       IoTString iValueD = new IoTString(valueD);
+
+                       t1.startTransaction();
+                       t1.addKV(iKeyA, iValueA);
+                       transStatusList.add(t1.commitTransaction());
+
+                       t2.startTransaction();
+                       t2.addKV(iKeyD, iValueD);
+                       transStatusList.add(t2.commitTransaction());
+               }
+               endTime = System.currentTimeMillis();
+               System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
+               System.out.println("Time Taken Per Update: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
+               System.out.println();
+
+
+               System.out.println("Updating Clients...");
+               t1.update();
+               t2.update();
+
+
+               System.out.println("Checking Key-Values...");
+               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+
+                       String keyA = "a" + i;
+                       String keyB = "b" + i;
+                       String keyC = "c" + i;
+                       String keyD = "d" + i;
+                       String valueA = "a" + i;
+                       String valueB = "b" + i;
+                       String valueC = "c" + i;
+                       String valueD = "d" + i;
+
+                       IoTString iKeyA = new IoTString(keyA);
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iKeyD = new IoTString(keyD);
+                       IoTString iValueA = new IoTString(valueA);
+                       IoTString iValueB = new IoTString(valueB);
+                       IoTString iValueC = new IoTString(valueC);
+                       IoTString iValueD = new IoTString(valueD);
+
+
+                       IoTString testValA1 = t1.getCommitted(iKeyA);
+                       IoTString testValB1 = t1.getCommitted(iKeyB);
+                       IoTString testValC1 = t1.getCommitted(iKeyC);
+                       IoTString testValD1 = t1.getCommitted(iKeyD);
+
+                       IoTString testValA2 = t2.getCommitted(iKeyA);
+                       IoTString testValB2 = t2.getCommitted(iKeyB);
+                       IoTString testValC2 = t2.getCommitted(iKeyC);
+                       IoTString testValD2 = t2.getCommitted(iKeyD);
+
+                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyA);
+                               foundError = true;
+                       }
+
+                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyB);
+                               foundError = true;
+                       }
+
+                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyC);
+                               foundError = true;
+                       }
+
+                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyD);
+                               foundError = true;
+                       }
+
+
+                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
+                               foundError = true;
+                       }
+
+                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                               foundError = true;
+                       }
+
+                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
+                               foundError = true;
+                       }
+
+                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
+                               foundError = true;
+                       }
+               }
+
+               for (TransactionStatus status : transStatusList) {
+                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
+                               foundError = true;
+                       }
+               }
+
+               if (foundError) {
+                       System.out.println("Found Errors...");
+               } else {
+                       System.out.println("No Errors Found...");
+               }
+       }
+
+       static void test2() throws ServerException, InterruptedException {
+
+               boolean foundError = false;
+               long startTime = 0;
+               long endTime = 0;
+               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+               // Setup the 2 clients
+               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+               t1.initTable();
+               System.out.println("T1 Ready");
+
+               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+               t2.update();
+               System.out.println("T2 Ready");
+
+               // Make the Keys
+               System.out.println("Setting up keys");
+               startTime = System.currentTimeMillis();
+               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+                       String a = "a" + i;
+                       String b = "b" + i;
+                       String c = "c" + i;
+                       String d = "d" + i;
+                       IoTString ia = new IoTString(a);
+                       IoTString ib = new IoTString(b);
+                       IoTString ic = new IoTString(c);
+                       IoTString id = new IoTString(d);
+                       t1.createNewKey(ia, 321);
+                       t1.createNewKey(ib, 351);
+                       t2.createNewKey(ic, 321);
+                       t2.createNewKey(id, 351);
+               }
+               endTime = System.currentTimeMillis();
+               System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
+               System.out.println("Time Taken Per Key: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
+               System.out.println();
+
+               // Do Updates for the keys
+               System.out.println("Setting Key-Values...");
+               startTime = System.currentTimeMillis();
+               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+                       String keyA = "a" + i;
+                       String keyB = "b" + i;
+                       String keyC = "c" + i;
+                       String keyD = "d" + i;
+                       String valueA = "a" + i;
+                       String valueB = "b" + i;
+                       String valueC = "c" + i;
+                       String valueD = "d" + i;
+
+                       IoTString iKeyA = new IoTString(keyA);
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iKeyD = new IoTString(keyD);
+                       IoTString iValueA = new IoTString(valueA);
+                       IoTString iValueB = new IoTString(valueB);
+                       IoTString iValueC = new IoTString(valueC);
+                       IoTString iValueD = new IoTString(valueD);
+
+                       t1.startTransaction();
+                       t1.addKV(iKeyA, iValueA);
+                       transStatusList.add(t1.commitTransaction());
+
+                       t1.startTransaction();
+                       t1.addKV(iKeyB, iValueB);
+                       transStatusList.add(t1.commitTransaction());
+
+                       t2.startTransaction();
+                       t2.addKV(iKeyC, iValueC);
+                       transStatusList.add(t2.commitTransaction());
+
+                       t2.startTransaction();
+                       t2.addKV(iKeyD, iValueD);
+                       transStatusList.add(t2.commitTransaction());
+               }
+               endTime = System.currentTimeMillis();
+               System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
+               System.out.println("Time Taken Per Update: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
+               System.out.println();
+
+
+               System.out.println("Updating Clients...");
+               t1.update();
+               t2.update();
+
+
+               System.out.println("Checking Key-Values...");
+               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+
+                       String keyA = "a" + i;
+                       String keyB = "b" + i;
+                       String keyC = "c" + i;
+                       String keyD = "d" + i;
+                       String valueA = "a" + i;
+                       String valueB = "b" + i;
+                       String valueC = "c" + i;
+                       String valueD = "d" + i;
+
+                       IoTString iKeyA = new IoTString(keyA);
+                       IoTString iKeyB = new IoTString(keyB);
+                       IoTString iKeyC = new IoTString(keyC);
+                       IoTString iKeyD = new IoTString(keyD);
+                       IoTString iValueA = new IoTString(valueA);
+                       IoTString iValueB = new IoTString(valueB);
+                       IoTString iValueC = new IoTString(valueC);
+                       IoTString iValueD = new IoTString(valueD);
+
+
+                       IoTString testValA1 = t1.getCommitted(iKeyA);
+                       IoTString testValB1 = t1.getCommitted(iKeyB);
+                       IoTString testValC1 = t1.getCommitted(iKeyC);
+                       IoTString testValD1 = t1.getCommitted(iKeyD);
+
+                       IoTString testValA2 = t2.getCommitted(iKeyA);
+                       IoTString testValB2 = t2.getCommitted(iKeyB);
+                       IoTString testValC2 = t2.getCommitted(iKeyC);
+                       IoTString testValD2 = t2.getCommitted(iKeyD);
+
+                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyA);
+                               foundError = true;
+                       }
+
+                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyB);
+                               foundError = true;
+                       }
+
+                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyC);
+                               foundError = true;
+                       }
+
+                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t1 incorrect: " + keyD);
+                               foundError = true;
+                       }
+
+
+                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
+                               foundError = true;
+                       }
+
+                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                               foundError = true;
+                       }
+
+                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
+                               foundError = true;
+                       }
+
+                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
+                               foundError = true;
+                       }
+               }
+
+               for (TransactionStatus status : transStatusList) {
+                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
+                               foundError = true;
+                       }
+               }
+
+               if (foundError) {
+                       System.out.println("Found Errors...");
+               } else {
+                       System.out.println("No Errors Found...");
+               }
+       }
+}
diff --git a/version2/backup/src/java/iotcloud/ThreeTuple.java b/version2/backup/src/java/iotcloud/ThreeTuple.java
new file mode 100644 (file)
index 0000000..8a882a4
--- /dev/null
@@ -0,0 +1,29 @@
+package iotcloud;
+
+class ThreeTuple<A, B, C> {
+    private A a;
+    private B b;
+    private C c;
+
+    ThreeTuple(A a, B b, C c) {
+        this.a = a;
+        this.b = b;
+        this.c = c;
+    }
+
+    A getFirst() {
+        return a;
+    }
+
+    B getSecond() {
+        return b;
+    }
+
+    C getThird() {
+        return c;
+    }
+
+    public String toString() {
+        return "<" + a + "," + b + "," + c + ">";
+    }
+}
diff --git a/version2/backup/src/java/iotcloud/Transaction.java b/version2/backup/src/java/iotcloud/Transaction.java
new file mode 100644 (file)
index 0000000..90ef4d4
--- /dev/null
@@ -0,0 +1,154 @@
+package iotcloud;
+
+import java.nio.ByteBuffer;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Map;
+
+class Transaction extends Entry {
+
+    private long seqnum;
+    private long machineid;
+    private Set<KeyValue> keyValueUpdateSet = null;
+    private Set<KeyValue> keyValueGuardSet = null;
+    private Long arbitrator;
+
+    public Transaction(Slot slot, long _seqnum, long _machineid, Long _arbitrator, Set<KeyValue> _keyValueUpdateSet, Set<KeyValue> _keyValueGuardSet) {
+        super(slot);
+        seqnum = _seqnum;
+        machineid = _machineid;
+        arbitrator = _arbitrator;
+        // keyValueUpdateSet = new HashSet<KeyValue>();
+        // keyValueGuardSet = new HashSet<KeyValue>();
+
+        // for (KeyValue kv : _keyValueUpdateSet) {
+        //     KeyValue kvCopy = kv.getCopy();
+        //     keyValueUpdateSet.add(kvCopy);
+        // }
+
+        // for (KeyValue kv : _keyValueGuardSet) {
+        //     KeyValue kvCopy = kv.getCopy();
+        //     keyValueGuardSet.add(kvCopy);
+        // }
+
+        keyValueUpdateSet = _keyValueUpdateSet;
+        keyValueGuardSet = _keyValueGuardSet;
+    }
+
+    public long getMachineID() {
+        return machineid;
+    }
+
+    public long getArbitrator() {
+        return arbitrator;
+    }
+
+    public long getSequenceNumber() {
+        return seqnum;
+    }
+
+
+    public Set<KeyValue> getkeyValueUpdateSet() {
+        return keyValueUpdateSet;
+    }
+
+    public Set<KeyValue> getkeyValueGuardSet() {
+        return keyValueGuardSet;
+    }
+
+    public boolean evaluateGuard(Map<IoTString, KeyValue> keyValTableCommitted, Map<IoTString, KeyValue> keyValTableSpeculative) {
+        for (KeyValue kvGuard : keyValueGuardSet) {
+
+            // First check if the key is in the speculative table, this is the value of the latest assumption
+            KeyValue kv = null;
+
+            // If we have a speculation table then use it first
+            if (keyValTableSpeculative != null) {
+                kv = keyValTableSpeculative.get(kvGuard.getKey());
+            }
+
+            if (kv == null) {
+
+                // if it is not in the speculative table then check the committed table and use that
+                // value as our latest assumption
+                kv = keyValTableCommitted.get(kvGuard.getKey());
+            }
+
+            if (kvGuard.getValue() != null) {
+                if ((kv == null) || (!kvGuard.getValue().equals(kv.getValue()))) {
+                    return false;
+                }
+            } else {
+                if (kv != null) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    public byte getType() {
+        return Entry.TypeTransaction;
+    }
+
+    public int getSize() {
+        int size = 3 * Long.BYTES + Byte.BYTES; // seq, machine id, entry type
+        size += Integer.BYTES; // number of KV's
+        size += Integer.BYTES; // number of Guard KV's
+
+        // Size of each KV
+        for (KeyValue kv : keyValueUpdateSet) {
+            size += kv.getSize();
+        }
+
+        // Size of each Guard KV
+        for (KeyValue kv : keyValueGuardSet) {
+            size += kv.getSize();
+        }
+
+        return size;
+    }
+
+    public void encode(ByteBuffer bb) {
+        bb.put(Entry.TypeTransaction);
+        bb.putLong(seqnum);
+        bb.putLong(machineid);
+        bb.putLong(arbitrator);
+
+        bb.putInt(keyValueUpdateSet.size());
+        for (KeyValue kv : keyValueUpdateSet) {
+            kv.encode(bb);
+        }
+
+        bb.putInt(keyValueGuardSet.size());
+        for (KeyValue kv : keyValueGuardSet) {
+            kv.encode(bb);
+        }
+    }
+
+    static Entry decode(Slot slot, ByteBuffer bb) {
+        long seqnum = bb.getLong();
+        long machineid = bb.getLong();
+        long arbitrator = bb.getLong();
+        int numberOfKeys = bb.getInt();
+
+        Set<KeyValue> kvSetUpdates = new HashSet<KeyValue>();
+        for (int i = 0; i < numberOfKeys; i++) {
+            KeyValue kv = KeyValue.decode(bb);
+            kvSetUpdates.add(kv);
+        }
+
+        int numberOfGuards = bb.getInt();
+        Set<KeyValue> kvSetGuards = new HashSet<KeyValue>();
+        for (int i = 0; i < numberOfGuards; i++) {
+            KeyValue kv = KeyValue.decode(bb);
+            kvSetGuards.add(kv);
+        }
+
+        return new Transaction(slot, seqnum, machineid, arbitrator, kvSetUpdates, kvSetGuards);
+    }
+
+    public Entry getCopy(Slot s) {
+        return new Transaction(s, seqnum, machineid, arbitrator, keyValueUpdateSet, keyValueGuardSet);
+    }
+}
\ No newline at end of file
diff --git a/version2/backup/src/java/iotcloud/TransactionStatus.java b/version2/backup/src/java/iotcloud/TransactionStatus.java
new file mode 100644 (file)
index 0000000..a42f570
--- /dev/null
@@ -0,0 +1,53 @@
+package iotcloud;
+
+class TransactionStatus {
+    static final byte StatusAborted = 1;
+    static final byte StatusPending = 2;
+    static final byte StatusCommitted = 3;
+    // static final byte StatusRetrying = 4;
+    static final byte StatusSent = 5;
+    static final byte StatusNoEffect = 6;
+
+    private byte status = 0;
+    private boolean applicationReleased = false;
+    private long arbitrator = 0;
+    private boolean wasSentInChain = false;
+
+    public TransactionStatus(byte _status, long _arbitrator) {
+        status = _status;
+        arbitrator = _arbitrator;
+    }
+
+    public byte getStatus() {
+        return status;
+    }
+
+    public void setStatus(byte _status) {
+        status = _status;
+    }
+
+    public void setSentTransaction() {
+        wasSentInChain = true;
+    }
+
+    public boolean getSentTransaction() {
+        return wasSentInChain;
+    }
+
+
+    // public void setArbitrator(long _arbitrator) {
+    //     arbitrator = _arbitrator;
+    // }
+
+    public long getArbitrator() {
+        return arbitrator;
+    }
+
+    public void release() {
+        applicationReleased = true;
+    }
+
+    public boolean getReleased() {
+        return applicationReleased;
+    }
+}
\ No newline at end of file
diff --git a/version2/backup/src/java/iotcloud/issues.txt b/version2/backup/src/java/iotcloud/issues.txt
new file mode 100644 (file)
index 0000000..4c246b6
--- /dev/null
@@ -0,0 +1,2 @@
+1) add better resizing support...gets stuck when it is full now...
+2) Transaction does not check arbitrator is the same for all keys and guards
\ No newline at end of file
diff --git a/version2/backup/src/script/C.cfg b/version2/backup/src/script/C.cfg
new file mode 100644 (file)
index 0000000..6165d83
--- /dev/null
@@ -0,0 +1,37 @@
+indent_with_tabs = 2
+indent_cmt_with_tabs = True
+indent_columns = 2
+indent_class = True
+output_tab_size = 2
+nl_if_brace = Remove
+nl_brace_else = Remove
+nl_elseif_brace = Remove
+nl_struct_brace = Remove
+nl_union_brace = Remove
+nl_fcall_brace = Remove
+nl_for_brace = Remove
+nl_fdef_brace = Remove
+nl_while_brace = Remove
+nl_do_brace = Remove
+nl_brace_while = Remove
+nl_switch_brace = Remove
+nl_before_case = True
+nl_try_brace = Remove
+nl_catch_brace = Remove
+nl_brace_catch = Remove
+sp_func_proto_paren = Remove
+sp_func_def_paren = Remove
+sp_inside_fparens = remove
+sp_inside_fparen = remove
+sp_func_call_paren = Remove
+sp_fparen_brace = Add
+sp_sparen_brace = Add
+sp_paren_brace = Add
+sp_else_brace = Add
+sp_brace_else = Add
+sp_catch_brace = Add
+sp_brace_catch = Add
+sp_try_brace = Add
+sp_after_sparen = Add
+sp_cond_colon = remove
+sp_cond_question = remove
diff --git a/version2/backup/src/script/java.cfg b/version2/backup/src/script/java.cfg
new file mode 100644 (file)
index 0000000..6165d83
--- /dev/null
@@ -0,0 +1,37 @@
+indent_with_tabs = 2
+indent_cmt_with_tabs = True
+indent_columns = 2
+indent_class = True
+output_tab_size = 2
+nl_if_brace = Remove
+nl_brace_else = Remove
+nl_elseif_brace = Remove
+nl_struct_brace = Remove
+nl_union_brace = Remove
+nl_fcall_brace = Remove
+nl_for_brace = Remove
+nl_fdef_brace = Remove
+nl_while_brace = Remove
+nl_do_brace = Remove
+nl_brace_while = Remove
+nl_switch_brace = Remove
+nl_before_case = True
+nl_try_brace = Remove
+nl_catch_brace = Remove
+nl_brace_catch = Remove
+sp_func_proto_paren = Remove
+sp_func_def_paren = Remove
+sp_inside_fparens = remove
+sp_inside_fparen = remove
+sp_func_call_paren = Remove
+sp_fparen_brace = Add
+sp_sparen_brace = Add
+sp_paren_brace = Add
+sp_else_brace = Add
+sp_brace_else = Add
+sp_catch_brace = Add
+sp_brace_catch = Add
+sp_try_brace = Add
+sp_after_sparen = Add
+sp_cond_colon = remove
+sp_cond_question = remove
diff --git a/version2/backup/src/script/makefile b/version2/backup/src/script/makefile
new file mode 100644 (file)
index 0000000..ac2da6e
--- /dev/null
@@ -0,0 +1,4 @@
+tabbing:
+       uncrustify -c java.cfg --no-backup $$(find .. -name "*.java")
+       uncrustify -c C.cfg --no-backup $$(find .. -name "*.cpp")
+       uncrustify -c C.cfg --no-backup $$(find .. -name "*.h")
diff --git a/version2/backup/src/server/.dir-locals.el b/version2/backup/src/server/.dir-locals.el
new file mode 100644 (file)
index 0000000..e166a2e
--- /dev/null
@@ -0,0 +1,2 @@
+((nil . ((indent-tabs-mode . t))))
+
diff --git a/version2/backup/src/server/Makefile b/version2/backup/src/server/Makefile
new file mode 100644 (file)
index 0000000..8eee1fa
--- /dev/null
@@ -0,0 +1,15 @@
+CPPFLAGS=-O0 -g -Wall
+
+all: iotcloud.fcgi
+
+iotcloud.fcgi: iotcloud.o iotquery.o
+       g++ $(CPPFLAGS) -o iotcloud.fcgi iotcloud.o iotquery.o -lfcgi -lfcgi++
+
+iotcloud.o: iotcloud.cpp iotquery.h
+       g++ $(CPPFLAGS) -c -o iotcloud.o iotcloud.cpp
+
+iotquery.o: iotquery.cpp iotquery.h
+       g++ $(CPPFLAGS) -c -o iotquery.o iotquery.cpp
+
+clean:
+       rm *.o iotcloud.fcgi
diff --git a/version2/backup/src/server/README.txt b/version2/backup/src/server/README.txt
new file mode 100644 (file)
index 0000000..6eb138f
--- /dev/null
@@ -0,0 +1,32 @@
+1) Requires apache2
+2) Requires fastcgi (libapache2-mod-fastcgi and libfcgi-dev)
+
+Setup on ubuntu
+1) Install modules
+
+2) Add .htaccess file in /var/www/html
+RewriteEngine on
+RewriteBase /
+SetHandler cgi-script
+RewriteRule ^([a-zA-Z0-9._]*\.iotcloud/([a-zA-Z0-9._]*))$ /cgi-bin/iotcloud.fcgi/$1
+
+3) Create account directory.  For example, create the directory test.iotcloud in /var/www/html
+   -- To password protect, create the following .htaccess file in the account directory:
+AuthType Basic
+AuthName "Private"
+AuthUserFile /var/www/html/foo.iotcloud/.htpasswd
+Require valid-user
+
+4) In apache2.conf, add to the /var/www directory section:
+AllowOverride FileInfo AuthConfig
+
+5) In the sites-enabled/000-default.conf file, add the line:
+SetEnv IOTCLOUD_ROOT /iotcloud/
+
+6) Create the /iotcloud directory.
+
+7) Create the account directory in the /iotcloud directory.  For example, test.iotcloud and give it permissions that the apache daemon can write to.
+
+8) Compile cloud server by typing make
+
+9) Copy it to the cgi-bin directory.
diff --git a/version2/backup/src/server/iotcloud.cpp b/version2/backup/src/server/iotcloud.cpp
new file mode 100644 (file)
index 0000000..bb9eff8
--- /dev/null
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "iotquery.h"
+
+using namespace std;
+
+
+int main(void) {
+       // Backup the stdio streambufs
+       streambuf * cin_streambuf  = cin.rdbuf();
+       streambuf * cout_streambuf = cout.rdbuf();
+       streambuf * cerr_streambuf = cerr.rdbuf();
+
+       FCGX_Request request;
+
+       FCGX_Init();
+       FCGX_InitRequest(&request, 0, 0);
+
+       while (FCGX_Accept_r(&request) == 0) {
+               fcgi_streambuf cin_fcgi_streambuf(request.in);
+               fcgi_streambuf cout_fcgi_streambuf(request.out);
+               fcgi_streambuf cerr_fcgi_streambuf(request.err);
+
+               cin.rdbuf(&cin_fcgi_streambuf);
+               cout.rdbuf(&cout_fcgi_streambuf);
+               cerr.rdbuf(&cerr_fcgi_streambuf);
+
+               IoTQuery * iotquery=new IoTQuery(&request);
+               iotquery->processQuery();
+
+               delete iotquery;
+       }
+
+       // restore stdio streambufs
+       cin.rdbuf(cin_streambuf);
+       cout.rdbuf(cout_streambuf);
+       cerr.rdbuf(cerr_streambuf);
+
+       return 0;
+}
+
diff --git a/version2/backup/src/server/iotquery.cpp b/version2/backup/src/server/iotquery.cpp
new file mode 100644 (file)
index 0000000..0b1c4b3
--- /dev/null
@@ -0,0 +1,517 @@
+#include "iotquery.h"
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <netinet/in.h>
+
+using namespace std;
+
+const char * query_str="QUERY_STRING";
+const char * uri_str="REQUEST_URI";
+const char * method_str="REQUEST_METHOD";
+const char * iotcloudroot_str="IOTCLOUD_ROOT";
+const char * length_str="CONTENT_LENGTH";
+
+IoTQuery::IoTQuery(FCGX_Request *request) :
+       request(request),
+       data(NULL),
+       directory(NULL),
+       uri(NULL),
+       query(NULL),
+       method(NULL),
+       iotcloudroot(NULL),
+       length(0),
+       oldestentry(0),
+       newestentry(0),
+       requestsequencenumber(0),
+       numqueueentries(DEFAULT_SIZE),
+       fd(-1),
+       reqGetSlot(false),
+       reqPutSlot(false),
+       reqSetSalt(false),
+       reqGetSalt(false) {
+}
+
+IoTQuery::~IoTQuery() {
+       if (fd >= 0)
+               close(fd);
+       if (directory)
+               delete directory;
+       if (data)
+               delete data;
+}
+
+/**
+ *  Returns true if the account directory exists.
+ */
+
+bool IoTQuery::checkDirectory() {
+       struct stat s;
+       int err=stat(directory, &s);
+       if (-1 == err)
+               return false;
+       return S_ISDIR(s.st_mode);
+}
+
+/**
+ * Decodes query string from client. Extracts type of request,
+ * sequence number, and whether the request changes the number of
+ * slots.
+ */
+
+void IoTQuery::decodeQuery() {
+       int len=strlen(query);
+       char * str=new char[len+1];
+       memcpy(str, query, len+1);
+       char *tok_ptr=str;
+       
+       /* Parse commands */
+       char *command=strsep(&tok_ptr, "&");
+       if (strncmp(command, "req=putslot", 11) == 0)
+               reqPutSlot = true;
+       else if (strncmp(command, "req=getslot", 11) == 0)
+               reqGetSlot = true;
+       else if (strncmp(command, "req=setsalt", 11) == 0)
+               reqSetSalt = true;
+       else if (strncmp(command, "req=getsalt", 11) == 0)
+               reqGetSalt = true;
+
+       /* Load Sequence Number for request */
+       char *sequencenumber_str = strsep(&tok_ptr, "&");
+       if (sequencenumber_str != NULL &&
+                       strncmp(sequencenumber_str, "seq=", 4) == 0) {
+               sequencenumber_str = strchr(sequencenumber_str, '=');
+               if (sequencenumber_str != NULL) {
+                       requestsequencenumber = strtoll(sequencenumber_str + 1, NULL, 10);
+               }
+       }
+
+       /* don't allow a really old sequence number */
+       if (requestsequencenumber < oldestentry)
+               requestsequencenumber = oldestentry;
+
+       /* Update size if we get request */
+       char * numqueueentries_str = tok_ptr;
+       if (numqueueentries_str != NULL &&
+                       strncmp(numqueueentries_str, "max=", 4) == 0) {
+               numqueueentries_str = strchr(numqueueentries_str, '=') + 1;
+               numqueueentries = strtoll(numqueueentries_str, NULL, 10);
+       }
+
+       delete str;
+}
+
+/**
+ * Helper function to write data to file.
+ */
+
+void doWrite(int fd, char *data, long long length) {
+       long long offset=0;
+       do {
+               long long byteswritten=write(fd, &data[offset], length);
+               if (byteswritten > 0) {
+                       length -= byteswritten;
+                       offset += byteswritten;
+               } else {
+                       cerr << "Bytes not written" << endl;
+                       if (byteswritten < 0) {
+                               cerr << strerror(errno) << " error writing slot file" << endl;
+                       }
+                       return;
+               }
+       } while(length != 0);
+}
+
+/** Helper function to read data from file. */
+bool doRead(int fd, void *buf, int numbytes) {
+       int offset=0;
+       char *ptr=(char *)buf;
+       do {
+               int bytesread=read(fd, ptr+offset, numbytes);
+               if (bytesread > 0) {
+                       offset += bytesread;
+                       numbytes -= bytesread;
+               } else
+                       return false;
+       } while (numbytes!=0);
+       return true;
+}
+
+/**
+ * Function that handles a getSlot request.
+ */
+
+void IoTQuery::getSlot() {
+       int numrequeststosend = (int)((newestentry-requestsequencenumber)+1);
+       if (numrequeststosend < 0)
+               numrequeststosend = 0;
+       long long numbytes = 0;
+       int filesizes[numrequeststosend];
+       int fdarray[numrequeststosend];
+       int index=0;
+       for(long long seqn = requestsequencenumber; seqn <= newestentry; seqn++, index++) {
+               struct stat st;
+               char *filename=getSlotFileName(seqn);
+               if (stat(filename, &st) == 0) {
+                       fdarray[index]=open(filename, O_RDONLY);
+                       filesizes[index]=st.st_size;
+                       numbytes+=filesizes[index];
+               } else {
+                       fdarray[index]=-1;
+                       filesizes[index]=0;
+               }
+               delete filename;
+       }
+       const char header[]="getslot";
+
+       /* Size is the header + the payload + space for number of requests
+                plus sizes of each slot */
+
+       long long size=sizeof(header)-1+sizeof(numrequeststosend)+4*numrequeststosend+numbytes;
+       char * response = new char[size];
+       long long offset=0;
+       memcpy(response, header, sizeof(header)-1);
+       offset+=sizeof(header)-1;
+       int numreq=htonl(numrequeststosend);
+       memcpy(response + offset, &numreq, sizeof(numreq));
+       offset+=sizeof(numrequeststosend);
+       for(int i=0; i<numrequeststosend; i++) {
+               int filesize=htonl(filesizes[i]);
+               memcpy(response + offset, &filesize, sizeof(filesize));
+               offset+=sizeof(int);
+       }
+
+       /* Read the file data into the buffer */
+       for(int i=0; i<numrequeststosend; i++) {
+               if (fdarray[i]>=0) {
+                       doRead(fdarray[i], response+offset, filesizes[i]);
+                       offset+=filesizes[i];
+               }
+       }
+
+       /* Send the response out to the webserver. */
+       sendResponse(response, size);
+
+       /* Delete the response buffer and close the files. */
+       delete response;
+       for(int i=0; i<numrequeststosend; i++) {
+               if (fdarray[i] >= 0)
+                       close(fdarray[i]);
+       }
+}
+
+/**
+ * The method setSalt handles a setSalt request from the client.
+ */
+
+void IoTQuery::setSalt() {
+       /* Write the slot data we received to a SLOT file */
+       char *filename = getSaltFileName();
+       int saltfd = open(filename, O_CREAT|O_WRONLY, S_IRUSR| S_IWUSR);
+       doWrite(saltfd, data, length);
+       char response[0];
+       sendResponse(response, 0);
+       close(saltfd);
+       delete filename;
+}
+
+/**
+ * The method getSalt handles a setSalt request from the client.
+ */
+
+void IoTQuery::getSalt() {
+       /* Write the slot data we received to a SLOT file */
+       char *filename = getSaltFileName();
+       int filesize = 0;
+       struct stat st;
+       if (stat(filename, &st) == 0) {
+               filesize=st.st_size;
+       } else {
+               delete filename;
+               return;
+       }
+       int saltfd = open(filename, O_RDONLY);
+       int responsesize = filesize + sizeof(int);
+       char * response = new char[responsesize];
+       doRead(saltfd, response+ sizeof(int), filesize);
+       int n_filesize=htonl(filesize);
+       *((int*) response) = n_filesize;
+       sendResponse(response, responsesize);
+       close(saltfd);
+       delete filename;
+       delete response;
+}
+
+/**
+ *     The method putSlot handles a putSlot request from the client
+ */
+
+void IoTQuery::putSlot() {
+       /* Check if the request is stale and send update in that case.  This
+                servers as an implicit failure of the request. */
+       if (requestsequencenumber!=(newestentry+1)) {
+               getSlot();
+               return;
+       }
+
+       /* See if we have too many slots and if so, delete the old one */
+       int numberofliveslots=(int) ((newestentry-oldestentry)+1);
+       if (numberofliveslots >=  numqueueentries) {
+               removeOldestSlot();
+       }
+
+       /* Write the slot data we received to a SLOT file */
+       char *filename = getSlotFileName(requestsequencenumber);
+       int slotfd = open(filename, O_CREAT|O_WRONLY, S_IRUSR| S_IWUSR);
+       doWrite(slotfd, data, length);
+       close(slotfd);
+       delete filename;
+       newestentry = requestsequencenumber;
+
+       /* Update the seuqence numbers and other status file information. */
+       updateStatusFile();
+
+       /* Send response acknowledging success */
+       char command[]="putslot";
+       sendResponse(command, sizeof(command)-1);
+}
+
+/**
+ * Method sends response.  It wraps in appropriate headers for web
+ * server.
+ */
+
+void IoTQuery::sendResponse(char * bytes, int len) {
+       cout << "Accept-Ranges: bytes\r\n"
+                        << "Content-Length: " << len << "\r\n"
+                        << "\r\n";
+       cout.write(bytes, len);
+}
+
+/**
+ *     Computes the name for a slot file for the given sequence number.
+ */
+
+char * IoTQuery::getSlotFileName(long long seqnum) {
+       int directorylen=strlen(directory);
+
+       /* Size is 19 digits for ASCII representation of a long + 4
+                characters for SLOT string + 1 character for null termination +
+                directory size*/
+
+       char * filename=new char[25+directorylen];
+       snprintf(filename, 25+directorylen, "%s/SLOT%lld", directory, seqnum);
+       return filename;
+}
+
+/**
+ *     Computes the name for a salt file
+ */
+
+char * IoTQuery::getSaltFileName() {
+       int directorylen=strlen(directory);
+
+       /* Size is 4 characters for SALT string + 1 character for null
+                termination + directory size*/
+
+       char * filename=new char[6+directorylen];
+       snprintf(filename, 6+directorylen, "%s/SALT", directory);
+       return filename;
+}
+
+/**
+ *  Removes the oldest slot file
+ */
+
+void IoTQuery::removeOldestSlot() {
+       if (oldestentry!=0) {
+               char * filename=getSlotFileName(oldestentry);
+               unlink(filename);
+               delete filename;
+       }
+       oldestentry++;
+}
+
+/**
+ * Processes the query sent to the fastcgi handler.
+ */
+
+void IoTQuery::processQuery() {
+       getQuery();
+       getDirectory();
+       readData();
+
+       /* Verify that we receive a post request. */
+       if (strncmp(method, "POST", 4) != 0) {
+               cerr << "Not POST Request" << endl;
+               return;
+       }
+
+       /* Make sure the directory is okay. */
+       if (directory == NULL ||
+                       !checkDirectory()) {
+               cerr << "Directory " << directory << " does not exist" << endl;
+               return;
+       }
+
+       /* Get queue state from the status file.  If it doesn't exist,
+                create it. */
+       if (!openStatusFile()) {
+               cerr << "Failed to open status file" << endl;
+               return;
+       }
+
+       /* Lock status file to keep other requests out. */
+       flock(fd, LOCK_EX);
+
+       /* Decode query. */
+       decodeQuery();
+       
+       /* Handle request. */
+       if (reqGetSlot)
+               getSlot();
+       else if (reqPutSlot)
+               putSlot();
+       else if (reqSetSalt)
+               setSalt();
+       else if (reqGetSalt)
+               getSalt();
+       else {
+               cerr << "No recognized request" << endl;
+               return;
+       }
+}
+
+/**
+ * Reads in data for request.  This is used for the slot to be
+ * inserted.
+ */
+
+void IoTQuery::readData() {
+       if (length) {
+               data = new char[length+1];
+               memset(data, 0, length+1);
+               cin.read(data, length);
+       }
+       do {
+               char dummy;
+               cin >> dummy;
+       } while (!cin.eof());
+}
+
+
+/**
+ * Reads relevant environmental variables to find out the request.
+ */
+
+void IoTQuery::getQuery() {
+       uri = FCGX_GetParam(uri_str, request->envp);
+       query = FCGX_GetParam(query_str, request->envp);
+       method = FCGX_GetParam(method_str, request->envp);
+       iotcloudroot = FCGX_GetParam(iotcloudroot_str, request->envp);
+
+       /** We require the content-length header to be sent. */
+       char * reqlength = FCGX_GetParam(length_str, request->envp);
+       if (reqlength) {
+               length=strtoll(reqlength, NULL, 10);
+       } else {
+               length=0;
+       }
+}
+
+/**
+ *  Initializes directory field from environmental variables.
+ */
+
+void IoTQuery::getDirectory() {
+       char * split = strchr((char *)uri, '?');
+       if (split == NULL)
+               return;
+       int split_len = (int) (split-uri);
+       int rootdir_len = strlen(iotcloudroot);
+       int directory_len = split_len + rootdir_len + 1;
+       directory = new char[directory_len];
+       memcpy(directory, iotcloudroot, rootdir_len);
+       memcpy(directory + rootdir_len, uri, split_len);
+       directory[directory_len-1]=0;
+}
+
+/**
+ * Helper function that is used to read the status file.
+ */
+
+int doread(int fd, void *ptr, size_t count, off_t offset) {
+       do {
+               size_t bytesread=pread(fd, ptr, count, offset);
+               if (bytesread==count) {
+                       return 1;
+               } else if (bytesread==0) {
+                       return 0;
+               }
+       } while(1);
+}
+
+
+/**
+ * Writes the current state to the status file.
+ */
+
+void IoTQuery::updateStatusFile() {
+       pwrite(fd, &numqueueentries, sizeof(numqueueentries), OFFSET_MAX);
+       pwrite(fd, &oldestentry, sizeof(oldestentry), OFFSET_OLD);
+       pwrite(fd, &newestentry, sizeof(newestentry), OFFSET_NEW);
+}
+
+/**
+ * Reads in queue state from the status file.  Returns true if
+ * successful.
+ */
+
+bool IoTQuery::openStatusFile() {
+       char statusfile[]="queuestatus";
+       int len=strlen(directory);
+
+       char * filename=new char[len+sizeof(statusfile)+2];
+       memcpy(filename, directory, len);
+       filename[len]='/';
+       memcpy(filename+len+1, statusfile, sizeof(statusfile));
+       filename[len+sizeof(statusfile)+1]=0;
+       fd=open(filename, O_CREAT| O_RDWR, S_IRUSR| S_IWUSR);
+       delete filename;
+
+       if (fd < 0) {
+               cerr << strerror(errno) << " error opening statusfile" << endl;
+               return false;
+       }
+
+       /* Read in queue size, oldest sequence number, and newest sequence number. */
+       int size;
+       int needwrite=0;
+       if (doread(fd, &size, sizeof(size), OFFSET_MAX))
+               numqueueentries=size;
+       else
+               needwrite=1;
+
+       long long entry;
+       if (doread(fd, &entry, sizeof(entry), OFFSET_OLD))
+               oldestentry=entry;
+       else
+               needwrite=1;
+
+       if (doread(fd, &entry, sizeof(entry), OFFSET_NEW))
+               newestentry=entry;
+       else
+               needwrite=1;
+
+       if (needwrite)
+               updateStatusFile();
+
+       return true;
+}
+
+
diff --git a/version2/backup/src/server/iotquery.h b/version2/backup/src/server/iotquery.h
new file mode 100644 (file)
index 0000000..ae39366
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef IOTQUERY_H
+#define IOTQUERY_H
+#include <iostream>
+#include "fcgio.h"
+#include "fcgi_stdio.h"
+
+#define DEFAULT_SIZE 128
+#define OFFSET_MAX 0
+#define OFFSET_OLD 4
+#define OFFSET_NEW 12
+
+class IoTQuery {
+public:
+       IoTQuery(FCGX_Request * request);
+       ~IoTQuery();
+       void processQuery();
+
+private:
+       void sendResponse(char *data, int length);
+       void getQuery();
+       void getDirectory();
+       void readData();
+       bool checkDirectory();
+       bool openStatusFile();
+       void updateStatusFile();
+       void decodeQuery();
+       void getSlot();
+       void putSlot();
+       void setSalt();
+       void getSalt();
+       void removeOldestSlot();
+       char * getSlotFileName(long long);
+       char * getSaltFileName();
+
+       FCGX_Request * request;
+       char *data;
+       /* Directory slot files are placed in. */
+       char *directory;
+       /* Full URI from Apache */
+       const char * uri;
+       /* Query portion of URI */
+       const char * query;
+       /* Type of request: GET or PUT */
+       const char * method;
+       /* Root directory for all accounts */
+       const char * iotcloudroot;
+       /* Expected length of data from client */
+       long long length;
+       /* Sequence number for oldest slot */
+       long long oldestentry;
+       /* Sequence number for newest slot */
+       long long newestentry;
+       /* Sequence number from request */
+       long long requestsequencenumber;
+       /* Size of queue */
+       int numqueueentries;
+       /* fd for queuestatus file */
+       int fd;
+       /* Is the request to get a slot? */
+       bool reqGetSlot;
+       /* Is the request to put a slot? */
+       bool reqPutSlot;
+       /* Is the request to set the salt? */
+       bool reqSetSalt;
+       /* Is the request to get the salt? */
+       bool reqGetSalt;
+};
+#endif
diff --git a/version2/doc/iotcloud.tex b/version2/doc/iotcloud.tex
deleted file mode 100644 (file)
index 1d760d7..0000000
+++ /dev/null
@@ -1,1860 +0,0 @@
-\documentclass[11pt]{article}\r
-\newcommand{\tuple}[1]{\ensuremath \langle #1 \rangle}\r
-\usepackage{color}\r
-\usepackage{amsthm}\r
-\usepackage{amsmath}\r
-\usepackage{graphicx}\r
-\usepackage{mathrsfs}\r
-\usepackage{amssymb}\r
-\usepackage{algpseudocode}% http://ctan.org/pkg/algorithmicx\r
-\usepackage[all]{xy}\r
-\usepackage{varwidth}\r
-\r
-\newtheorem{theorem}{Theorem}\r
-\newtheorem{prop}{Proposition}\r
-\newtheorem{lem}{Lemma}\r
-\newtheorem{defn}{Definition}\r
-\newcommand{\note}[1]{{\color{red} \bf [[#1]]}}\r
-\newcommand{\push}[1][1]{\hskip\dimexpr #1\algorithmicindent\relax}\r
-\newcommand*\xor{\mathbin{\oplus}}\r
-\algnewcommand{\LeftComment}[1]{\Statex \(\triangleright\) #1}\r
-\begin{document}\r
-\r
-\r
-\setlength\parindent{0pt} % Removes all indentation from paragraphs - comment this line for an assignment with lots of text\r
-\r
-\r
-\section{\textbf{Introduction}}\r
-\r
-\r
-\section{Approach}\r
-\r
-\subsection{Keys}\r
-\r
-Each device has: user id + password\r
-\r
-Server login is:\r
-hash1(user id), hash1(password)\r
-\r
-Symmetric Crypto keys is:\r
-hash2(user id | password)\r
-\r
-Server has finite length queue of entries + max\_entry\_identifier +\r
-server login key\r
-\r
-\subsection{Entry layout}\r
-Each entry has:\r
-\begin{enumerate}\r
-\item Sequence identifier\r
-\item Random IV (if needed by crypto algorithm)\r
-\item Encrypted payload\r
-\end{enumerate}\r
-\r
-Payload has:\r
-\begin{enumerate}\r
-\item Sequence identifier\r
-\item Machine id (most probably something like a 64-bit random number \r
-that is self-generated by client)\r
-\item HMAC of previous slot\r
-\item Data entries\r
-\item HMAC of current slot\r
-\end{enumerate}\r
-\r
-A data entry can be one of these:\r
-\begin{enumerate}\r
-    \item A transaction:\r
-        \begin{itemize}\r
-            \item Contains a sequence number, a set of key value pair updates and a guard condition that can be evaluated.\r
-            \item Must have the same arbitrator for all its key value pair updates and reads within the guard condition\r
-        \end{itemize}\r
-    \r
-    \item A Commit\r
-        \newline{Commits a transaction into the block chain.  Until a transaction is committed, no client can be sure if that transaction's key value updates will be used to update the state of the system.  Once an arbitrator commits a transaction then that transaction becomes a permanent state change in the system.  Transactions should be committed and aborted in order of their sequence numbers.}\r
-    \r
-    \item An Abort\r
-        \newline{An abort is used to show that a transactions key value update should not be used in the state change of the system.  This occurs when the guard of a transaction evaluates to false meaning that the conditions under-which this transaction should be committed no longer exists in the system (another transaction could have been committed first that would have changed the system in a way that makes the current transaction invalid).}\r
-    \r
-    \item New Key:\r
-        \newline{This creates a new key and assignes an arbitrator to that key.  Only the first new key message for a given key is valid.  Once a new key message is inserted into the block chain it is never removed and no other new key entries for the same key name can be inserted into the block chain.}\r
-        \r
-    \item Slot sequence entry: Machine id + last message identifier \r
-        \newline {The purpose of this is to keep the record of the last slot from a certain client if a client's update has to expunge that other client's last entry from the queue. This is kept in the slot until the entry owner inserts a newer update into the queue.}\r
-\r
-    \item Queue state entry: Includes queue size \r
-        \newline {The purpose of this is for the client to tell if the server lies about the number of slots in the queue, e.g. if there are 2 queue state entry in the queue, e.g. 50 and 70, the client knows that when it sees 50, it should expect at most 50 slots in the queue and after it sees 70, it should expect 50 slots before that queue state entry slot 50 and at most 70 slots. The queue state entry slot 70 is counted as slot number 51 in the queue.}\r
-\r
-    \item Collision resolution entry: message identifier + machine id of a collision winner\r
-        \newline {The purpose of this is to keep keep track of the winner of all the collisions until all clients have seen the particular entry.}\r
-\end{enumerate}\r
-\r
-\subsection{Live status}\r
-\r
-Live status of entries:\r
-\begin{enumerate}\r
-    \item Transaction is live if it has not been committed or aborted yet.\r
-    \r
-    \item Abort is live until the machine ID that created the transaction that is being aborted inserts into the block chain a message with a sequence number greater than the abort (that client sees the abort).\r
-        \r
-    \item Commit is dead if for all key value updates in the commit there is a commit with the same key value update that is newer (larger sequence number).  The committing client (arbitrator) will see those newer commits since it is the one that generates them.\r
-    \r
-    \item New Key messages are always kept alive.  Keys can not be deleted.  Deleted keys will cause arbitration to fail if a key is deleted then reassigned to a new client device for arbitration.\r
-    \r
-    \item Slot sequence number (of either a message version data or user-level data) is dead if there is a newer slot from the same machine.\r
-\r
-    \item Queue state entry is dead if there is a newer queue state entry.\r
-    {In the case of queue state entries 50 and 70, this means that queue state entry 50 is dead and 70 is live. However, not until the number of slots reaches 70 that queue state entry 50 will be expunged from the queue.  Further all entries before the 50 entry will also not be expunged until the queue size has reached 70}\r
-\r
-    \item Collision resolution entry is dead if this entry has been seen by all clients after a collision happens.\r
-\end{enumerate}\r
-\r
-When data is at the end of the queue ready to expunge, if:\r
-\begin{enumerate}\r
-    \item If any entry is not dead it must be reinserted into the queue.\r
-\r
-    \item If the slot sequence number is not dead, then a message sequence entry must be inserted.\r
-\end{enumerate}\r
-\r
-\paragraph{Validation procedure on client:}\r
-\begin{enumerate}\r
-    \item Decrypt each new slot in order.\r
-    \item For each slot:\r
-        (a) check its HMAC, and\r
-        (b) check that the previous entry HMAC field matches the previous entry (in case of a gap do not check for slots on gap margins).\r
-    \item That no slots are slots we have seen before (server trying to pass old slots).    \r
-    \r
-    \item For all other machines, check that the latest sequence number is at least as large (never goes backwards).\r
-    \r
-    \item That the queue has a current queue state entry.\r
-    \r
-    \item That the number of entries received is consistent with the size specified in the queue state entry and/or the queue is growing in size.\r
-\end{enumerate}\r
-\r
-\subsection{Resizing Queue}\r
-Client can make a request to resize the queue. This is done as a write that combines:\r
-  (a) a slot with the message, and (b) a request to the server. The queue can only be expanded, never contracted; attempting to decrease the size of the queue will cause future clients to throw an error.\r
-\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-\subsection{The Arbitrator}\r
-Each key has an arbitrator that makes the final decision when it comes to whether a specific transaction containing that key updates the state of the system or is aborted.  This ensures that clients can make offline updates and then push those updates to the server at a later time.  The arbitrator then tries to merge those updates and if possible will commit them into the current working state of the system.  If not possible then the arbitrator will abort that transaction.  The arbitrator arbitrates on transactions in order of transaction sequence number.\r
-\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\section{Server Algorithm}\r
-$s \in SN$ is a sequence number\\\r
-$sv \in SV$ is a slot's value\\\r
-$slot_s = \tuple{s, sv} \in SL \subseteq SN \times SV$ \\ \\\r
-\textbf{State} \\\r
-\textit{SL = set of live slots on server} \\\r
-\textit{max = maximum number of slots (input only for resize message)} \\\r
-\textit{n = number of slots} \\ \\\r
-\textbf{Helper Function} \\\r
-$MaxSlot(SL_s)= \tuple{s, sv} \mid \tuple{s, sv}\r
-\in SL_s \wedge \forall \tuple{s_s, sv_s} \in SL_s, s \geq s_s$ \\\r
-$MinSlot(SL_s)= \tuple{s, sv} \mid \tuple{s, sv} \r
-\in SL_s \wedge \forall \tuple{s_s, sv_s} \in SL_s, s \leq s_s$ \\\r
-$SeqN(slot_s = \tuple{s, sv})=s$ \\\r
-$SlotVal(slot_s = \tuple{s, sv})=sv$ \\\r
-\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Get Slot:}\\\r
-Returns to the client the slots that have a sequence number that is greater than or equal to the sequence number that is in the requese.\\\r
-\begin{algorithmic}[1]\r
-\Function{GetSlot}{$s_g$}\r
-\State \Return{$\{\tuple{s, sv} \in SL \mid s \geq s_g\}$}\r
-\EndFunction\r
-\end{algorithmic}\end{varwidth}% \r
-}\r
-\r
-\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Get Slot:}\\\r
-Puts a slot in the server memory if the slot has the correct sequence number.  Also resizes the server memory if needed.\\\r
-\begin{algorithmic}[1]\r
-\Function{PutSlot}{$s_p,sv_p,max'$}\r
-\If{$(max' \neq \emptyset)$}  \Comment{Resize}\r
-\State $max \gets max'$\r
-\EndIf\r
-\State $\tuple{s_n,sv_n} \gets MaxSlot(SL)$\Comment{Last sv}\r
-%\State $s_n \gets SeqN(\tuple{s_n,sv_n})$\r
-\If{$(s_p = s_n + 1)$}\r
-    \If{$n = max$}\r
-        \State $\tuple{s_m,sv_m} \gets MinSlot(SL)$\Comment{First sv}\r
-        \State $SL \gets SL - \{\tuple{s_m,sv_m}\}$\r
-    \Else \Comment{$n < max$}\r
-        \State $n \gets n + 1$\r
-    \EndIf\r
-    \State $SL \gets SL \cup \{\tuple{s_p,sv_p}\}$\r
-    \State \Return{$(true,\emptyset)$}\r
-\Else\r
-    \State \Return{$(false,\{\tuple{s,sv}\in SL \mid \r
-    s \geq s_p\})$}\r
-\EndIf\r
-\EndFunction\r
-\end{algorithmic}\end{varwidth}% \r
-}\r
-\r
-\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\section{\textbf{Client}}\r
-\r
-\subsection{\textbf{Client Notation Conventions}}\r
-$k$ is key of entry \\\r
-$v$ is value of entry \\\r
-$size$ is a size (target size of the current block chain) \\\r
-$kv$ is a key-value pair $\tuple{k,v}$ \\\r
-$KV$ is a set of $kv$ \\\r
-$id$ is a machine ID \\\r
-$seq$ is a sequence number \\\r
-$hmac_p$ is the HMAC value of the previous slot \\\r
-$hmac_c$ is the HMAC value of the current slot \\\r
-$Guard$ is a set of$ \tuple{k,v,$logical operator$}$ which can be evaluated to a boolean \\\r
-\r
-$trans$ is a transaction entry , $\tuple{seq, id, KV, Guard}$  \\\r
-$lastmsg$ is a last message entry, $\tuple{seq, id}$ \\\r
-$qstate$ is a queue state entry, $\tuple{size}$ \\\r
-$colres$ is a collision resolution entry, $\tuple{id, seq_{old}, seq_{new}, true \lor false}$ \\\r
-$newkey$ is a new key entry, $\tuple{k, id}$, $id$ is ID of arbitrator \\\r
-$commit$ is a commit transaction entry, $\tuple{seq_{trans},KV}$, id is id of arbitrator \\\r
-$abort$ is an abort transaction entry, $\tuple{seq_{trans},id_{trans}}$ \\\r
-\r
-\r
-$de$ is a data entry that can one of: $trans$, $lastmsg$, $qstate$, $colres$, $newkey$, $commit$, $abort$ \\\r
-$DE$ is a set of all data entries, possibly of different types, in a single message, set of $de$\\\r
-\r
-$slotDat = \tuple{seq,id,DE,hmac_p,hmac_c}$ \\\r
-$slot = \tuple{seq, Encrpt(slotDat)}$\\\r
-\r
-\subsection{\textbf{Client State}}\r
-\r
-\subsubsection{Constants}\r
-$LOCAL\_ID$ = machine ID of this client.\\\r
-$RESIZE\_THRESH\_PERCENT$ = percent of slots that need to have live data to trigger a resize.\\\r
-$RESIZE\_PERCENT$ = percent that we should grow the block chain to.\\\r
-$DATA\_ENTRY\_SET\_MAX\_SIZE$ = max size that a data entry set can have (in bytes).\\\r
-$DEAD\_SLOT\_COUNT$ = number of slots to keep dead if possible at the end of the block chain.\\\r
-$MAX\_RESCUE\_SKIPS$ = number of skips that are allowed when saving data entries.\\\r
-\r
-\subsubsection{Primitive Variables}\r
-$max\_size$ = max size of the block chain\\\r
-\r
-\subsubsection{Sets and Lists}\r
-\r
-$PendingTransQueue$ = Queue of pending transactions that need to be pushed to the block chain, $\tuple{PendingTrans}$\\\r
-$PendingTrans= \tuple{KV, Guard} = \tuple{$set of key value pairs, set of guard conditions$}$.\\\r
-$Arbitrator$ = set of $\tuple{k,id}$ containing the key and its arbitrating device.\\\r
-$LastSlot$ = set of $\tuple{id, seq}$ containing the machine ID and the largest sequence number from that machine ID.\\\r
-$LocalSlots$ = set of slots that are in the clients local buffer (initially $\emptyset$), data is decrypted.\\\r
-$RejectedSlotList$ = ordered list of the sequence numbers of slots that this client tried to insert but were rejected.\\\r
-$CommittedKV$ = set of committed key value pairs (initially $\emptyset$).\\\r
-$SpeculatedKV$ = set of speculated key value pairs (initially $\emptyset$).\r
-\r
-\subsection{Helper Functions}\r
-The following helper functions are needed:\\\r
-\r
-$MaxSlot(SL_s)= \tuple{s, sv} \mid \tuple{s, sv} \in SL_s \wedge \forall \tuple{s_s, sv_s} \in SL_s, s \geq s_s$ \\\r
-$MinSlot(SL_s)= \tuple{s, sv} \mid \tuple{s, sv} \in SL_s \wedge \forall \tuple{s_s, sv_s} \in SL_s, s \leq s_s$ \\\r
-\r
-\r
-% Get Size\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Get Byte Size:}\\\r
-Get the size in bytes of the thing that is passed in.\\\r
-\begin{algorithmic}[1]\r
-\Function{GetSize}{$a$}\r
-    \State \Return{Size in bytes of $a$}\r
-\EndFunction\r
-\end{algorithmic}\end{varwidth}% \r
-}\r
-\r
-% Error\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{ Error:}\\\r
-Prints an error message and halts the execution of the client.\\\r
-\begin{algorithmic}[1]\r
-\Function{Error}{$msg$}\r
-    \State $Print(msg)$\r
-    \State $Halt()$\r
-\EndFunction\r
-\end{algorithmic}\end{varwidth}% \r
-}\r
-\r
-% Get Next Sequence Number\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Get Next Sequence Number:}\\\r
-Get the next sequence number for insertion into the block chain.\\\r
-\begin{algorithmic}[1]\r
-\Function{GetNextSeq}{$k$}\r
-    \LeftComment{Get the largest known sequence number}\r
-    \State $seq_{ret} \gets seq$ such that $\tuple{id, seq}\in LastSlo \land (\forall \tuple{id', seq'} \in LastSlo, seq \geq seq')$\\\r
-    \r
-    \LeftComment{Add one to the largest seq number to generate the new seq number}\r
-    \State \Return{$seq_{ret} + 1$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Get Arbitrator\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Get Arbitrator:}\\\r
-Get the arbitrator for a given key.\\\r
-\begin{algorithmic}[1]\r
-\Function{GetArbitrator}{$k$}\r
-    \State $\tuple{k_1,id_1} \gets \tuple{k_2,id_2} $ \textit{such that} $ \tuple{k_2,id_2} \in Arbitrator \land k_2=k$\r
-    \State \Return{$id_1$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Get Arbitrator KV\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Get Arbitrator for KV Set:}\\\r
-Get the arbitrator for a given key value set.\\\r
-\begin{algorithmic}[1]\r
-\Function{GetArbitratorKV}{$KV$}\r
-    \State $\tuple{k,v} \gets \tuple{k',v'}$ such that $\tuple{k',v'} \in KV$\r
-    \State $\tuple{k_1,id_1} \gets \tuple{k_2,id_2} $ \textit{such that} $ \tuple{k_2,id_2} \in Arbitrator \land k_2=k$\r
-    \State \Return{$id_1$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Check Transaction arbitrator\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Check Arbitrator for a Transaction:}\\\r
-Check that the arbitrators for a given set are all the same arbitrator.\\\r
-\begin{algorithmic}[1]\r
-\Function{CheckArbitrator}{$PendingTrans_a$}\r
-    \State $id_{arb} \gets NULL$\\\r
-    \State $\tuple{KV_a, Guard_a} \gets PendingTrans_a$\r
-    \r
-    \ForAll{$\tuple{k',v'} \in KV_a$}\r
-        \State $id' \gets$ \Call{GetArbitrator}{$k'$}\\\r
-        \r
-        \If{$id_{arb} = NULL$}  \r
-            \State $id_{arb} \gets id'$\r
-        \ElsIf{$id' \neq id_{arb}$} \Comment{Check all arbitrators are the same}\r
-            \State \Call{Error}{"Multiple arbitrators for key values in transaction."}\r
-        \EndIf\r
-    \EndFor\r
-    \r
-    \ForAll{$\tuple{k',v', lop'} \in Guard_a$}\r
-        \State $id' \gets$ \Call{GetArbitrator}{$k'$}\\\r
-        \r
-        \If{$id_{arb} = NULL$}  \r
-            \State $id_{arb} \gets id'$\r
-        \ElsIf{$id' \neq id_{arb}$} \Comment{Check all arbitrators are the same}\r
-            \State \Call{Error}{"Multiple arbitrators for key values in transaction."}\r
-        \EndIf\r
-    \EndFor\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Get all Commits\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Get all Commits:}\\\r
-Get all commits that are currently in the local block chain.  Iterate over all the local slots and extract all the commits from each slot.\\\r
-\begin{algorithmic}[1]\r
-\Function{GetCommits}{$ $}\r
-    \State $ComSet \gets \emptyset$ \Comment{Set of the commits}\\\r
-        \r
-    \LeftComment{Iterate over all the slots saved locally}\r
-    \ForAll{$\tuple{s_1', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \in LocalSlots$}\r
-        \State $ComSet \gets ComSet \cup \{c |c \in DE',c$is a $commit\}$\r
-    \EndFor\r
-    \State \Return{$ComSet$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Get all Transactions\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Get all Transactions:}\\\r
-Get all transactions that are currently in the local block chain.  Iterate over all the local slots and extract all the transactions from each slot.\\\r
-\begin{algorithmic}[1]\r
-\Function{GetTrans}{$ $}\r
-    \State $TransSet \gets \emptyset$ \Comment{Set of the trans}\\\r
-        \r
-    \LeftComment{Iterate over all the slots saved locally}\r
-    \ForAll{$\tuple{s_1', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \in LocalSlots$}\r
-        \State $TransSet \gets TransSet \cup \{c |c \in DE',c$is a $trans\}$\r
-    \EndFor\r
-    \State \Return{$TransSet$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Get all aborts\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Get all aborts:}\\\r
-Get all aborts that are currently in the local block chain.  Iterate over all the local slots and extract all the aborts from each slot.\\\r
-\begin{algorithmic}[1]\r
-\Function{GetAborts}{$ $}\r
-    \State $AbrtSet \gets \emptyset$ \Comment{Set of the aborts}\\\r
-        \r
-    \LeftComment{Iterate over all the slots saved locally}\r
-    \ForAll{$\tuple{s_1', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \in LocalSlots$}\r
-        \State $AbrtSet \gets AbrtSet \cup \{c |c \in DE',c$is a $abort\}$\r
-    \EndFor\r
-    \State \Return{$AbrtSet$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Get all Queue States\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Get all queue states:}\\\r
-Get all qstates that are currently in the local block chain.  Iterate over all the local slots and extract all the qstates from each slot.\\\r
-\begin{algorithmic}[1]\r
-\Function{GetQStates}{$ $}\r
-    \State $QSet \gets \emptyset$ \Comment{Set of the qstates}\\\r
-        \r
-    \LeftComment{Iterate over all the slots saved locally}\r
-    \ForAll{$\tuple{s_1', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \in LocalSlots$}\r
-        \State $QSet \gets QSet \cup \{c |c \in DE',c$is a $qstate\}$\r
-    \EndFor\r
-    \State \Return{$QSet$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Get all Last Messages States\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Get all last message data entrues:}\\\r
-Get all last msg that are currently in the local block chain.  Iterate over all the local slots and extract all the last msg from each slot.\\\r
-\begin{algorithmic}[1]\r
-\Function{GetLastMsg}{$ $}\r
-    \State $LMSet \gets \emptyset$ \Comment{Set of the last msg}\\\r
-        \r
-    \LeftComment{Iterate over all the slots saved locally}\r
-    \ForAll{$\tuple{s_1', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \in LocalSlots$}\r
-        \State $LMSet \gets LMSet \cup \{c |c \in DE',c$is a $lastmsg\}$\r
-    \EndFor\r
-    \State \Return{$LMSet$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Check Queue State Live\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Check Queue State Live:}\\\r
-A queue state is dead if there is another queue state data entry that has a larger queue state.\\\r
-\begin{algorithmic}[1]\r
-\Function{CheckQStateLive}{$qstate_a$}\r
-    \State $\tuple{size_a} \gets qstate_a$\r
-    \State $AllQStates \gets$ \Call{GetQState}{} \Comment{Get all the qstates} \\\r
-    \r
-    \If{$\exists \tuple{size'} \in AllQStates, size' > size_a$}\r
-        \State \Return{false}\r
-    \EndIf\r
-    \State \Return{true}\r
-    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Check Commit Live\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Check Commit Live:}\\\r
-A commit is dead if for every key value pair in the commit there is a commit with a larger transaction sequence number that has a key value pair with the same key.\\\r
-\begin{algorithmic}[1]\r
-\Function{CheckCommitLive}{$commit_a$}\r
-    \State $\tuple{seq_{a_{trans}},KV_a} \gets commit_a$\r
-    \State $KSet \gets \{k|\tuple{k,v} \in KV\}$\r
-    \State $AllCommits \gets$ \Call{GetCommits}{} \Comment{Get all the commits} \\\r
-    \r
-    \LeftComment{Iterate all commits that are newer in time}\r
-    \ForAll{$\tuple{seq_{trans}',KV'}\in AllCommits, seq_{trans}' > seq_{a_{trans}}$}\r
-        \State $KVSet \gets KVSet \setminus \{k|\tuple{k,v} \in KV'\}$\\\r
-        \r
-        \If{$KVSet = \emptyset$}\r
-            \State \Return{false} \Comment{All keys have a newer commit}\r
-        \EndIf\r
-    \EndFor\r
-    \State \Return{true} \Comment{If got here then some keys still live}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Check Last Message Live\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Check Last Message Live:}\\\r
-The last message is dead if the device in question pushed a slot that has a larger sequence number than the one recorded in the last message data entry. \\\r
-\begin{algorithmic}[1]\r
-\Function{CheckLastMsgLive}{$lastmsg_a$}\r
-    \State $\tuple{seq_a, id_a} \gets lastmsg_a$\\\r
-    \r
-    \If{$\exists \tuple{id', seq'} \in LastSlot, id'=id_a \land seq' > seq_a$}\r
-        \State \Return{false}\r
-    \EndIf\r
-    \State \Return{True}    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-%Check Collision Resolution Live\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Check Collision Resolution Live:}\\\r
-Check if a collision resolution data entry is live or not.  This done by checking if all clients that we know about have seen the collision resolution entry.  This is checked by seeing if all devices have inserted a message with a larger sequence number into the block chain.\\\r
-\begin{algorithmic}[1]\r
-\Function{CheckColResLive}{$colres_a$}\r
-    \State $\tuple{id_a, seq_{a_{old}}, seq_{a_{new}}, equal_a} \gets colres_a$\\\r
-    \r
-    \If{$\forall \tuple{id', seq'} \in LastSlot, seq' \geq seq_{a_{new}}$}\r
-        \State \Return{false}\r
-    \EndIf\r
-    \State \Return{true}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Check New Key Live\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Check New Key Live:}\\\r
-A new key data entry is always live.\\\r
-\begin{algorithmic}[1]\r
-\Function{CheckNewkeyLive}{$newkey_a$}\r
-    \State \Return{True}    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Check Abort Live\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Check Abort Live:}\\\r
-Check if an abort data entry is live or not.  Abort is dead if the device whos transaction was aborted sees the abort.  This is checked by seeing if that device inserted a slot into the block chain which has a sequence numberl that is larger than the aborts sequence number.\\\r
-\begin{algorithmic}[1]\r
-\Function{CheckAbortLive}{$abort_a, seq_a$}\r
-    \State $\tuple{seq_{a_{trans}},id_a} \gets abort_a$\\\r
-    \r
-    \LeftComment{The device whos transaction was aborted saw the abort}\r
-    \If{$\exists \tuple{id', seq'} \in LastSlot, id'=id_a \land seq' > seq_a$}\r
-        \State \Return{false}\r
-    \EndIf\r
-    \State \Return{True}    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Check Transaction Live\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Check Transaction Live:}\\\r
-A transaction is dead if there is an abort for that transaction or if there is a commit for that a transaction that came after this transaction.  Since transactions must be committed in order of there insertion, seeing a transaction that is committed and has a larger sequence number than the transaction in question means that the transaction in question was committed at some point.\\\r
-\begin{algorithmic}[1]\r
-\Function{CheckTransLive}{$trans_a$}\r
-    \State $\tuple{seq_a, id_a, KV_a, Guard_a} \gets trans_a$\r
-    \State $AllCommits \gets$ \Call{GetCommits}{} \Comment{Get all the commits}\r
-    \State $AllAborts \gets$ \Call{GetAborts}{} \Comment{Get all the aborts} \\\r
-    \r
-    \If{$\exists \tuple{seq_{abrt}',seq_{trans}',id'} \in AllAborts, seq_{trans}' = seq_a$}\r
-        \State \Return{false}\r
-    \ElsIf{$\exists \tuple{seq_{trans}',KV'} \in AllCommits, seq_{trans}' \geq seq_a$}\r
-        \State \Return{false}\r
-    \EndIf\r
-    \State \Return{true}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Check Live\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Check Live:}\\\r
-Checks if a data entry is live based on its type.\\\r
-\begin{algorithmic}[1]\r
-\Function{CheckLive}{$datentry, seq$}\r
-    \If{$datentry$ is a $commit$}\r
-        \State \Return{\Call{CheckCommitLive}{$datentry$}}\\r
-    \ElsIf{$datentry$ is a $abort$}\r
-        \State \Return{\Call{CheckAbortLive}{$datentry, seq$}}\\r
-    \ElsIf{$datentry$ is a $trans$}\r
-        \State \Return{\Call{CheckTransLive}{$datentry$}}\\r
-    \ElsIf{$datentry$ is a $lastmsg$}\r
-        \State \Return{\Call{CheckLastMsgLive}{$datentry$}}\\r
-    \ElsIf{$datentry$ is a $colres$}\r
-        \State \Return{\Call{CheckColResLive}{$datentry$}}\\r
-    \ElsIf{$datentry$ is a $qstate$}\r
-        \State \Return{\Call{CheckQStateLive}{$datentry$}}\r
-    \ElsIf{$datentry$ is a $newkey$}\r
-        \State \Return{\Call{CheckNewkeyLive}{$datentry$}}\r
-    \Else\r
-        \State \Call{Error}{"Unknown data entry type."}\r
-    \EndIf\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Slot Has Live\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Slot Has Live:}\\\r
-Check if the slot has any live data entries in it. Do this by looking at all the data entries in the slot and checking if they are live\\\r
-\begin{algorithmic}[1]\r
-\Function{SlotHasLive}{$slot_a$}\r
-    \State $\tuple{s_1, \tuple{seq_2,id,DE,hmac_p,hmac_c}} \in LocalSlots$\r
-    \r
-    \ForAll{$datentry \in DE$}\r
-        \If{\Call{CheckLive}{$datentry, s_1$}} \Comment{an entry is alive}\r
-            \State \Return{true}\r
-        \EndIf\r
-    \EndFor\r
-    \r
-    \State \Return{false} \Comment{All entries were dead}    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Calculate Resize Threshold\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Calculate Resize Threshold:}\\\r
-Calculate a threshold for how many slots need to have live data entries in them for a resize to take place.\\\r
-\begin{algorithmic}[1]\r
-\Function{CalcResizeThresh}{$maxsize$}\r
-    \State \Return{$\left \lfloor {maxsize * RESIZE\_THRESH\_PERCENT} \right \rfloor$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Calculate Block Chain New Size\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Calculate Block Chain New Size:}\\\r
-Calculate the new size of the block chain which we need if we are to resize the data structure.\\\r
-\begin{algorithmic}[1]\r
-\Function{CalcNewSize}{$maxsize$}\r
-    \State \Return{$\left \lceil {maxsize * RESIZE\_THRESH\_PERCENT} \right \rceil$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Should Resize\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Should Resize:}\\\r
-Check if the block should resize based on some metric of how many slots in the block chain are filled with live data. \\\r
-\begin{algorithmic}[1]\r
-\Function{ShouldResize}{$ $}\r
-    \State $LiveSlots \gets \{slot_s|slot_s \in LocalSlots \land $\Call{SlotHasLive}{$slot_s$}$\}$\r
-    \State $resizethreshold \gets $ \Call{CalcResizeThresh}{$max\_size$}\r
-    \State \Return{$|LiveSlots| \geq resizethreshold$} \Comment{If passes threshold then resize}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Create Queue State \r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Create Queue State:}\\\r
-Generate a queue state data entry.\\\r
-\begin{algorithmic}[1]\r
-\Function{CreateQState}{$size_a$}\r
-    \State \Return{$\tuple{size_a}$}    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Create Abort\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Create Abort:}\\\r
-Generate a abort data entry.\\\r
-\begin{algorithmic}[1]\r
-\Function{CreateAbort}{$seq_a, id_a$}\r
-    \State \Return{$\tuple{seq_a, id_a}$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Create Collision\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Create ColRes:}\\\r
-Generate a colres data entry.\\\r
-\begin{algorithmic}[1]\r
-\Function{CreateColRes}{$is_a, seq_{a_{old}}, seq_{a_{new}}, isequal_a$}\r
-    \State \Return{$\tuple{id_a, seq_{a_{old}}, seq_{a_{new}},}isequal_a$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-\r
-% Create Transaction\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Create Transaction:}\\\r
-Generate a transaction data entry.\\\r
-\begin{algorithmic}[1]\r
-\Function{CreateTrans}{$pendingtrans_a, seq_a$}\r
-    \State $\tuple{KV_a, Guard_a} \gets pendingtrans_a$\r
-    \State \Return{$\tuple{seq_a, LOCAL\_ID, KV_a, Guard_a}$}    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Create Commit\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Create Commit:}\\\r
-Generate a commit data entry.\\\r
-\begin{algorithmic}[1]\r
-\Function{CreateCommit}{$seq_a,KV_a$}\r
-    \State \Return{$\tuple{seq_a,KV_a}$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Create New Key\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Create New Key:}\\\r
-Generate a new key data entry.\\\r
-\begin{algorithmic}[1]\r
-\Function{CreateNewKey}{$k_a, id_a$}\r
-    \State \Return{$\tuple{k_a,id_a}$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Data Entry Set Has Space \r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Data Entry Set Has Space :}\\\r
-Checks if a data entry set has enough space for a new data entry to be inserted.\\\r
-\begin{algorithmic}[1]\r
-\Function{DEHasSpace}{$DE_a, de_a$}\r
-    \State $newsize \gets $ \Call{GetSize}{$DE_a$}\r
-    \State $newsize \gets newsize +$ \Call{GetSize}{$de_a$}\r
-    \State \Return{$newsize \leq DATA\_ENTRY\_SET\_MAX\_SIZE$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Create Rescued Commit\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Create Rescued Date Entry:}\\\r
-For commits only the key-value pairs that are most recent (no newer commit that has those key values in it).\\\r
-\begin{algorithmic}[1]\r
-\Function{CreateRescuedCommit}{$commit_a$}\r
-    \State $AllCommits \gets $ \Call{GetCommits}{}\r
-    \State $\tuple{seq_{a_{trans}},KV_a} \gets de_a$\r
-    \State $NewKV \gets KV_a$\\\r
-\r
-    \LeftComment{Get rid of all key values that have newer commits}\r
-    \ForAll{$\tuple{k_a, v_a} \in KV_a$}\r
-        \LeftComment{Iterate over all commits that are newer than the rescue commit}\r
-        \ForAll{$\tuple{seq', KV'} \in AllCommits, seq' > seq_{a_{trans}}$}\r
-            \If{$\exists \tuple{k', v'} \in KV', k' = k_a$}\r
-                \State $NewKV \gets NewKV \setminus \tuple{k_a, v_a}$\r
-                \State Break\r
-            \EndIf\r
-        \EndFor\r
-    \EndFor\r
-    \State \Return{$\tuple{seq_{a_{trans}}, NewKV}$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Create Rescued Date Entry\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Create Rescued Date Entry:}\\\r
-Generate the data entry rescued version of the entry.  For some data entry types such as commits, the entry is not rescued as is.  For commits only the key-value pairs that are most recent (no newer commit that has those key values in it).\\\r
-\begin{algorithmic}[1]\r
-\Function{CreateRescuedEntry}{$de_a$}\r
-\r
-    \If{$de_a$is a $commit$}\r
-        \State \Return{\Call{CreateRescuedCommit}{$de_a$}}\r
-    \EndIf\r
-    \r
-    \State \Return{$de_a$} \Comment{No Modification needed}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Check Slot Hmacs\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Check Slot HMACs:}\\\r
-Check that each slot has not been tampered with by checking that the stored HMAC matches the calculated HMAC.  Also check thatthe slot number reported by the server matches the slot number of the actual slot.\\\r
-\begin{algorithmic}[1]\r
-\Function{CheckSlotsHmacAndSeq}{$Slots_a$}\r
-    \ForAll{$slot_a \in Slots_a$}\r
-        \State $\tuple{seq_{a_1}, \tuple{seq_{a_2},id_a,DE_a,hmac_{a_p},hmac_{a_c}}} \gets slot_a$\r
-        \State $calchmac \gets $ \Call{GenerateHmac}{$seq_{a_2}, id_a, DE_a, hmac_{a_p}$}\r
-    \r
-        \If{$seq_{a_1} \neq seq_{a_2}$}\r
-          \State \Call{Error}{"Slot sequence number mismatch"}\r
-        \ElsIf{$calchmac \neq hmac_{a_c}$}\r
-            \State \Call{Error}{"Slot HMAC mismatch"}\r
-        \EndIf\r
-    \EndFor\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Check HMAC Chain\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Check HMAC Chain:}\\\r
-Check that the HMAC chain has not been violated.\\\r
-\begin{algorithmic}[1]\r
-\Function{CheckHmacChain}{$Slots_a$}\r
-    \State $SlotsList \gets Slots_a$ sorted by sequence number\\  \r
-    \r
-    \r
-    \LeftComment{Check all new slots}\r
-    \ForAll{$index \in [2: |SlotsList|]$}\r
-        \State $\tuple{seq_{a_1}, \tuple{seq_{a_2},id_a,DE_a,hmac_{a_p},hmac_{a_c}}} \gets SlotList[i-1]$\r
-        \State $\tuple{seq_{b_1}, \tuple{seq_{b_2},id_b,DE_b,hmac_{b_p},hmac_{b_c}}} \gets SlotList[i]$\r
-        \r
-        \If{$hmac_{b_p} \neq hmac_{b_c}$}\r
-            \State \Call{Error}{"Invalid previous HMAC."}\r
-        \EndIf    \r
-    \EndFor\\\r
-    \r
-    \LeftComment{Check against slots that we already have in the block chain}\r
-    \If{$|LocalSlots| \neq 0$}\r
-        \State $\tuple{seq, SDE} \gets $\Call{MaxSlot}{$LocalSlots$}\r
-        \State $\tuple{seq{last_2},id_{last},DE_{last},hmac_{last_p},hmac_{last_c}} \gets SDE$\\\r
-        \r
-        \State $\tuple{seq_{a_1}, \tuple{seq_{a_2},id_a,DE_a,hmac_{a_p},hmac_{a_c}}} \gets SlotList[1]$\\\r
-\r
-        \If{$(seq_{last_2} + 1) = seq_{a_1}$}\r
-            \If{$hmac_{a_p} \neq hmac_{last_c}$}\r
-                \State \Call{Error}{"Invalid previous HMAC."}\r
-            \EndIf\r
-        \EndIf\r
-    \EndIf\r
-    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-\r
-% Check For Old Slots\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Check For Old Slots:}\\\r
-Check if the slots are not new.  Checks if the "new" slots are actually new or if they are older than the most recent slot that we have.\\\r
-\begin{algorithmic}[1]\r
-\Function{CheckOldSlots}{$Slots_a$}\r
-    \State $\tuple{seq_{new}, Dat_{new}} \gets$ \Call{MinSlot }{$Slots_a$} \Comment{Get the oldest new slot}\r
-    \State $\tuple{seq_{local}, Dat_{local}} \gets$ \Call{MaxSlot }{$LocalSlots$} \Comment{Get the newest slot seen}\\\r
-    \r
-    \If{$seq_{new} \leq seq_{local}$} \Comment{The slots were not newer than what was already seen}\r
-        \State \Call{Error}{"Server sent old slots."}\r
-    \EndIf\\\r
-    \r
-    \LeftComment{Check if slots have the same sequence number but different data entries}\r
-    \ForAll{$\tuple{seq, Dat} \in Slots_a$}\r
-        \If{$\exists \tuple{seq', Dat'} \in (LocalSlots \cup Slots_a), seq'=seq \land Dat' \neq Dat$}\r
-            \State \Call{Error}{"Slot sequence number match but data does not"}\r
-        \EndIf\r
-    \EndFor\r
-    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Get All Queue States with Sequence numbers\r
-% \noindent\fbox{%\r
-% \begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-% \textbf{Get All Queue States with Sequence numbers:}\\\r
-% Gets all the queue states with the sequence number of the slot that the queue state was inside.\r
-% \begin{algorithmic}[1]\r
-% \Function{GetQStateWithSeq}{$Slots_a$}\r
-%     \State $QSet \gets \emptyset$\\\r
-    \r
-%     \ForAll{$\tuple{seq_1', \tuple{seq_2',id',DE',hmac_p', hmac_c'}} \in Slots_a$}\r
-%         \ForAll{$de' \in DE'$}\r
-%             \If{$de'$ is a  $qstate$}\r
-%                 \State $QSet \gets QSet \cup \{\tuple{seq_1', de'}\}$\r
-%             \EndIf\r
-%         \EndFor\r
-%     \EndFor\\\r
-    \r
-%     \State \Return{$QSet$}\r
-% \EndFunction\r
-% \end{algorithmic}\r
-% \end{varwidth}% \r
-% }\r
-\r
-% Get All Queue States\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Get All Queue States:}\\\r
-Gets all the queue states from the slots that were passed in.\\\r
-\begin{algorithmic}[1]\r
-\Function{GetQState}{$Slots_a$}\r
-    \State $QSet \gets \emptyset$\\\r
-    \r
-    \ForAll{$\tuple{seq_1', \tuple{seq_2',id',DE',hmac_p', hmac_c'}} \in Slots_a$}\r
-        \ForAll{$de' \in DE'$}\r
-            \If{$de'$ is a  $qstate$}\r
-                \State $QSet \gets QSet \cup \{de'\}$\r
-            \EndIf\r
-        \EndFor\r
-    \EndFor\\\r
-    \r
-    \State \Return{$QSet$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-\r
-% Check Size With Gap\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Check Size With Gap:}\\\r
-Checks that the block chain size is correct when there is a gap in the block chain.  This check makes sure that the server is not hiding any information from the client.  If there is a gap and there is only 1 queue state in the new slot entries then there must have at least that many slots since the old slot entry must have been purged.  If there is more than 1 queue state then the block chain is still growing check the smallest max size and there should be at least that many slots. \\\r
-\begin{algorithmic}[1]\r
-\Function{CheckSizeWithGap}{$Slots_a$}    \r
-    %\State $QSSet \gets $ \Call{GetQStateWithSeq}{$Slots_a$}\r
-    %\State $\tuple{seq_{max}, size_{max}} \gets \tuple{seq, size}$ such that $\tuple{seq, size} \in QSSet \land \forall \tuple{seq', size'} \in QSSet, size \geq size'$ \Comment{Get largest size}\r
-    %\State $\tuple{seq_{min}, size_{min}} \gets \tuple{seq, size}$ such that $\tuple{seq, size} \in QSSet \land \forall \tuple{seq', size'} \in QSSet , size \leq size'$ \Comment{Get smallest size}\r
-    \r
-    \State $QSet \gets $ \Call{GetQState}{$Slots_a$}\r
-    \State $size_{max} \gets size$ such that $size \in QSet \land \forall size' \in QSet, size \geq size'$ \r
-    \State $size_{min} \gets size$ such that $size \in QSet \land \forall size' \in QSet, size \leq size'$     \r
-    \State $Slots_{oldmax} \gets \emptyset$\\\r
-\r
-    \r
-    \LeftComment{If only 1 max size then we must have all the slots for that size}\r
-    \If{$(|QSSet| = 1) \land (|Slots_a| \neq size_{max})$}\r
-        \State \Call{Error}{"Missing Slots"}\r
-    \EndIf\\\r
-    \r
-    \LeftComment{We definitely have all the slots}\r
-    \If$|Slots_a| = size_{max}$\r
-        \State \Return{} \Comment{We have all the slots}\r
-    \EndIf\\\r
-    \r
-    \LeftComment{We must have at least this many slots}\r
-    \If$|Slots_a| < size_{min}$\r
-        \State \Call{Error}{"Missing Slots"}\r
-    \EndIf\\\r
-\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Check Size\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Check Size:}\\\r
-\begin{algorithmic}[1]\r
-\Function{CheckSize}{$Slots_a$}    \r
-    \State $\tuple{seq_{old_{max}}, Dat_{old_{max}}} \gets $ \Call{MaxSlot}{$LocalSlots$}\r
-    \State $\tuple{seq_{new_{max}}, Dat_{new_{max}}} \gets $ \Call{MinSlot}{$Slots_a$}\\\r
-    \r
-    \If{$(seq_{old_{max}} + 1) = seq_{new_{max}}$}\r
-        \LeftComment{No Gap so cannot say anything about the size}\r
-        \State \Return{} \r
-    \Else \r
-        \LeftComment{Has a gap so we need to do checks}\r
-        \State \Call{CheckSizeWithGap}{$Slots_a$}\r
-    \EndIf\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-\r
-% % Initialize the expected size of the block chain\r
-% \noindent\fbox{%\r
-% \begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-% \textbf{Initialize the expected size of the block chain:}\\\r
-% Initialize the expected size of the block chain based on the size at the server.\\\r
-% \begin{algorithmic}[1]\r
-% \Function{InitExpSize}{$seq_a$}\r
-%     \State $startingsize \gets 0$\\\r
-\r
-%     \If{$seq_a < max\_size$} \Comment{Check whether saves slots are full on server}\r
-%         \State $startingsize \gets seq_a$\r
-%     \Else\r
-%         \State $startingsize \gets max\_size$\r
-%     \EndIf\\\r
-    \r
-%     \State \Return{$startingsize$}\r
-% \EndFunction\r
-% \end{algorithmic}\r
-% \end{varwidth}% \r
-% }\r
-\r
-% % Update the expected size of the block chain\r
-% \noindent\fbox{%\r
-% \begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-% \textbf{Update the expected size of the block chain:}\\\r
-% Update the expected size of the block chain.\\\r
-% \begin{algorithmic}[1]\r
-% \Function{UpdateExpSize}{$size_a$}\r
-%     \State $size_a \gets size_a + 1$\\\r
-    \r
-%     \If{$size_a > max\_size$}\Comment{Expected size $\leq max\_size$}\r
-%         \State $ssize_a \gets max_\_size$\r
-%     \EndIf\\\r
-    \r
-%     \State \Return{$size_a$}\r
-% \EndFunction\r
-% \end{algorithmic}\r
-% \end{varwidth}% \r
-% }\r
-\r
-\r
-\r
-% Update Last Message\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Process Commit Data Entry:}\\\r
-Process a commit entry.  Updates the local copy of commits.\\\r
-\begin{algorithmic}[1]\r
-\Function{UpdateLastMessage}{$seq_a, id_a, LstSlt_a, updateinglocal_a$}\r
-    \State $\tuple{id_{old}, seq_{old}} \gets \tuple{id', seq'}$ such that $\tuple{id', seq'} \in LastSlot \land id'=id$\\\r
-    \r
-    \If{$id_a = LOCAL\_ID$}\r
-        \If{$\lnot updateinglocal_a \land (seq_a \neq seq_{old})$}\r
-            \LeftComment{This client did not make any updates so its latest sequence number should not change}\r
-            \State \Call{Error}{"Mismatch on local machine sequence number"}\r
-        \EndIf\r
-    \Else\r
-        \If{$seq_{old} > seq_a$}\r
-            \State \Call{Error}{"Rollback on remote machine sequence number"}\r
-        \EndIf\r
-    \EndIf\\\r
-    \r
-    \State $LastSlot \gets LastSlot \setminus \{\tuple{id, seq} | \tuple{id, seq} \in LastSlot, id=id_a\}$\r
-    \State $LastSlot \gets LastSlot \cup \{\tuple{id_a, seq_a}\}$\r
-    \r
-    \State \Return{$LstSlt_a \setminus \{\tuple{id, seq} | \tuple{id, seq} \in LstSlt_a, id=id_a\}$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Process Commit Data Entry\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Process Commit Data Entry:}\\\r
-Process a commit entry.  Updates the local copy of commits.\\\r
-\begin{algorithmic}[1]\r
-\Function{ProcessCommit}{$commit_a$}\r
-    \State $\tuple{seq_{a_{trans}},KV_a} \gets commit_a$\r
-    \State $DKV \gets \{\tuple{k,v}| \tuple{k,v} \in CommittedKV \land \tuple{k',v'}\in KV_a \land k'=k\}$\r
-    \State $CommittedKV \gets (CommittedKV \setminus DKV) \cup KV_a$\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Process Queue State Data Entry\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Process Queue State Entry:}\\\r
-Process a queue state entry. Updates the max size of the block chain\\\r
-\begin{algorithmic}[1]\r
-\Function{ProcessQState}{$qstate_a$}\r
-    \State $\tuple{size_a} \gets qstate_a$\r
-    \State $max\_size \gets size_a$ \Comment{Update the max size we can have}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Process Collision Resolution Entry\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Process Queue State Entry:}\\\r
-Process a collision resolution entry.\\\r
-\begin{algorithmic}[1]\r
-\Function{ProcessColres}{$colres_a, NewSlots_a$}\r
-    \State $\tuple{id_a, seq_{a_{old}}, seq_{a_{new}}, isequal_a}$\r
-    \State $AllSlots \gets LocalSlots \cup NewSlots_a$\r
-    \State $index \gets seq_{a_{old}}$\\\r
-    \r
-    \While{$index <= seq_{a_{new}}$}\r
-        \State $slt \gets \tuple{seq' Dat'}$ such that $\tuple{seq' Dat'} \in AllSlots \land seq'=index$\r
-        \r
-        \If{$\exists \tuple{seq' Dat'} \in AllSlots, seq' = index$}\r
-            \State $\tuple{seq, Dat} \gets \tuple{seq' Dat'}$ such that $\tuple{seq' Dat'} \in AllSlots \land seq'=index$\r
-            \State $\tuple{seq,id,DE,hmac_p,hmac_c} \gets Dat$\r
-            \If{$isequal_a \neq (id=id_a)$}\r
-                \State \Call{Error}{"Trying to insert rejected messages for slot"}\r
-            \EndIf\r
-        \EndIf\\\r
-        \State $index \gets index + 1$\r
-    \EndWhile\r
-    \r
-    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Process New Key Data Entry\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Process New Key Entry:}\\\r
-Process a queue state entry. Adds a key to the key arbitrator set\\\r
-\begin{algorithmic}[1]\r
-\Function{ProcessNewkey}{$newkey_a$}\r
-    \State $\tuple{seq_a, k_a, id_a} \gets newkey_a$\r
-    \State $Arbitrator \gets Arbitrator \cup \{\tuple{k_a,id_a}\}$\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Process Process Data Entry\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Process Data Entry:}\\\r
-Process the data entry based on what kind of entry it is.\\\r
-\begin{algorithmic}[1]\r
-\Function{ProcessDatEntry}{$slot_a, NewSlots_a,LstSlt_a$}\r
-    \If{$datentry_a$ is a $commit$}\r
-        \State \Call{ProcessCommit}{$dataentry_a$}\r
-        \r
-    \ElsIf{$datentry_a$ is a $abort$}\r
-        \LeftComment{Do Nothing in this case}\r
-        \r
-    \ElsIf{$datentry_a$ is a $trans$}\r
-        \LeftComment{Do Nothing in this case}\r
-    \r
-    \ElsIf{$datentry_a$ is a $lastmsg$}\r
-        \State $\tuple{seq_a, id_a} \gets dataentry_a$\r
-        \State $LstSlt_a \gets$ \Call{UpdateLastMessage}{$seq_a, id_a, LstSlt_a, false$}\r
-    \r
-    \ElsIf{$datentry_a$ is a $colres$}\r
-        \State \Call{ProcessColres}{$dataentry_a, NewSlots_a$}\r
-        \r
-    \ElsIf{$datentry_a$ is a $qstate$}\r
-        \State \Call{ProcessQState}{$dataentry_a$}\r
-        \r
-    \ElsIf{$datentry_a$ is a $newkey$}\r
-        \State \Call{ProcessNewkey}{$dataentry_a$}\r
-        \r
-    \Else\r
-        \State \Call{Error}{"Unknown data entry type."}\r
-    \EndIf\r
-    \r
-    \State \Return{$LstSlt_a$}    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-\r
-% Delete Local Slots\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Delete Local Slots:}\\\r
-Deletes local slots that are deleted at the server.  This keeps the size of the local block chain bounded.\\\r
-\begin{algorithmic}[1]\r
-\Function{DeleteLocalSlots}{$ $}\r
-    \State $\tuple{seq_{max}, Dat_{max}} \gets $ \Call{MaxSlot}{$LocalSlots$}\r
-    \State $seq_{min} \gets seq_{max} - max\_size$ \Comment{Min sequence number we should keep}\r
-    \State $LSDelete \gets \emptyset$\r
-        \r
-    \If{$|LocalSlots| \leq max\_size$}\r
-        \State \Return{} \Comment{Nothing to delete}\r
-    \EndIf\\\r
-    \r
-    \State $LSDelete \gets \{\tuple{seq', Dat'}|\tuple{seq', Dat'} \in LocalSlots, seq' > seq_{min}\}$\r
-    \State $LocalSlots \gets LocalSlots \setminus LSDelete$    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Create Speculative KV\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Create Speculative KV:}\\\r
-Speculates on what the most recent key value pairs will be based on the latest committed key value pairs and the uncommitted transactions.\\\r
-\begin{algorithmic}[1]\r
-\Function{SpeculateKV}{$ $}\r
-    \State $AllTrans \gets$ \Call{GetTrans}{}\r
-    \State $LiveTrans \gets \{t| t\in AllTrans, $\Call{CheckTransLive}{$t$}$\}$\r
-    \State $CurrKV \gets CommittedKV$\r
-    \State $DKV \gets \emptyset$\r
-\r
-    \ForAll{$\tuple{seq_t, id_t, KV_t, Guard_t} \in LiveTrans$ ordered by $seq'$} \r
-        \If{\Call{EvaluateGuard}{$Guard_t, CurrKV$}}\r
-            \State $DKV \gets \{\tuple{k,v}| \tuple{k,v} \in CurrKV \land \tuple{k',v'}\in KV_t \land k'=k\}$\r
-            \State $CurrKV \gets (CurrKV \setminus DKV) \cup KV_t$\r
-        \EndIf\r
-    \EndFor\r
-    \r
-    \State \Return{$CurrKV$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-\r
-% Validate and Update \r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Validate Update:}\\\r
-Validate the block chain and insert into the local block chain.\\\r
-\begin{algorithmic}[1]\r
-\Function{ValidateUpdate}{$NewSlots_a, updatinglocal_a$}\r
-    \State $\tuple{seq_{oldest}, Dat_{oldest}} \gets$ \Call{MinSlot}{$NewSlots_a$}\r
-    \State $\tuple{seq_{newest}, Dat_{newest}} \gets$ \Call{MaxSlot}{$NewSlots_a$}\r
-    \State $\tuple{seq_{local}, Dat_{local}} \gets$ \Call{MaxSlot}{$LocalSlots$}\r
-    \State $LastSlotTmp \gets LastSlot$\\\r
-    %\State $currsize \gets $\Call{InitExpSize}{$seq_{oldest}$}\\\r
-    \r
-    \State \Call{CheckSlotsHmacAndSeq}{$NewSlots_a$} \Comment{Check all the HMACs}\r
-    \State \Call{CheckHmacChain}{$NewSlots_a$} \Comment{Check HMAC Chain} \r
-    \State \Call{CheckOldSlots}{$NewSlots_a$} \Comment{Check if new slots are actually old slots} \r
-    \State \Call{CheckSize}{$NewSlots_a$} \Comment{Check if the size is correct}\\\r
-    \r
-    \ForAll{$slot_a \in NewSlots_a$ in order of sequence number}\r
-        \If{$slot_a \in LocalSlots$} \Comment{Client already has this slot}\r
-            \State $NewSlots_a \gets NewSlots_a \setminus \{slot_a\}$\r
-            \State Continue\r
-        \EndIf\\\r
-    \r
-        \State $\tuple{seq_{a_1}, \tuple{seq_{a_2},id_a,DE_a,hmac_{a_p},hmac_{a_c}}} \gets slot_a$\r
-        \State $LstSlt_a \gets$ \Call{UpdateLastMessage}{$seq_{a_1}, id_a, LstSlt_a, updatinglocal_a$}\\\r
-        \r
-        \ForAll{$de_a \in DE_a$} \Comment{Process each data entry}\r
-            \State $LstSlt_a \gets $ \Call{ProccessDatEntry}{$de_a, NewSlots_a,LstSlt_a$}\r
-        \EndFor\\\r
-    \r
-        %\State $currsize \gets $ \Call{UpdateExpSize}{$currsize$}\\\r
-        \State $LocalSlots \gets LocalSlots \cup \{slot_a\}$ \Comment{Add to local Chain}\r
-    \EndFor\\\r
-    \r
-    \If{$seq_{oldest} > (seq_{local} +1) \land LastSlotTmp \neq \emptyset$}\r
-        \LeftComment{There was a gap so there should be a complete set of information on each previously seen client}\r
-        \State \Call{Error}{"Missing records for machines"}\r
-    \EndIf\\\r
-    \r
-    \State \Call{DeleteLocalSlots}{ } \Comment{Delete old slots from local}\r
-    \State $SpeculatedKV \gets $\Call{SpeculateKV}{ } \Comment{Speculate on what will be latest KV set}\r
-    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Decrypt Validate Insert Slots\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Decrypt Validate Insert Slots:}\\\r
-Decrypts slots, validates (checks for malicious activity) slots and inserts the slots into the local block chain.\\\r
-\begin{algorithmic}[1]\r
-\Function{DecryptValidateInsert}{$NewSlots_a, updatinglocal_a$}\r
-    \State $DecryptedSlots \gets \emptyset$\r
-    \State $DDat \gets NULL$\\\r
-    \r
-    \ForAll{$\tuple{seq', EDat'} \in NewSlots_a$}\r
-        \State $DDat \gets $ \Call{Decrypt}{$EDat'$}\r
-        \State $DecryptedSlots \gets DecryptedSlots \cup \tuple{seq',DDat}$\r
-    \EndFor\\\r
-    \State \Call{ValidateUpdate}{$DecryptedSlots, updatinglocal_a$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Check and Create Last Message Data Entry\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Check and Create Last Message Data Entry:}\\\r
-Check if a last message entry needs to be created for this slot and if so create it.  The check is done by checking if there are any newer slots with the same id or if there is already a last message slot with a newer sequence number\\\r
-\begin{algorithmic}[1]\r
-\Function{CheckCreateLastMsgEntry}{$seq_a, id_a$}\r
-    \State $AllLastMsg \gets$ \Call{GetLastMsg}{}\\\r
-    \r
-    \LeftComment{Already Has one}\r
-    \If{$\exists  \tuple{seq', id'} \in AllLastMsg, id_a=id' \land seq'=seq_a$}\r
-        \State \Return{$\{\}$}\\\r
-    \EndIf\\\r
-    \r
-    \LeftComment{Not latest slot from that client}\r
-    \If{$\exists  \tuple{seq_1', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \in LocalSlots, id_a=id' \land seq_1'>seq_a$}\r
-        \State \Return{$\{\}$}\\\r
-    \EndIf\\\r
-    \r
-    \r
-    \State \Return{$\{\tuple{seq_a, id_a}\}$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Mandatory Rescue\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Mandatory Rescue:}\\\r
-This rescue is mandatory before any types of data entries (excpet queue states) can be placed into the data entry section of the new slot.  Returns the data entry Set or null if the first slot could not be cleared (the live data in that slot could not fit in this current slot). \\\r
-\begin{algorithmic}[1]\r
-\Function{MandatoryRescue}{$DE_a$}\r
-    \State $smallestseq \gets seq$ such that $\tuple{seq, DE}\in LocalSlots \land (\forall \tuple{seq', DE'} \in LocalSlots, seq \leq seq')$\r
-    \State $cseq \gets smallestseq$\\\r
-    \r
-    \LeftComment{Check the least slots to rescue and live entries}\r
-    \While{$cseq < (smallestseq + DEAD\_SLOT\_COUNT)$}\r
-        \State $currentslot \gets s'$ such that $\tuple{s',DE'} \in LocalSlots \land s' = cseq$\r
-        \State $\tuple{seq', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \gets currentslot$\r
-        \State $DE' \gets DE' \cup$ \Call{CheckCreateLastMsgEntry}{$seq', id'$} \Comment{Get the last message too if we need it}\\\r
-        \r
-        \ForAll{$de \in DE'$} \Comment{Iterate over all the entries}\r
-            \If{\Call{CheckLive}{$de, cseq$}} \Comment{data entry is live}\r
-                \State $de \gets $ \Call{CreateRescuedEntry}{de} \Comment{Resize entry if needed}\r
-                \If{\Call{DEHasSpace}{$DE_a, de$}}\r
-                    \State $DE_a \gets DE_a \cup de$ \Comment{Had enough space to add it}\r
-                \ElsIf{$currentseq = smallestseq$}\r
-                    \State \Return{$NULL$}\r
-                \Else\r
-                    \State \Return{$DE_a$}\r
-                \EndIf\r
-            \EndIf\r
-        \EndFor\\\r
-        \r
-        \State $cseq \gets cseq+1$ \Comment{Move onto the next slot}\r
-    \EndWhile\r
-    \r
-    \State \Return{$DE_a$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Optional Rescue\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Optional Rescue:}\\\r
-This rescue is not mandatory.  This is trying to fill the remaining portion of the slot with rescued data so that no space is wasted. If we encounter a data entry that does not fit move on to the next, maybe that one will fit.  Do this until we skipped too many live data entries\\\r
-\begin{algorithmic}[1]\r
-\Function{OptionalRescue}{$DE_a$}\r
-    \State $smallestseq \gets seq$ such that $\tuple{seq, DE}\in LocalSlots \land (\forall \tuple{seq', DE'} \in LocalSlots, seq \leq seq')$\r
-    \State $largestseq \gets seq$ such that $\tuple{seq, DE}\in LocalSlots \land (\forall \tuple{seq', DE'} \in LocalSlots, seq \geq seq')$\r
-\r
-    \State $numofskips \gets 0$\r
-    \State $cseq \gets smallestseq$\\\r
-    \r
-    \LeftComment{Check the least slots to rescue and live entries}\r
-    \While{$cseq < largestseq$}\r
-        \State $currentslot \gets s'$ such that $\tuple{s',DE'} \in LocalSlots \land s' = cseq$\r
-        \State $\tuple{seq', \tuple{seq_2',id',DE',hmac_p',hmac_c'}} \gets currentslot$\\\r
-        \r
-        \ForAll{$de \in DE'$} \Comment{Iterate over all the entries}\r
-            \If{\Call{CheckLive}{$de, cseq$}} \Comment{data entry is live}\r
-                \State $de \gets $ \Call{CreateRescuedEntry}{de} \Comment{Resize entry if needed}\\\r
-                \r
-                \If{$de \in DE_a$} \Comment{Already being rescued}\r
-                    \State Continue\r
-                \EndIf\\\r
-                \r
-                \If{\Call{DEHasSpace}{$DE_a, de$}}\r
-                    \State $DE_a \gets DE_a \cup de$ \Comment{Had enoug space to add it}\r
-                \ElsIf{$numofskips \geq MAX\_RESCUE\_SKIPS$}\r
-                    \State \Return{$DE_a$}\r
-                \Else\r
-                    $numofskips \gets numofskips +1$\r
-                \EndIf\r
-            \EndIf\r
-        \EndFor\\\r
-        \r
-        \State $cseq \gets cseq+1$ \Comment{Move onto the next slot}\r
-    \EndWhile\r
-    \r
-    \State \Return{$DE_a$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-\r
-% Rejected Messages\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Rejected Messages:}\\\r
-\begin{algorithmic}[1]\r
-\Function{RejectedMessages}{$DE_a$}\r
-    \State $seq_{old} \gets seq$ such that $\tuple{seq} \in RejectedSlotList \land \forall \tuple{seq'} \in RejectedSlotList, seq \geq seq'$\r
-    \State $prev \gets -1$\\\r
-    \r
-    \r
-    \r
-    \If{$|RejectedSlotList| \geq REJECTED\_THRESH$}\r
-        \State $seq_{new} \gets seq$ such that $\tuple{seq} \in RejectedSlotList \land \forall \tuple{seq'} \in RejectedSlotList, seq \leq seq'$\\\r
-        \State $colres \gets $ \Call{CreateColRes}{$LOCAL\_ID, seq_{old}, seq_{new}, false$}    \r
-        \State \Return{$DE_a \cup \{colres\}$}\r
-    \EndIf\\\r
-    \r
-    \ForAll{$\tuple{seq} \in RejectedSlotList$ sorted by $seq$}\r
-        \If{$\exists \tuple{seq',Dat'} \in LocalSlots$}\r
-            \State Break\r
-        \EndIf\r
-        \State $prev \gets seq$\r
-    \EndFor\\\r
-    \r
-    \If{$prev \neq -1$}\r
-        \State $DE_a \gets DE_a \cup$ \Call{CreateColRes}{$LOCAL\_ID, seq_{old}, prev, false$}\r
-    \EndIf\\\r
-    \r
-    \State $RejectedSlotList \gets \{\tuple{seq}| \tuple{seq} \in RejectedSlotList, seq > prev\}$\\\r
-    \r
-    \ForAll{$\tuple{seq} \in RejectedSlotList$ sorted by $seq$}\r
-        \State $DE_a \gets DE_a \cup$ \Call{CreateColRes}{$LOCAL\_ID, seq,seq, false$}\r
-    \EndFor\\\r
-    \r
-    \State \Return{$DE_a$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-\r
-\r
-% Arbitrate\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Arbitrate:}\\\r
-\begin{algorithmic}[1]\r
-\Function{Arbitrate}{$DE_a$}\r
-    \State $AllCommits \gets$ \Call{GetCommits}{}\r
-    \State $AllTrans \gets$ \Call{GetTrans}{}\r
-    \State $LiveCommits \gets \{c| c\in AllCommits, $\Call{CheckCommitLive}{$c$}$\}$\r
-    \State $LiveTrans \gets \{t| t\in AllTrans, $\Call{CheckTransLive}{$t$}$\}$\r
-    \State $KV \gets \emptyset$\r
-    \State $lastcomseq \gets -1$\r
-    \State $CurrKV \gets \emptyset$\r
-    \State $DKV \gets \emptyset$\r
-    \State $KVTmp \gets \emptyset$\\\r
-    \r
-    \LeftComment{Get all the latest commits}\r
-    \ForAll{$\tuple{seq_{trans}',KV'} \in LiveCommits$}\r
-        \State $CurrKV \gets CurrKV \cup KV'$\r
-    \EndFor\\\r
-    \r
-    \ForAll{$\tuple{seq_t, id_t, KV_t, Guard_t} \in LiveTrans$ ordered by $seq'$} \r
-        \If{\Call{GetArbitratorKV}{$KV_t$} $\neq LOCAL\_ID$}\r
-            \State Continue \Comment{Client not arbitrator for this transaction}\r
-        \EndIf\\\r
-    \r
-        \If{$\lnot$\Call{EvaluateGuard}{$Guard_t, CurrKV$}}\r
-            \State $abortde \gets $\Call{CreateAbort}{$seq_t, id_t$}\r
-            \LeftComment{No more space so we cant arbitrate any further}\r
-            \If($lnot$\Call{DeHasSpace}{$DE_a, abortde$})\r
-                \State \Return{$DE_a$}\r
-            \EndIf\r
-            \State $DE_a \gets DE_a \cup abortde$\r
-        \Else\r
-            \State $DKV \gets \{\tuple{k,v}| \tuple{k,v} \in KV \land \tuple{k',v'}\in KV_t \land k'=k\}$\r
-            \State $KVTmp \gets (KV \setminus DKV) \cup KV'$\r
-            \State $DKV \gets \{\tuple{k,v}| \tuple{k,v} \in CurrKV \land \tuple{k',v'}\in KVTmp \land k'=k\}$\r
-            \State $CurrKV \gets (CurrKV \setminus DKV) \cup KVTmp$\r
-            \State $commitde \gets $ \Call{CreateCommit}{$seq_t,KVTmp$}\r
-            \r
-            \If{$\lnot$ \Call{DeHasSpace}{$DE_a, commitde$}}\r
-                \If{$lastcomseq \neq -1$}\r
-                    \State $DE_a \gets DE_a \cup$ \Call{CreateCommit}{$lastcomseq,KV$}\r
-                \EndIf\r
-                \State \Return{$DE_a$}\r
-            \Else\r
-                \State $KV \gets KVTmp$\r
-                \State $lastcomseq \gets seq_t$\r
-            \EndIf\r
-        \EndIf\r
-    \EndFor\r
-    \r
-    \State $DE_a \gets DE_a \cup$ \Call{CreateCommit}{$lastcomseq,KV$}\r
-    \State \Return{$DE_a$}\r
-\r
-    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Create New Slot\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Create New Slot:}\\\r
-Create a slot and encrypt it.\\\r
-\begin{algorithmic}[1]\r
-\Function{CreateNewSlot}{$seq_a, DE_a$}\r
-    \State $\tuple{seq, SDE} \gets \tuple{seq', SDE'}$ such that $\tuple{seq', SDE'}\in LocalSlots \land (\forall \tuple{seq'', DE''} \in LocalSlots, seq' \geq seq'')$\r
-    \State $\tuple{seq,id,DE,hmac_p,hmac_c} \gets SDE$\\\r
-    \r
-    \State $newhmac \gets $ \Call{GenerateHmac}{$seq_a, LOCAL\_ID, DE_a, hmac_p$}\r
-    \State $newSDE \gets \tuple{seq,LOCAL\_ID,DE_a,hmac_c,newhmac}$\r
-    \State $encryptnewSDE \gets $\Call{Encrypt}{newSDE}\\\r
-    \r
-    \State \Return{$\tuple{seq_a, encryptnewSDE}$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Send Data to Server\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Send Data to Server:}\\\r
-Send the data to the server.  If this fails then new slots will be returned by the server.\\\r
-\begin{algorithmic}[1]\r
-\Function{SendToServer}{$seq_a, DE_a, newsize_a$}\r
-    \LeftComment{Make the slot and try to send to server}\r
-    \State $newslot \gets $ \Call{CreateNewSlot}{$seq_a, DE_a$}\r
-    \State $\tuple{success, newslots} \gets$ \Call{PutSlot}{$seq_a, newslot, newsize_a$}\\\r
-    \r
-    \If{$success$}\r
-        \State $RejectedSlotList \gets \emptyset$\r
-        \State \Return{$\tuple{true, \{newslot\}}$}\r
-    \Else\r
-        \If{$|newslots| = 0$}\r
-            \State \Call{Error}{"Server rejected but did not send any slots"}\r
-        \EndIf\r
-        \State $RejectedSlotList \gets RejectedSlotList \cup \{seq_a\}$\r
-        \State \Return{$\tuple{false, newslots}$}\r
-    \EndIf\\\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-\r
-% Try Insert Transaction\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Try Insert Transaction:}\\\r
-Try to insert a transaction into the block chain. Does resizing, rescues and insertion of other data entry types as needed. \\\r
-\begin{algorithmic}[1]\r
-\Function{TryInsertTransaction}{$pendingtrans_a, forceresize$}\r
-    \State $DE \gets \emptyset$ \Comment{The data entries for this slot}\r
-    \State $seq \gets $ \Call{GetNextSeq}{} \Comment{Get the sequence number for this slot}\r
-    \State $newsize \gets 0$\r
-    \State $trans \gets$ \Call{CreateTrans}{$pendingtrans_a, seq$}\r
-    \State $transinserted \gets false$\r
-    \State $slotstoinsert \gets \emptyset$\\\r
-    \r
-    \State $resize \gets $ \Call{ShouldResize}{ } \Comment{Check if we should resize}\r
-    \State $resize \gets resize \lor forceresize$\r
-    \If{$resize$}\r
-        \State $newsize \gets$ \Call{CalcNewSize}{$max\_size$}\r
-        \State $DE \gets DE \cup \{$\Call{CreateQState}{$newsize$}$\}$\r
-    \EndIf\\\r
-    \r
-    \If{$RejectedSlotList \neq \emptyset$}   \r
-        \State $DE \gets$ \Call{RejectedMessages}{$DE$}\r
-    \EndIf\\\r
-    \r
-    \State $DE \gets$ \Call{MandatoryRescue}{$DE$} \Comment{Round 1 of rescue}\r
-    \If{$DE = NULL$}\r
-        \LeftComment{Data was going to fall off the end so try again with a forced resize}\r
-        \State \Return{\Call{TryInsertTransaction}{$trans_a, true$}}\r
-    \EndIf\\\r
-    \r
-    \State $DE \gets $\Call{Arbitrate}{$DE$}\\\r
-    \r
-    \If{\Call{DEHasSpace}{$DE, trans$}} \Comment{transaction fits}\r
-        \State $DE \gets DE \cup trans$\r
-        \State $transinserted \gets true$\r
-    \EndIf\\\r
-    \r
-    \LeftComment{Rescue data to fill slot data entry section}\r
-    \State $DE \gets$ \Call{OptionalRescue}{$DE$}\\\r
-    \r
-    \LeftComment{Send to server.}\r
-    \State $\tuple{sendsuccess, newslots} \gets $ \Call{SendToServer}{$seq, DE, newsize$}\\\r
-    \r
-    \LeftComment{Insert the slots into the local bloakc chain}\r
-    \State \Call{DecryptValidateInsert}{$newslots, true$}\\\r
-    \r
-    \State \Return{$transinserted \land success$} \Comment{Return if  succeeded or not}\r
-    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-\r
-% Try Insert New Key\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Try Insert New Key:}\\\r
-Try to insert a new key into the block chain. Does resizing, rescues and insertion of other data entry types as needed. \\\r
-\begin{algorithmic}[1]\r
-\Function{TryInsertNewKey}{$k_a, id_a, forceresize$}\r
-    \State $DE \gets \emptyset$ \Comment{The data entries for this slot}\r
-    \State $seq \gets $ \Call{GetNextSeq}{} \Comment{Get the sequence number for this slot}\r
-    \State $newsize \gets 0$\r
-    \r
-    \r
-    \State $newkey \gets$ \Call{CreateNewKey}{$k_a, id_a$}\r
-    \State $newkeyinserted \gets false$\r
-    \State $slotstoinsert \gets \emptyset$\\\r
-    \r
-    \State $resize \gets $ \Call{ShouldResize}{ } \Comment{Check if we should resize}\r
-    \State $resize \gets resize \lor forceresize$\r
-    \If{$resize$}\r
-        \State $newsize \gets$ \Call{CalcNewSize}{$max\_size$}\r
-        \State $DE \gets DE \cup \{$\Call{CreateQState}{$newsize$}$\}$\r
-    \EndIf\\\r
-    \r
-    \If{$RejectedSlotList \neq \emptyset$}   \r
-        \State $DE \gets$ \Call{RejectedMessages}{$DE$}\r
-    \EndIf\\\r
-    \r
-    \State $DE \gets$ \Call{MandatoryRescue}{$DE$} \Comment{Round 1 of rescue}\r
-    \If{$DE = NULL$}\r
-        \LeftComment{Data was going to fall off the end so try again with a forced resize}\r
-        \State \Return{\Call{TryInsertNewKey}{$k_a, id_a, true$}}\r
-    \EndIf\\\r
-    \r
-    \State $DE \gets $\Call{Arbitrate}{$DE$}\\\r
-    \r
-    \If{\Call{DEHasSpace}{$DE, newkey$}} \Comment{new key fits}\r
-        \State $DE \gets DE \cup newkey$\r
-        \State $newkeyinserted \gets true$\r
-    \EndIf\\\r
-    \r
-    \LeftComment{Rescue data to fill slot data entry section}\r
-    \State $DE \gets$ \Call{OptionalRescue}{$DE$}\\\r
-    \r
-    \LeftComment{Send to server.}\r
-    \State $\tuple{sendsuccess, newslots} \gets $ \Call{SendToServer}{$seq, DE, newsize$}\\\r
-    \r
-    \LeftComment{Insert the slots into the local block chain}\r
-    \State \Call{DecryptValidateInsert}{$newslots, true$}\\\r
-    \r
-    \State \Return{$newkeyinserted \land success$} \Comment{Return if  succeeded or not}\r
-    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-\r
-\r
-\subsection{Client Interfaces}\r
-\r
-% Put KV pair\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Put Key Value Pair:}\\\r
-Puts a key value pair into the key value pair buffer\\\r
-\begin{algorithmic}[1]\r
-\Function{PutKeyValue}{$k,v$}\r
-    \State $\tuple{seq, KV, Guard} \gets PendingTrans$\\\r
-    \r
-    \LeftComment{Check if KV already has a key value pair for the specified key}\r
-    \State $DSet \gets \{\tuple{k_1,v_1} | \tuple{k_1,v_1} \in KV \land k_1 = k\}$\\\r
-    \r
-    \If{$DSet \neq \emptyset$}\r
-        \State \Call{Error}{"Value for key already in most recent update"}\r
-    \EndIf\\\r
-        \r
-    \State $KV \gets KV \cup \{\tuple{k,v}\}$ \Comment{Add key value pair}\r
-    \State $PendingTrans \gets \tuple{seq, KV, Guard}$\r
-    \State \Call{CheckArbitrator}{$PendingTrans$} \Comment{Check that the transaction still valid}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Get KV Pair Speculative\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Get KV Pair Speculative:}\\\r
-Get the value for the key while speculating.\\\r
-\begin{algorithmic}[1]\r
-\Function{GetValueSpeculate}{$k_a$}\r
-    %\State $\tuple{k,v} \gets \tuple{k,v}$ \textit{such that} $\tuple{k,v} \in SpeculatedKV \land k = k_a$\r
-    \r
-    \State $\tuple{k,v} \gets \tuple{k,v}$ \textit{such that} $\tuple{k,v} \in SpeculatedKV \land k = k_a$\r
-\State \Return{$v$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Update\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Update}\\\r
-Sync with the server and get all the latest slots.\\\r
-\begin{algorithmic}[1]\r
-\Function{Update}{$ $}\r
-    \State $\tuple{seq, Dat} \gets $ \Call{MaxSlot}{$LocalSlots$}\r
-    \State $NewSlots \gets$ \Call{GetSlots}{$seq$}\r
-    \State \Call{DecryptValidateInsert}{$NewSlots, false$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Get KV Pair Committed\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Get KV Pair Committed:}\\\r
-Get the value for the key which have been committed.\\\r
-\begin{algorithmic}[1]\r
-\Function{GetValueCommit}{$k_a$}\r
-    \State $\tuple{k,v} \gets \tuple{k,v}$ \textit{such that} $\tuple{k,v} \in Committed \land k = k_a$\r
-    \State \Return{$v$}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Put guard condition\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Put Guard:}\\\r
-Puts a guard transaction into the key value update.  A guard is a key value with a logical operator ($lop$).\\\r
-\begin{algorithmic}[1]\r
-\Function{PutGuard}{$k,v, lop$}\r
-    \State $\tuple{seq, KV, Guard} \gets PendingTrans$\\\r
-    \r
-    \If{$\tuple{k,v, lop} \in Guard$}\r
-        \State \Return{} \Comment{Already have guard condition in update}\r
-    \EndIf\\\r
-    \r
-    \State $Guard \gets Guard \cup \{\tuple{k,v,lop}\}$\r
-    \State $PendingTrans \gets \tuple{seq, KV, Guard}$\r
-    \State \Call{CheckArbitrator}{$PendingTrans$} \Comment{Check that the transaction still valid}\r
-\EndFunction    \r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Transaction Start\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{ Transaction Start:}\\\r
-Starts a transaction.  Clears out the key value pair update buffer.\\\r
-\begin{algorithmic}[1]\r
-\Function{TransactionStart}{$ $}\r
-    % \LeftComment{Reset the key value update buffer}\r
-    % \State $KVUpdate \gets \tuple{\emptyset, \emptyset}$\r
-    \State $PendingTrans \gets NULL$\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-% Transaction Commit\r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{ Transaction Commit:}\\\r
-Commits the transaction into the block chain.  Keeps attempting to insert the transaction into the block chain until it succeeds.\\\r
-\begin{algorithmic}[1]\r
-\Function{Transaction Commit}{$ $}\r
-    \State $DKV \gets \emptyset$\r
-    \State $pt \gets NULL$\\\r
-    \r
-    \State $PendingTransQueue.$\Call{push}{$PendingTrans$}\\\r
-        \r
-    \While{\Call{HasConnectionToServer}{ } $\land PendingTransQueue \neq \emptyset$}\r
-        \State $pt \gets PendingTransQueue.$\Call{peak}{ }\\\r
-    \r
-        \If{\Call{TryInsertTransaction}{$pt, false$}}\r
-            \State $PendingTransQueue.$\Call{pop}{ }\r
-        \EndIf\r
-    \EndWhile\\    \r
-    \r
-    \LeftComment{Go Through local pending transactions and speculate}\r
-    \ForAll{$\tuple{KV, Guard} \in PendingTransQueue$}\r
-        \If{\Call{EvaluateGuard}{$Guard, SpeculatedKV$}}\r
-            \State $DKV \gets \{\tuple{k,v}| \tuple{k,v} \in SpeculatedKV \land \tuple{k',v'}\in KV \land k'=k\}$\r
-            \State $SpeculatedKV \gets (SpeculatedKV \setminus DKV) \cup KV$\r
-        \EndIf\r
-    \EndFor\r
-    \r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-\r
-%Create New Key \r
-\noindent\fbox{%\r
-\begin{varwidth}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}\r
-\textbf{Create New Key:}\\\r
-Creates a new key and specifies which machine ID is the arbitrator. If there is already a new key entry in the block chain for this key name then do not insert into the chain, another client got there first. \\\r
-\begin{algorithmic}[1]\r
-\Function{Transaction Commit}{$k_a, id_a$}\r
-    \State $success \gets false$\\\r
-    \While{$\lnot success$}\r
-        \If{$\exists \tuple{k',id'} \in Arbitrator, k' = k_a$}\r
-            \State \Return{$false$} \Comment{Key already created}\r
-        \EndIf\\\r
-    \r
-        \State $success \gets$ \Call{TryInsertNewKey}{$k_a, id_a, false$}\r
-    \EndWhile\r
-    \r
-    \State \Return{$true$} \Comment{If got here then insertion was correct}\r
-\EndFunction\r
-\end{algorithmic}\r
-\end{varwidth}% \r
-}\r
-\r
-\r
-\end{document}\r
diff --git a/version2/doc/makefile b/version2/doc/makefile
deleted file mode 100644 (file)
index cff4a15..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-LATEX := pdflatex -halt-on-error
-
-default:
-       $(LATEX) iotcloud.tex
-
-clean:
-       rm -f *.dvi *.log *.aux *.blg *.bbl *~
-       rm -f iotcloud.ps iotcloud.pdf 
index 327ce336b9a68e358c0d8930616ef66c83c7d78c..62312926192b2fe4ba5b5c3dd6e5f6703bb4d259 100644 (file)
@@ -9,48 +9,88 @@ import java.nio.ByteBuffer;
  */
 
 
  */
 
 
-class Abort extends Entry {
-       private long seqnumtrans;
-       private long machineid;
-       private long transarbitrator;
+class Abort extends Entry{
+       private long transactionClientLocalSequenceNumber = -1;
+       private long transactionSequenceNumber = -1;
+       private long sequenceNumber = -1;
+       private long transactionMachineId = -1;
+       private long transactionArbitrator = -1;
 
 
+       private Pair<Long, Long> abortId = null;
 
 
-       public Abort(Slot slot, long _seqnumtrans,  long _machineid, long _transarbitrator) {
+
+       public Abort(Slot slot, long _transactionClientLocalSequenceNumber, long _transactionSequenceNumber ,  long _transactionMachineId, long _transactionArbitrator) {
+               super(slot);
+               transactionClientLocalSequenceNumber = _transactionClientLocalSequenceNumber;
+               transactionSequenceNumber = _transactionSequenceNumber;
+               transactionMachineId = _transactionMachineId;
+               transactionArbitrator = _transactionArbitrator;
+               abortId = new Pair<Long, Long>(transactionMachineId, transactionClientLocalSequenceNumber);
+       }
+
+       public Abort(Slot slot, long _transactionClientLocalSequenceNumber, long _transactionSequenceNumber, long _sequenceNumber ,  long _transactionMachineId, long _transactionArbitrator) {
                super(slot);
                super(slot);
-               seqnumtrans = _seqnumtrans;
-               machineid = _machineid;
-               transarbitrator = _transarbitrator;
+               transactionClientLocalSequenceNumber = _transactionClientLocalSequenceNumber;
+               transactionSequenceNumber = _transactionSequenceNumber;
+               sequenceNumber = _sequenceNumber;
+               transactionMachineId = _transactionMachineId;
+               transactionArbitrator = _transactionArbitrator;
+               abortId = new Pair<Long, Long>(transactionMachineId, transactionClientLocalSequenceNumber);
+       }
+
+       public Pair<Long, Long> getAbortId() {
+               return abortId;
+       }
+
+       public long getTransactionMachineId() {
+               return transactionMachineId;
+       }
+
+       public long getTransactionSequenceNumber() {
+               return transactionSequenceNumber;
+       }
+
+       public long getTransactionClientLocalSequenceNumber() {
+               return transactionClientLocalSequenceNumber;
+       }
+
+       public void setSlot(Slot s) {
+               parentslot = s;
        }
 
        }
 
-       public long getMachineID() {
-               return machineid;
+       public long getSequenceNumber() {
+               return sequenceNumber;
        }
 
        }
 
-       public long getTransSequenceNumber() {
-               return seqnumtrans;
+       public void setSequenceNumber(long _sequenceNumber) {
+               sequenceNumber = _sequenceNumber;
        }
 
 
        }
 
 
-       public long getTransArbitrator() {
-               return transarbitrator;
+       public long getTransactionArbitrator() {
+               return transactionArbitrator;
        }
 
        static Entry decode(Slot slot, ByteBuffer bb) {
        }
 
        static Entry decode(Slot slot, ByteBuffer bb) {
-               long seqnumtrans = bb.getLong();
-               long machineid = bb.getLong();
-               long transarbitrator = bb.getLong();
-               return new Abort(slot, seqnumtrans,  machineid, transarbitrator);
+               long transactionClientLocalSequenceNumber = bb.getLong();
+               long transactionSequenceNumber = bb.getLong();
+               long sequenceNumber = bb.getLong();
+               long transactionMachineId = bb.getLong();
+               long transactionArbitrator = bb.getLong();
+               return new Abort(slot, transactionClientLocalSequenceNumber, transactionSequenceNumber, sequenceNumber, transactionMachineId, transactionArbitrator);
        }
 
        public void encode(ByteBuffer bb) {
                bb.put(Entry.TypeAbort);
        }
 
        public void encode(ByteBuffer bb) {
                bb.put(Entry.TypeAbort);
-               bb.putLong(seqnumtrans);
-               bb.putLong(machineid);
-               bb.putLong(transarbitrator);
+               bb.putLong(transactionClientLocalSequenceNumber);
+               bb.putLong(transactionSequenceNumber);
+               bb.putLong(sequenceNumber);
+               bb.putLong(transactionMachineId);
+               bb.putLong(transactionArbitrator);
        }
 
        public int getSize() {
        }
 
        public int getSize() {
-               return (3 * Long.BYTES) + Byte.BYTES;
+               return (4 * Long.BYTES) + Byte.BYTES;
        }
 
        public byte getType() {
        }
 
        public byte getType() {
@@ -58,6 +98,6 @@ class Abort extends Entry {
        }
 
        public Entry getCopy(Slot s) {
        }
 
        public Entry getCopy(Slot s) {
-               return new Abort(s, seqnumtrans, machineid, transarbitrator);
+               return new Abort(s, transactionClientLocalSequenceNumber, transactionSequenceNumber, sequenceNumber, transactionMachineId, transactionArbitrator);
        }
 }
\ No newline at end of file
        }
 }
\ No newline at end of file
index 6f548af57889b1f6a927eadba1f0172329d15628..ac499e51b881bfaa23d6e5af1e2049989fea008e 100644 (file)
@@ -1,4 +1,5 @@
 package iotcloud;
 package iotcloud;
+
 import java.io.*;
 import java.net.*;
 import java.util.Arrays;
 import java.io.*;
 import java.net.*;
 import java.util.Arrays;
@@ -15,7 +16,6 @@ import java.security.SecureRandom;
 
 
 class CloudComm {
 
 
 class CloudComm {
-       String hostname;
        String baseurl;
        Cipher encryptCipher;
        Cipher decryptCipher;
        String baseurl;
        Cipher encryptCipher;
        Cipher decryptCipher;
@@ -36,9 +36,8 @@ class CloudComm {
        /**
         * Constructor for actual use. Takes in the url and password.
         */
        /**
         * Constructor for actual use. Takes in the url and password.
         */
-       CloudComm(Table _table, String _hostname, String _baseurl, String _password) {
+       CloudComm(Table _table,  String _baseurl, String _password) {
                this.table = _table;
                this.table = _table;
-               this.hostname = _hostname;
                this.baseurl = _baseurl;
                this.password = _password;
                this.random = new SecureRandom();
                this.baseurl = _baseurl;
                this.password = _password;
                this.random = new SecureRandom();
@@ -111,24 +110,51 @@ class CloudComm {
 
                        salt = saltTmp;
                } catch (Exception e) {
 
                        salt = saltTmp;
                } catch (Exception e) {
-                       throw new ServerException("Failed setting salt");
+                       throw new ServerException("Failed setting salt", ServerException.TypeConnectTimeout);
                }
                initCrypt();
        }
 
                }
                initCrypt();
        }
 
-       private void getSalt() throws Exception {
-               URL url = new URL(baseurl + "?req=getsalt");
-               URLConnection con = url.openConnection();
-               HttpURLConnection http = (HttpURLConnection) con;
-               http.setRequestMethod("POST");
-               http.connect();
-
-               InputStream is = http.getInputStream();
-               DataInputStream dis = new DataInputStream(is);
-               int salt_length = dis.readInt();
-               byte [] tmp = new byte[salt_length];
-               dis.readFully(tmp);
-               salt = tmp;
+       private void getSalt() throws ServerException {
+               URL url = null;
+               URLConnection con = null;
+               HttpURLConnection http = null;
+
+               try {
+                       url = new URL(baseurl + "?req=getsalt");
+               } catch (Exception e) {
+                       e.printStackTrace();
+                       throw new Error("getSlot failed");
+               }
+               try {
+
+                       con = url.openConnection();
+                       http = (HttpURLConnection) con;
+                       http.setRequestMethod("POST");
+                       http.setConnectTimeout(TIMEOUT_MILLIS);
+                       http.setReadTimeout(TIMEOUT_MILLIS);
+                       http.connect();
+               } catch (SocketTimeoutException e) {
+                       throw new ServerException("getSalt failed", ServerException.TypeConnectTimeout);
+               } catch (Exception e) {
+                       e.printStackTrace();
+                       throw new Error("getSlot failed");
+               }
+
+               try {
+                       InputStream is = http.getInputStream();
+                       DataInputStream dis = new DataInputStream(is);
+                       int salt_length = dis.readInt();
+                       byte [] tmp = new byte[salt_length];
+                       dis.readFully(tmp);
+                       salt = tmp;
+               } catch (SocketTimeoutException e) {
+                       throw new ServerException("getSalt failed", ServerException.TypeInputTimeout);
+               } catch (Exception e) {
+                       e.printStackTrace();
+                       throw new Error("getSlot failed");
+               }
+
        }
 
        /*
        }
 
        /*
@@ -136,8 +162,11 @@ class CloudComm {
         * On failure, the server will send slots with newer sequence
         * numbers.
         */
         * On failure, the server will send slots with newer sequence
         * numbers.
         */
-
        Slot[] putSlot(Slot slot, int max) throws ServerException {
        Slot[] putSlot(Slot slot, int max) throws ServerException {
+               URL url = null;
+               URLConnection con = null;
+               HttpURLConnection http = null;
+
                try {
                        if (salt == null) {
                                getSalt();
                try {
                        if (salt == null) {
                                getSalt();
@@ -148,23 +177,30 @@ class CloudComm {
                        byte[] bytes = slot.encode(mac);
                        bytes = encryptCipher.doFinal(bytes);
 
                        byte[] bytes = slot.encode(mac);
                        bytes = encryptCipher.doFinal(bytes);
 
-
-                       URL url = buildRequest(true, sequencenumber, max);
-                       URLConnection con = url.openConnection();
-                       HttpURLConnection http = (HttpURLConnection) con;
+                       url = buildRequest(true, sequencenumber, max);
+                       con = url.openConnection();
+                       http = (HttpURLConnection) con;
 
                        http.setRequestMethod("POST");
                        http.setFixedLengthStreamingMode(bytes.length);
                        http.setDoOutput(true);
                        http.setConnectTimeout(TIMEOUT_MILLIS);
 
                        http.setRequestMethod("POST");
                        http.setFixedLengthStreamingMode(bytes.length);
                        http.setDoOutput(true);
                        http.setConnectTimeout(TIMEOUT_MILLIS);
-                       // http.setReadTimeout(TIMEOUT_MILLIS);
+                       http.setReadTimeout(TIMEOUT_MILLIS);
                        http.connect();
 
                        OutputStream os = http.getOutputStream();
                        os.write(bytes);
                        os.flush();
                        http.connect();
 
                        OutputStream os = http.getOutputStream();
                        os.write(bytes);
                        os.flush();
+               } catch (SocketTimeoutException e) {
+                       throw new ServerException("putSlot failed", ServerException.TypeConnectTimeout);
+               } catch (Exception e) {
+                       e.printStackTrace();
+                       throw new Error("putSlot failed");
+               }
 
 
 
 
+
+               try {
                        InputStream is = http.getInputStream();
                        DataInputStream dis = new DataInputStream(is);
                        byte[] resptype = new byte[7];
                        InputStream is = http.getInputStream();
                        DataInputStream dis = new DataInputStream(is);
                        byte[] resptype = new byte[7];
@@ -177,8 +213,11 @@ class CloudComm {
                        else
                                throw new Error("Bad response to putslot");
 
                        else
                                throw new Error("Bad response to putslot");
 
+               } catch (SocketTimeoutException e) {
+                       throw new ServerException("putSlot failed", ServerException.TypeInputTimeout);
                } catch (Exception e) {
                } catch (Exception e) {
-                       throw new ServerException("putSlot failed");
+                       e.printStackTrace();
+                       throw new Error("putSlot failed");
                }
        }
 
                }
        }
 
@@ -188,47 +227,46 @@ class CloudComm {
         * sequencenumber or newer.
         */
        Slot[] getSlots(long sequencenumber) throws ServerException {
         * sequencenumber or newer.
         */
        Slot[] getSlots(long sequencenumber) throws ServerException {
+               URL url = null;
+               URLConnection con = null;
+               HttpURLConnection http = null;
+
                try {
                        if (salt == null) {
                                getSalt();
                                initCrypt();
                        }
 
                try {
                        if (salt == null) {
                                getSalt();
                                initCrypt();
                        }
 
-                       URL url = buildRequest(false, sequencenumber, 0);
-                       URLConnection con = url.openConnection();
-                       HttpURLConnection http = (HttpURLConnection) con;
+                       url = buildRequest(false, sequencenumber, 0);
+                       con = url.openConnection();
+                       http = (HttpURLConnection) con;
                        http.setRequestMethod("POST");
                        http.setConnectTimeout(TIMEOUT_MILLIS);
                        http.setRequestMethod("POST");
                        http.setConnectTimeout(TIMEOUT_MILLIS);
-                       // http.setReadTimeout(TIMEOUT_MILLIS);
+                       http.setReadTimeout(TIMEOUT_MILLIS);
+
+
                        http.connect();
                        http.connect();
+               } catch (ServerException e) {
+                       throw new ServerException("getSlots failed", ServerException.TypeConnectTimeout);
+               } catch (Exception e) {
+                       e.printStackTrace();
+                       throw new Error("getSlots failed");
+               }
+
+               try {
                        InputStream is = http.getInputStream();
                        DataInputStream dis = new DataInputStream(is);
                        InputStream is = http.getInputStream();
                        DataInputStream dis = new DataInputStream(is);
-
-                       int responsecode = http.getResponseCode();
-                       if (responsecode != HttpURLConnection.HTTP_OK) {
-                               // TODO: Remove this print
-                               // System.out.println("Code:  " + responsecode);
-                               throw new ServerException("getSlots failed");
-                       }
-
                        byte[] resptype = new byte[7];
                        dis.readFully(resptype);
                        if (!Arrays.equals(resptype, "getslot".getBytes()))
                                throw new Error("Bad Response: " + new String(resptype));
                        else
                                return processSlots(dis);
                        byte[] resptype = new byte[7];
                        dis.readFully(resptype);
                        if (!Arrays.equals(resptype, "getslot".getBytes()))
                                throw new Error("Bad Response: " + new String(resptype));
                        else
                                return processSlots(dis);
+               } catch (ServerException e) {
+                       throw new ServerException("getSlots failed", ServerException.TypeInputTimeout);
                } catch (Exception e) {
                } catch (Exception e) {
-                       // e.printStackTrace();
-                       throw new ServerException("getSlots failed");
-               }
-       }
-
-       public boolean hasConnection() {
-               try {
-                       InetAddress address = InetAddress.getByName(hostname);
-                       return address.isReachable(TIMEOUT_MILLIS);
-               } catch (Exception e) {
-                       return false;
+                       e.printStackTrace();
+                       throw new Error("getSlots failed");
                }
        }
 
                }
        }
 
@@ -254,8 +292,4 @@ class CloudComm {
                dis.close();
                return slots;
        }
                dis.close();
                return slots;
        }
-
-
-
-
 }
 }
index fb52e6738e4854318bb9e578a6613e8f74855749..c43fcfd27f15e79ec093a243963caedbc065b790 100644 (file)
 package iotcloud;
 
 package iotcloud;
 
-import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.HashMap;
 import java.util.Set;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.HashSet;
-import java.util.Iterator;
+import java.nio.ByteBuffer;
+
+class Commit {
+
+    private Map<Integer, CommitPart> parts = null;
+    private Set<Integer> missingParts = null;
+    private boolean isComplete = false;
+    private boolean hasLastPart = false;
+    private Set<KeyValue> keyValueUpdateSet = null;
+    private boolean isDead = false;
+    private long sequenceNumber = -1;
+    private long machineId = -1;
+    private long transactionSequenceNumber = -1;
+
+    private Set<IoTString> liveKeys = null;
+
+    public Commit() {
+        parts = new HashMap<Integer, CommitPart>();
+        keyValueUpdateSet = new HashSet<KeyValue>();
+
+        liveKeys = new HashSet<IoTString>();
+    }
+
+    public Commit(long _sequenceNumber, long _machineId, long _transactionSequenceNumber) {
+        parts = new HashMap<Integer, CommitPart>();
+        keyValueUpdateSet = new HashSet<KeyValue>();
+
+        liveKeys = new HashSet<IoTString>();
+
+        sequenceNumber = _sequenceNumber;
+        machineId = _machineId;
+        transactionSequenceNumber = _transactionSequenceNumber;
+        isComplete = true;
+    }
+
 
 
-/**
- * This Entry records the commit of a transaction.
- * @author Ali Younis <ayounis@uci.edu>
- * @version 1.0
- */
+    public void addPartDecode(CommitPart newPart) {
 
 
+        if (isDead) {
+            // If dead then just kill this part and move on
+            newPart.setDead();
+            return;
+        }
 
 
-class Commit extends Entry {
-       private long seqnumtrans;
-       private long seqnumcommit;
-       private long transarbitrator;
-
-       private Set<KeyValue> keyValueUpdateSet = null;
+        CommitPart previoslySeenPart = parts.put(newPart.getPartNumber(), newPart);
 
 
+        if (previoslySeenPart != null) {
+            // Set dead the old one since the new one is a rescued version of this part
+            previoslySeenPart.setDead();
+        } else if (newPart.isLastPart()) {
+            missingParts = new HashSet<Integer>();
+            hasLastPart = true;
 
 
-       public Commit(Slot slot, long _seqnumtrans,  long _seqnumcommit, long _transarbitrator, Set<KeyValue> _keyValueUpdateSet) {
-               super(slot);
-               seqnumtrans = _seqnumtrans;
-               seqnumcommit = _seqnumcommit;
-               transarbitrator = _transarbitrator;
+            for (int i = 0; i < newPart.getPartNumber(); i++) {
+                if (parts.get(i) == null) {
+                    missingParts.add(i);
+                }
+            }
+        }
 
 
-               keyValueUpdateSet = new HashSet<KeyValue>();
+        if (!isComplete && hasLastPart) {
 
 
-               for (KeyValue kv : _keyValueUpdateSet) {
-                       KeyValue kvCopy = kv.getCopy();
-                       keyValueUpdateSet.add(kvCopy);
-               }
-       }
+            // We have seen this part so remove it from the set of missing parts
+            missingParts.remove(newPart.getPartNumber());
 
 
-       public long getTransSequenceNumber() {
-               return seqnumtrans;
-       }
-       public long getSequenceNumber() {
-               return seqnumcommit;
-       }
+            // Check if all the parts have been seen
+            if (missingParts.size() == 0) {
 
 
-       public long getTransArbitrator() {
-               return transarbitrator;
-       }
+                // We have all the parts
+                isComplete = true;
 
 
-       public Set<KeyValue> getkeyValueUpdateSet() {
-               return keyValueUpdateSet;
-       }
+                // Decode all the parts and create the key value guard and update sets
+                decodeCommitData();
 
 
-       public byte getType() {
-               return Entry.TypeCommit;
-       }
+                // Get the sequence number and arbitrator of this transaction
+                sequenceNumber = parts.get(0).getSequenceNumber();
+                machineId = parts.get(0).getMachineId();
+                transactionSequenceNumber = parts.get(0).getTransactionSequenceNumber();
+            }
+        }
+    }
 
 
-       public int getSize() {
-               int size = 3 * Long.BYTES + Byte.BYTES; // seq id, entry type
-               size += Integer.BYTES; // number of KV's
+    public long getSequenceNumber() {
+        return sequenceNumber;
+    }
 
 
-               // Size of each KV
-               for (KeyValue kv : keyValueUpdateSet) {
-                       size += kv.getSize();
-               }
+    public long getTransactionSequenceNumber() {
+        return transactionSequenceNumber;
+    }
 
 
-               return size;
-       }
 
 
-       static Entry decode(Slot slot, ByteBuffer bb) {
-               long seqnumtrans = bb.getLong();
-               long seqnumcommit = bb.getLong();
-               long transarbitrator = bb.getLong();
-               int numberOfKeys = bb.getInt();
+    public Map<Integer, CommitPart> getParts() {
+        return parts;
+    }
 
 
-               Set<KeyValue> kvSet = new HashSet<KeyValue>();
-               for (int i = 0; i < numberOfKeys; i++) {
-                       KeyValue kv = KeyValue.decode(bb);
-                       kvSet.add(kv);
-               }
+    public void addKV(KeyValue kv) {
+        keyValueUpdateSet.add(kv);
+        liveKeys.add(kv.getKey());
+    }
 
 
-               return new Commit(slot, seqnumtrans, seqnumcommit, transarbitrator, kvSet);
-       }
+    public void invalidateKey(IoTString key) {
+        liveKeys.remove(key);
 
 
-       public void encode(ByteBuffer bb) {
-               bb.put(Entry.TypeCommit);
-               bb.putLong(seqnumtrans);
-               bb.putLong(seqnumcommit);
-               bb.putLong(transarbitrator);
+        if (liveKeys.size() == 0) {
+            setDead();
+        }
+    }
 
 
-               bb.putInt(keyValueUpdateSet.size());
+    public Set<KeyValue> getKeyValueUpdateSet() {
+        return keyValueUpdateSet;
+    }
 
 
-               for (KeyValue kv : keyValueUpdateSet) {
-                       kv.encode(bb);
-               }
-       }
+    public int getNumberOfParts() {
+        return parts.size();
+    }
 
 
-       public Entry getCopy(Slot s) {
-               return new Commit(s, seqnumtrans, seqnumcommit, transarbitrator, keyValueUpdateSet);
-       }
+    public long getMachineId() {
+        return machineId;
+    }
 
 
-       public Set<KeyValue> updateLiveKeys(Set<KeyValue> kvSet) {
+    public boolean isComplete() {
+        return isComplete;
+    }
+
+    public boolean isLive() {
+        return !isDead;
+    }
+
+    public void setDead() {
+        if (isDead) {
+            // Already dead
+            return;
+        }
 
 
-               if (!this.isLive())
-                       return new HashSet<KeyValue>();
+        // Set dead
+        isDead = true;
+
+        // Make all the parts of this transaction dead
+        for (Integer partNumber : parts.keySet()) {
+            CommitPart part = parts.get(partNumber);
+            part.setDead();
+        }
+    }
+
+    public CommitPart getPart(int index) {
+        return parts.get(index);
+    }
+
+    public void createCommitParts() {
+
+        parts.clear();
+
+        // Convert to bytes
+        byte[] byteData = convertDataToBytes();
+
+
+        int commitPartCount = 0;
+        int currentPosition = 0;
+        int remaining = byteData.length;
 
 
-               Set<KeyValue> toDelete = new HashSet<KeyValue>();
+        while (remaining > 0) {
 
 
-               for (KeyValue kv1 : kvSet) {
-                       for (Iterator<KeyValue> i = keyValueUpdateSet.iterator(); i.hasNext();) {
-                               KeyValue kv2 = i.next();
+            Boolean isLastPart = false;
+            // determine how much to copy
+            int copySize = CommitPart.MAX_NON_HEADER_SIZE;
+            if (remaining <= CommitPart.MAX_NON_HEADER_SIZE) {
+                copySize = remaining;
+                isLastPart = true; // last bit of data so last part
+            }
+
+            // Copy to a smaller version
+            byte[] partData = new byte[copySize];
+            System.arraycopy(byteData, currentPosition, partData, 0, copySize);
+
+            CommitPart part = new CommitPart(null, machineId, sequenceNumber, transactionSequenceNumber, commitPartCount, partData, isLastPart);
+            parts.put(part.getPartNumber(), part);
+
+            // Update position, count and remaining
+            currentPosition += copySize;
+            commitPartCount++;
+            remaining -= copySize;
+        }
+    }
+
+    private void decodeCommitData() {
 
 
-                               if (kv1.getKey().equals(kv2.getKey())) {
-                                       toDelete.add(kv2);
-                                       i.remove();
-                                       break;
-                               }
-                       }
-               }
+        // Calculate the size of the data section
+        int dataSize = 0;
+        for (int i = 0; i < parts.keySet().size(); i++) {
+            CommitPart tp = parts.get(i);
+            dataSize += tp.getDataSize();
+        }
+
+        byte[] combinedData = new byte[dataSize];
+        int currentPosition = 0;
+
+        // Stitch all the data sections together
+        for (int i = 0; i < parts.keySet().size(); i++) {
+            CommitPart tp = parts.get(i);
+            System.arraycopy(tp.getData(), 0, combinedData, currentPosition, tp.getDataSize());
+            currentPosition += tp.getDataSize();
+        }
+
+        // Decoder Object
+        ByteBuffer bbDecode = ByteBuffer.wrap(combinedData);
+
+        // Decode how many key value pairs need to be decoded
+        int numberOfKVUpdates = bbDecode.getInt();
+
+        // Decode all the updates key values
+        for (int i = 0; i < numberOfKVUpdates; i++) {
+            KeyValue kv = (KeyValue)KeyValue.decode(bbDecode);
+            keyValueUpdateSet.add(kv);
+            liveKeys.add(kv.getKey());
+        }
+    }
+
+    private byte[] convertDataToBytes() {
+
+        // Calculate the size of the data
+        int sizeOfData = Integer.BYTES; // Number of Update KV's
+        for (KeyValue kv : keyValueUpdateSet) {
+            sizeOfData += kv.getSize();
+        }
+
+        // Data handlers and storage
+        byte[] dataArray = new byte[sizeOfData];
+        ByteBuffer bbEncode = ByteBuffer.wrap(dataArray);
+
+        // Encode the size of the updates and guard sets
+        bbEncode.putInt(keyValueUpdateSet.size());
+
+        // Encode all the updates
+        for (KeyValue kv : keyValueUpdateSet) {
+            kv.encode(bbEncode);
+        }
 
 
-               if (keyValueUpdateSet.size() == 0) {
-                       this.setDead();
-               }
-
-               return toDelete;
-       }
+        return bbEncode.array();
+    }
 }
\ No newline at end of file
 }
\ No newline at end of file
diff --git a/version2/src/java/iotcloud/CommitPart.java b/version2/src/java/iotcloud/CommitPart.java
new file mode 100644 (file)
index 0000000..cea9fbf
--- /dev/null
@@ -0,0 +1,128 @@
+
+
+package iotcloud;
+
+import java.nio.ByteBuffer;
+
+class CommitPart extends Entry{
+
+    // Max size of the part excluding the fixed size header
+    public static final int MAX_NON_HEADER_SIZE = 512;
+
+
+    // Sequence number of the transaction this commit is for, -1 if not a cloud transaction
+    private long machineId = -1; // Machine Id of the device that made the commit
+    private long sequenceNumber = -1; // commit sequence number for this arbitrator
+    private long transactionSequenceNumber = -1;
+    private int partNumber = -1; // Parts position in the
+    private Boolean isLastPart = false;
+    private byte[] data = null;
+
+    private Pair<Long, Integer> partId = null;
+    private Pair<Long, Long> commitId = null;
+
+
+    public CommitPart(Slot s, long _machineId, long _sequenceNumber, long _transactionSequenceNumber, int _partNumber, byte[] _data, Boolean _isLastPart) {
+        super(s);
+        machineId = _machineId;
+        sequenceNumber = _sequenceNumber;
+        transactionSequenceNumber = _transactionSequenceNumber;
+        partNumber = _partNumber;
+        isLastPart = _isLastPart;
+        data = _data;
+
+        partId = new Pair<Long, Integer>(sequenceNumber, partNumber);
+        commitId = new Pair<Long, Long>(machineId, sequenceNumber);
+    }
+
+    public int getSize() {
+        if (data == null) {
+            return (3 * Long.BYTES) + (2 * Integer.BYTES) + (2 * Byte.BYTES);
+        }
+        return (3 * Long.BYTES) + (2 * Integer.BYTES) + (2 * Byte.BYTES) + data.length;
+    }
+
+    public void setSlot(Slot s) {
+        parentslot = s;
+    }
+
+    public int getPartNumber() {
+        return partNumber;
+    }
+
+    public int getDataSize() {
+        return data.length;
+    }
+
+    public byte[] getData() {
+        return data;
+    }
+
+    public Pair<Long, Integer> getPartId() {
+        return partId;
+    }
+
+    public Pair<Long, Long> getCommitId() {
+        return commitId;
+    }
+
+    public Boolean isLastPart() {
+        return isLastPart;
+    }
+
+    public long getMachineId() {
+        return machineId;
+    }
+
+    public long getTransactionSequenceNumber() {
+        return transactionSequenceNumber;
+    }
+
+    public long getSequenceNumber() {
+        return sequenceNumber;
+    }
+
+    public void setSequenceNumber(long _sequenceNumber) {
+        sequenceNumber = _sequenceNumber;
+    }
+
+    static Entry decode(Slot s, ByteBuffer bb) {
+        long machineId = bb.getLong();
+        long sequenceNumber = bb.getLong();
+        long transactionSequenceNumber = bb.getLong();
+        int partNumber = bb.getInt();
+        int dataSize = bb.getInt();
+        Boolean isLastPart = bb.get() == 1;
+
+        // Get the data
+        byte[] data = new byte[dataSize];
+        bb.get(data);
+
+        return new CommitPart(s, machineId, sequenceNumber, transactionSequenceNumber, partNumber, data, isLastPart);
+    }
+
+    public void encode(ByteBuffer bb) {
+        bb.put(Entry.TypeCommitPart);
+        bb.putLong(machineId);
+        bb.putLong(sequenceNumber);
+        bb.putLong(transactionSequenceNumber);
+        bb.putInt(partNumber);
+        bb.putInt(data.length);
+
+        if (isLastPart) {
+            bb.put((byte)1);
+        } else {
+            bb.put((byte)0);
+        }
+
+        bb.put(data);
+    }
+
+    public byte getType() {
+        return Entry.TypeCommitPart;
+    }
+
+    public Entry getCopy(Slot s) {
+        return new CommitPart(s, machineId, sequenceNumber, transactionSequenceNumber, partNumber, data, isLastPart);
+    }
+}
\ No newline at end of file
index 8395deca5ea297091af4a7e3afc088dcb5fba07f..dd9e75b2f4afc9c32e4649497f258aad49c2e626 100644 (file)
@@ -10,10 +10,9 @@ import java.nio.ByteBuffer;
 
 abstract class Entry implements Liveness {
 
 
 abstract class Entry implements Liveness {
 
-
-       static final byte TypeCommit = 1;
+       static final byte TypeCommitPart = 1;
        static final byte TypeAbort = 2;
        static final byte TypeAbort = 2;
-       static final byte TypeTransaction = 3;
+       static final byte TypeTransactionPart = 3;
        static final byte TypeNewKey = 4;
        static final byte TypeLastMessage = 5;
        static final byte TypeRejectedMessage = 6;
        static final byte TypeNewKey = 4;
        static final byte TypeLastMessage = 5;
        static final byte TypeRejectedMessage = 6;
@@ -25,7 +24,7 @@ abstract class Entry implements Liveness {
                 superceded by a newer update.  */
 
        private boolean islive = true;
                 superceded by a newer update.  */
 
        private boolean islive = true;
-       private Slot parentslot;
+       protected Slot parentslot;
 
        public Entry(Slot _parentslot) {
                parentslot = _parentslot;
 
        public Entry(Slot _parentslot) {
                parentslot = _parentslot;
@@ -35,19 +34,18 @@ abstract class Entry implements Liveness {
         * Static method for decoding byte array into Entry objects.  First
         * byte tells the type of entry.
         */
         * Static method for decoding byte array into Entry objects.  First
         * byte tells the type of entry.
         */
-
        static Entry decode(Slot slot, ByteBuffer bb) {
                byte type = bb.get();
                switch (type) {
 
        static Entry decode(Slot slot, ByteBuffer bb) {
                byte type = bb.get();
                switch (type) {
 
-               case TypeCommit:
-                       return Commit.decode(slot, bb);
+               case TypeCommitPart:
+                       return CommitPart.decode(slot, bb);
 
                case TypeAbort:
                        return Abort.decode(slot, bb);
 
 
                case TypeAbort:
                        return Abort.decode(slot, bb);
 
-               case TypeTransaction:
-                       return Transaction.decode(slot, bb);
+               case TypeTransactionPart:
+                       return TransactionPart.decode(slot, bb);
 
                case TypeNewKey:
                        return NewKey.decode(slot, bb);
 
                case TypeNewKey:
                        return NewKey.decode(slot, bb);
@@ -69,16 +67,15 @@ abstract class Entry implements Liveness {
        /**
         * Returns true if the Entry object is still live.
         */
        /**
         * Returns true if the Entry object is still live.
         */
-
        public boolean isLive() {
                return islive;
        }
 
        public boolean isLive() {
                return islive;
        }
 
+
        /**
         * Flags the entry object as dead.  Also decrements the live count
         * of the parent slot.
         */
        /**
         * Flags the entry object as dead.  Also decrements the live count
         * of the parent slot.
         */
-
        public void setDead() {
 
                if (!islive ) {
        public void setDead() {
 
                if (!islive ) {
@@ -92,28 +89,28 @@ abstract class Entry implements Liveness {
                }
        }
 
                }
        }
 
+
        /**
         * Serializes the Entry object into the byte buffer.
         */
        /**
         * Serializes the Entry object into the byte buffer.
         */
-
        abstract void encode(ByteBuffer bb);
 
        abstract void encode(ByteBuffer bb);
 
+
        /**
         * Returns the size in bytes the entry object will take in the byte
         * array.
         */
        /**
         * Returns the size in bytes the entry object will take in the byte
         * array.
         */
-
        abstract int getSize();
 
        abstract int getSize();
 
+
        /**
         * Returns a byte encoding the type of the entry object.
         */
        /**
         * Returns a byte encoding the type of the entry object.
         */
-
        abstract byte getType();
 
        abstract byte getType();
 
+
        /**
         * Returns a copy of the Entry that can be added to a different slot.
         */
        abstract Entry getCopy(Slot s);
        /**
         * Returns a copy of the Entry that can be added to a different slot.
         */
        abstract Entry getCopy(Slot s);
-
 }
 }
index 17e3c057f93052a603c5a9c181239ce58492f54c..c2eb11b7bf8e9ce4b4402506fb9a93a108a7c0a3 100644 (file)
@@ -12,12 +12,14 @@ class LocalComm {
     public byte[] sendDataToLocalDevice(Long deviceId, byte[] data) throws InterruptedException{
         System.out.println("Passing Locally");
 
     public byte[] sendDataToLocalDevice(Long deviceId, byte[] data) throws InterruptedException{
         System.out.println("Passing Locally");
 
-        if (deviceId == t1.getId()) {
-            return t1.localCommInput(data);
-        } else if (deviceId == t2.getId()) {
-            return t2.localCommInput(data);
+        if (deviceId == t1.getMachineId()) {
+            // return t1.localCommInput(data);
+        } else if (deviceId == t2.getMachineId()) {
+            // return t2.localCommInput(data);
         } else {
             throw new Error("Cannot send to " + deviceId + " using this local comm");
         }
         } else {
             throw new Error("Cannot send to " + deviceId + " using this local comm");
         }
+
+        return new byte[0];
     }
 }
\ No newline at end of file
     }
 }
\ No newline at end of file
index 0970016c322595bcc342e9c1ba0c863c8393e805..3e53a1c4750244f025462cec63971a951508dbd1 100644 (file)
@@ -27,6 +27,10 @@ class NewKey extends Entry {
                return key;
        }
 
                return key;
        }
 
+       public void setSlot(Slot s) {
+               parentslot = s;
+       }
+
        static Entry decode(Slot slot, ByteBuffer bb) {
                int keylength = bb.getInt();
                byte[] key = new byte[keylength];
        static Entry decode(Slot slot, ByteBuffer bb) {
                int keylength = bb.getInt();
                byte[] key = new byte[keylength];
index 73ed6bd440b0858d2c9022c73014b7c07d3088f7..6352fc1dc73cf81c93e3beb5e4a109593bf81044 100644 (file)
@@ -1,12 +1,17 @@
 package iotcloud;
 
 package iotcloud;
 
-class Pair<A,B> {
+class Pair<A, B> {
        private A a;
        private B b;
        private A a;
        private B b;
+       int hashCode = -1;
 
        Pair(A a, B b) {
 
        Pair(A a, B b) {
-               this.a=a;
-               this.b=b;
+               this.a = a;
+               this.b = b;
+
+               hashCode = 23;
+               hashCode = hashCode * 31 + a.hashCode();
+               hashCode = hashCode * 31 + b.hashCode();
        }
 
        A getFirst() {
        }
 
        A getFirst() {
@@ -17,7 +22,22 @@ class Pair<A,B> {
                return b;
        }
 
                return b;
        }
 
+
+       public int hashCode() {
+               return hashCode;
+       }
+
+       public boolean equals(Object o) {
+               if (o instanceof Pair) {
+                       Pair i = (Pair)o;
+                       if (a.equals(i.getFirst()) && b.equals(i.getSecond())) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
        public String toString() {
        public String toString() {
-               return "<"+a+","+b+">";
+               return "<" + a + "," + b + ">";
        }
 }
        }
 }
index 1a14674aa8442816cdbb0b16b45bfc3a112294ea..ad752b5701b8a7c58f4d7028249a53b5bebc5a26 100644 (file)
@@ -6,6 +6,7 @@ import java.util.HashSet;
 
 import javax.script.ScriptException;
 import java.lang.NullPointerException;
 
 import javax.script.ScriptException;
 import java.lang.NullPointerException;
+import java.nio.ByteBuffer;
 
 
 class PendingTransaction {
 
 
 class PendingTransaction {
@@ -13,9 +14,13 @@ class PendingTransaction {
     private Set<KeyValue> keyValueUpdateSet = null;
     private Set<KeyValue> keyValueGuardSet = null;
     private long arbitrator = -1;
     private Set<KeyValue> keyValueUpdateSet = null;
     private Set<KeyValue> keyValueGuardSet = null;
     private long arbitrator = -1;
-    private long machineLocalTransSeqNum = -1;
+    private long clientLocalSequenceNumber = -1;
+    private long machineId = -1;
 
 
-    public PendingTransaction() {
+    private int currentDataSize = 0;
+
+    public PendingTransaction(long _machineId) {
+        machineId = _machineId;
         keyValueUpdateSet = new HashSet<KeyValue>();
         keyValueGuardSet = new HashSet<KeyValue>();
     }
         keyValueUpdateSet = new HashSet<KeyValue>();
         keyValueGuardSet = new HashSet<KeyValue>();
     }
@@ -41,13 +46,14 @@ class PendingTransaction {
         // Remove key if we are adding a newer version of the same key
         if (rmKV != null) {
             keyValueUpdateSet.remove(rmKV);
         // Remove key if we are adding a newer version of the same key
         if (rmKV != null) {
             keyValueUpdateSet.remove(rmKV);
+            currentDataSize -= rmKV.getSize();
         }
 
         // Add the key to the hash set
         keyValueUpdateSet.add(newKV);
         }
 
         // Add the key to the hash set
         keyValueUpdateSet.add(newKV);
+        currentDataSize += newKV.getSize();
     }
 
     }
 
-
     /**
      * Add a new key value to the guard set
      *
     /**
      * Add a new key value to the guard set
      *
@@ -55,11 +61,11 @@ class PendingTransaction {
     public void addKVGuard(KeyValue newKV) {
         // Add the key to the hash set
         keyValueGuardSet.add(newKV);
     public void addKVGuard(KeyValue newKV) {
         // Add the key to the hash set
         keyValueGuardSet.add(newKV);
+        currentDataSize += newKV.getSize();
     }
 
     /**
      * Checks if the arbitrator is the same
     }
 
     /**
      * Checks if the arbitrator is the same
-     *
      */
     public boolean checkArbitrator(long arb) {
         if (arbitrator == -1) {
      */
     public boolean checkArbitrator(long arb) {
         if (arbitrator == -1) {
@@ -72,7 +78,6 @@ class PendingTransaction {
 
     /**
      * Get the transaction arbitrator
 
     /**
      * Get the transaction arbitrator
-     *
      */
     public long getArbitrator() {
         return arbitrator;
      */
     public long getArbitrator() {
         return arbitrator;
@@ -80,27 +85,28 @@ class PendingTransaction {
 
     /**
      * Get the key value update set
 
     /**
      * Get the key value update set
-     *
      */
     public Set<KeyValue> getKVUpdates() {
         return keyValueUpdateSet;
     }
 
      */
     public Set<KeyValue> getKVUpdates() {
         return keyValueUpdateSet;
     }
 
-
     /**
     /**
-       * Get the key value update set
-       *
-       */
+     * Get the key value update set
+     */
     public Set<KeyValue> getKVGuard() {
         return keyValueGuardSet;
     }
 
     public Set<KeyValue> getKVGuard() {
         return keyValueGuardSet;
     }
 
-    public void setMachineLocalTransSeqNum(long _machineLocalTransSeqNum) {
-        machineLocalTransSeqNum = _machineLocalTransSeqNum;
+    public void setClientLocalSequenceNumber(long _clientLocalSequenceNumber) {
+        clientLocalSequenceNumber = _clientLocalSequenceNumber;
+    }
+
+    public long getClientLocalSequenceNumber() {
+        return clientLocalSequenceNumber;
     }
 
     }
 
-    public long getMachineLocalTransSeqNum() {
-        return machineLocalTransSeqNum;
+    public long getMachineId() {
+        return machineId;
     }
 
     public boolean evaluateGuard(Map<IoTString, KeyValue> keyValTableCommitted, Map<IoTString, KeyValue> keyValTableSpeculative, Map<IoTString, KeyValue> keyValTablePendingTransSpeculative) {
     }
 
     public boolean evaluateGuard(Map<IoTString, KeyValue> keyValTableCommitted, Map<IoTString, KeyValue> keyValTableSpeculative, Map<IoTString, KeyValue> keyValTablePendingTransSpeculative) {
@@ -135,4 +141,78 @@ class PendingTransaction {
         }
         return true;
     }
         }
         return true;
     }
+
+    public Transaction createTransaction() {
+
+        Transaction newTransaction = new Transaction();
+        int transactionPartCount = 0;
+
+        // Convert all the data into a byte array so we can start partitioning
+        byte[] byteData = convertDataToBytes();
+
+        int currentPosition = 0;
+        int remaining = byteData.length;
+
+        while (remaining > 0) {
+
+            Boolean isLastPart = false;
+            // determine how much to copy
+            int copySize = TransactionPart.MAX_NON_HEADER_SIZE;
+            if (remaining <= TransactionPart.MAX_NON_HEADER_SIZE) {
+                copySize = remaining;
+                isLastPart = true; // last bit of data so last part
+            }
+
+            // Copy to a smaller version
+            byte[] partData = new byte[copySize];
+            System.arraycopy(byteData, currentPosition, partData, 0, copySize);
+
+            TransactionPart part = new TransactionPart(null, machineId, arbitrator, clientLocalSequenceNumber, transactionPartCount, partData, isLastPart);
+            newTransaction.addPartEncode(part);
+
+            // Update position, count and remaining
+            currentPosition += copySize;
+            transactionPartCount++;
+            remaining -= copySize;
+        }
+
+        // Add the Guard Conditions
+        for (KeyValue kv : keyValueGuardSet) {
+            newTransaction.addGuardKV(kv);
+        }
+
+        //  Add the updates
+        for (KeyValue kv : keyValueUpdateSet) {
+            newTransaction.addUpdateKV(kv);
+        }
+
+        return newTransaction;
+    }
+
+    private byte[] convertDataToBytes() {
+
+        // Calculate the size of the data
+        int sizeOfData = 2 * Integer.BYTES; // Number of Update KV's and Guard KV's
+        sizeOfData += currentDataSize;
+
+        // Data handlers and storage
+        byte[] dataArray = new byte[sizeOfData];
+        ByteBuffer bbEncode = ByteBuffer.wrap(dataArray);
+
+        // Encode the size of the updates and guard sets
+        bbEncode.putInt(keyValueGuardSet.size());
+        bbEncode.putInt(keyValueUpdateSet.size());
+
+        // Encode all the guard conditions
+        for (KeyValue kv : keyValueGuardSet) {
+            kv.encode(bbEncode);
+        }
+
+        // Encode all the updates
+        for (KeyValue kv : keyValueUpdateSet) {
+            kv.encode(bbEncode);
+        }
+
+        return bbEncode.array();
+    }
 }
\ No newline at end of file
 }
\ No newline at end of file
index 6d35c43cc717d7e6c6207163051e0a21c6ccda5a..b09096c8ba07ee6339211e7165dbc3cf2f126dde 100644 (file)
@@ -1,8 +1,18 @@
 package iotcloud;
 
 public class ServerException extends Exception {
 package iotcloud;
 
 public class ServerException extends Exception {
-    
-    public ServerException(String message) {
+
+    public static final byte TypeConnectTimeout = 1;
+    public static final byte TypeInputTimeout = 2;
+    public static final byte TypeIncorrectResponseCode = 2;
+    private byte type = -1;
+
+    public ServerException(String message, byte _type) {
         super(message);
         super(message);
+        type = _type;
+    }
+
+    public byte getType() {
+        return type;
     }
 }
     }
 }
index f6d699b91187a6682b096f19074aefc6c69d8531..976422381d11087bf60e6ade37f9b9d03eb0fd6a 100644 (file)
 package iotcloud;
 package iotcloud;
-import java.util.HashMap;
-import java.util.Map;
+
 import java.util.Iterator;
 import java.util.Iterator;
-import java.util.HashSet;
+import java.util.Random;
 import java.util.Arrays;
 import java.util.Arrays;
+import java.util.Map;
+import java.util.Set;
+import java.util.List;
 import java.util.Vector;
 import java.util.Vector;
-import java.util.Random;
-import java.util.Queue;
-import java.util.LinkedList;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.ArrayList;
 import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Collections;
-import java.nio.ByteBuffer;
-import java.util.concurrent.Semaphore;
-
 
 /**
 
 /**
- * IoTTable data structure.  Provides client inferface.
+ * IoTTable data structure.  Provides client interface.
  * @author Brian Demsky
  * @version 1.0
  */
 
 final public class Table {
  * @author Brian Demsky
  * @version 1.0
  */
 
 final public class Table {
-       private int numslots;   //number of slots stored in buffer
-
-       // machine id -> (sequence number, Slot or LastMessage); records last message by each client
-       private HashMap<Long, Pair<Long, Liveness> > lastmessagetable = new HashMap<Long, Pair<Long, Liveness> >();
-       // machine id -> ...
-       private HashMap<Long, HashSet<RejectedMessage> > watchlist = new HashMap<Long, HashSet<RejectedMessage> >();
-       private Vector<Long> rejectedmessagelist = new Vector<Long>();
-       private SlotBuffer buffer;
-       private CloudComm cloud;
-       private long sequencenumber; //Largest sequence number a client has received
-       private long localmachineid;
-       private TableStatus lastTableStatus;
-       static final int FREE_SLOTS = 10; //number of slots that should be kept free
+
+
+       /* Constants */
+       static final int FREE_SLOTS = 10; // Number of slots that should be kept free
        static final int SKIP_THRESHOLD = 10;
        static final int SKIP_THRESHOLD = 10;
-       private long liveslotcount = 0;
-       private int chance;
        static final double RESIZE_MULTIPLE = 1.2;
        static final double RESIZE_THRESHOLD = 0.75;
        static final int REJECTED_THRESHOLD = 5;
        static final double RESIZE_MULTIPLE = 1.2;
        static final double RESIZE_THRESHOLD = 0.75;
        static final int REJECTED_THRESHOLD = 5;
-       private int resizethreshold;
-       private long lastliveslotseqn;  //smallest sequence number with a live entry
-       private Random random = new Random();
-       private long lastUncommittedTransaction = 0;
-
-       private int smallestTableStatusSeen = -1;
-       private int largestTableStatusSeen = -1;
-       private int lastSeenPendingTransactionSpeculateIndex = 0;
-       private int commitSequenceNumber = 0;
-       private long localTransactionSequenceNumber = 0;
-
-       private PendingTransaction pendingTransBuild = null; // Pending Transaction used in building
-       private LinkedList<PendingTransaction> pendingTransQueue = null; // Queue of pending transactions
-       private Map<Long, Map<Long, Commit>> commitMap = null; // List of all the most recent live commits
-       private Map<Long, Abort> abortMap = null; // Set of the live aborts
-       private Map<IoTString, Commit> committedMapByKey = null; // Table of committed KV
-       private Map<IoTString, KeyValue> commitedTable = null; // Table of committed KV
-       private Map<IoTString, KeyValue> speculativeTable = null; // Table of speculative KV
-       private Map<Long, Transaction> uncommittedTransactionsMap = null;
-       private Map<IoTString, Long> arbitratorTable = null; // Table of arbitrators
-       private Map<IoTString, NewKey> newKeyTable = null; // Table of speculative KV
-       private Map<Long, Map<Long, Commit>> newCommitMap = null; // Map of all the new commits
-       private Map<Long, Long> lastCommitSeenSeqNumMap = null; // sequence number of the last commit that was seen grouped by arbitrator
-       private Map<Long, Long> lastCommitSeenTransSeqNumMap = null; // transaction sequence number of the last commit that was seen grouped by arbitrator
-       private Map<Long, Long> lastAbortSeenSeqNumMap = null; // sequence number of the last abort that was seen grouped by arbitrator
-       private Map<IoTString, KeyValue> pendingTransSpeculativeTable = null;
-       private List<Commit> pendingCommitsList = null;
-       private List<Commit> pendingCommitsToDelete = null;
-       private Map<Long, LocalComm> localCommunicationChannels;
-       private Map<Long, TransactionStatus> transactionStatusMap = null;
-       private Map<Long, TransactionStatus> transactionStatusNotSentMap = null;
-
-       private Semaphore mutex = null;
-
-
-
-       public Table(String hostname, String baseurl, String password, long _localmachineid) {
-               localmachineid = _localmachineid;
-               buffer = new SlotBuffer();
-               numslots = buffer.capacity();
-               setResizeThreshold();
-               sequencenumber = 0;
-               cloud = new CloudComm(this, hostname, baseurl, password);
-               lastliveslotseqn = 1;
 
 
-               setupDataStructs();
+
+       /* Helper Objects */
+       private SlotBuffer buffer = null;
+       private CloudComm cloud = null;
+       private Random random = null;
+       private TableStatus liveTableStatus = null;
+       private PendingTransaction pendingTransactionBuilder = null; // Pending Transaction used in building a Pending Transaction
+       private Transaction lastPendingTransactionSpeculatedOn = null; // Last transaction that was speculated on from the pending transaction
+       private Transaction firstPendingTransaction = null; // first transaction in the pending transaction list
+
+       /* Variables */
+       private int numberOfSlots = 0;  // Number of slots stored in buffer
+       private int bufferResizeThreshold = 0; // Threshold on the number of live slots before a resize is needed
+       private long liveSlotCount = 0; // Number of currently live slots
+       private long oldestLiveSlotSequenceNumver = 0;  // Smallest sequence number of the slot with a live entry
+       private long localMachineId = 0; // Machine ID of this client device
+       private long sequenceNumber = 0; // Largest sequence number a client has received
+       private int smallestTableStatusSeen = -1; // Smallest Table Status that was seen in the latest slots sent from the server
+       private int largestTableStatusSeen = -1; // Largest Table Status that was seen in the latest slots sent from the server
+       private long localTransactionSequenceNumber = 0; // Local sequence number counter for transactions
+       private long lastTransactionSequenceNumberSpeculatedOn = -1; // the last transaction that was speculated on
+       private long oldestTransactionSequenceNumberSpeculatedOn = -1; // the oldest transaction that was speculated on
+       private long localCommitSequenceNumber = 0;
+
+       /* Data Structures  */
+       private Map<IoTString, KeyValue> committedKeyValueTable = null; // Table of committed key value pairs
+       private Map<IoTString, KeyValue> speculatedKeyValueTable = null; // Table of speculated key value pairs, if there is a speculative value
+       private Map<IoTString, KeyValue> pendingTransactionSpeculatedKeyValueTable = null; // Table of speculated key value pairs, if there is a speculative value from the pending transactions
+
+       private Map<IoTString, NewKey> liveNewKeyTable = null; // Table of live new keys
+       private HashMap<Long, Pair<Long, Liveness>> lastMessageTable = null; // Last message sent by a client machine id -> (Seq Num, Slot or LastMessage);
+       private HashMap<Long, HashSet<RejectedMessage>> rejectedMessageWatchListTable = null; // Table of machine Ids and the set of rejected messages they have not seen yet
+       private Map<IoTString, Long> arbitratorTable = null; // Table of keys and their arbitrators
+       private Map<Pair<Long, Long>, Abort> liveAbortTable = null; // Table live abort messages
+       private Map<Long, Map<Pair<Long, Integer>, TransactionPart>> newTransactionParts = null; // transaction parts that are seen in this latest round of slots from the server
+       private Map<Long, Map<Pair<Long, Integer>, CommitPart>> newCommitParts = null; // commit parts that are seen in this latest round of slots from the server
+       private Map<Long, Long> lastArbitratedTransactionNumberByArbitratorTable = null; // Last transaction sequence number that an arbitrator arbitrated on
+       private Map<Long, Transaction> liveTransactionBySequenceNumberTable = null; // live transaction grouped by the sequence number
+       private Map<Pair<Long, Long>, Transaction> liveTransactionByTransactionIdTable = null; // live transaction grouped by the transaction ID
+       private Map<Long, Map<Long, Commit>> liveCommitsTable = null;
+       private Map<IoTString, Commit> liveCommitsByKeyTable = null;
+       private Map<Long, Long> lastCommitSeenSequenceNumberByArbitratorTable = null;
+       private Vector<Long> rejectedSlotList = null; // List of rejected slots that have yet to be sent to the server
+
+       private List<Transaction> pendingTransactionQueue = null;
+       private List<Entry> pendingSendArbitrationEntries = null;
+       private List<Entry> pendingSendArbitrationEntriesToDelete = null;
+       private Map<Transaction, List<Integer>> transactionPartsSent = null;
+       private Map<Long, TransactionStatus> outstandingTransactionStatus = null;
+
+
+
+
+
+       public Table(String baseurl, String password, long _localMachineId) {
+               localMachineId = _localMachineId;
+               cloud = new CloudComm(this, baseurl, password);
+
+               init();
        }
 
        }
 
-       public Table(CloudComm _cloud, long _localmachineid) {
-               localmachineid = _localmachineid;
-               buffer = new SlotBuffer();
-               numslots = buffer.capacity();
-               setResizeThreshold();
-               sequencenumber = 0;
+       public Table(CloudComm _cloud, long _localMachineId) {
+               localMachineId = _localMachineId;
                cloud = _cloud;
 
                cloud = _cloud;
 
-               setupDataStructs();
+               init();
        }
 
        }
 
-       private void setupDataStructs() {
-               pendingTransQueue = new LinkedList<PendingTransaction>();
-               commitMap = new HashMap<Long, Map<Long, Commit>>();
-               abortMap = new HashMap<Long, Abort>();
-               committedMapByKey = new HashMap<IoTString, Commit>();
-               commitedTable = new HashMap<IoTString, KeyValue>();
-               speculativeTable = new HashMap<IoTString, KeyValue>();
-               uncommittedTransactionsMap = new HashMap<Long, Transaction>();
+       /**
+        * Init all the stuff needed for for table usage
+        */
+       private void init() {
+
+               // Init helper objects
+               random = new Random();
+               buffer = new SlotBuffer();
+
+               // Set Variables
+               oldestLiveSlotSequenceNumver = 1;
+
+               // init data structs
+               committedKeyValueTable = new HashMap<IoTString, KeyValue>();
+               speculatedKeyValueTable = new HashMap<IoTString, KeyValue>();
+               pendingTransactionSpeculatedKeyValueTable = new HashMap<IoTString, KeyValue>();
+               liveNewKeyTable = new HashMap<IoTString, NewKey>();
+               lastMessageTable = new HashMap<Long, Pair<Long, Liveness>>();
+               rejectedMessageWatchListTable = new HashMap<Long, HashSet<RejectedMessage>>();
                arbitratorTable = new HashMap<IoTString, Long>();
                arbitratorTable = new HashMap<IoTString, Long>();
-               newKeyTable = new HashMap<IoTString, NewKey>();
-               newCommitMap = new HashMap<Long, Map<Long, Commit>>();
-               lastCommitSeenSeqNumMap = new HashMap<Long, Long>();
-               lastCommitSeenTransSeqNumMap = new HashMap<Long, Long>();
-               lastAbortSeenSeqNumMap = new HashMap<Long, Long>();
-               pendingTransSpeculativeTable = new HashMap<IoTString, KeyValue>();
-               pendingCommitsList = new LinkedList<Commit>();
-               pendingCommitsToDelete = new LinkedList<Commit>();
-               localCommunicationChannels = new HashMap<Long, LocalComm>();
-               transactionStatusMap = new HashMap<Long, TransactionStatus>();
-               transactionStatusNotSentMap = new HashMap<Long, TransactionStatus>();
-               mutex = new Semaphore(1);
+               liveAbortTable = new HashMap<Pair<Long, Long>, Abort>();
+               newTransactionParts = new HashMap<Long, Map<Pair<Long, Integer>, TransactionPart>>();
+               newCommitParts = new HashMap<Long, Map<Pair<Long, Integer>, CommitPart>>();
+               lastArbitratedTransactionNumberByArbitratorTable = new HashMap<Long, Long>();
+               liveTransactionBySequenceNumberTable = new HashMap<Long, Transaction>();
+               liveTransactionByTransactionIdTable = new HashMap<Pair<Long, Long>, Transaction>();
+               liveCommitsTable = new HashMap<Long, Map<Long, Commit>>();
+               liveCommitsByKeyTable = new HashMap<IoTString, Commit>();
+               lastCommitSeenSequenceNumberByArbitratorTable = new HashMap<Long, Long>();
+               rejectedSlotList = new Vector<Long>();
+               pendingTransactionQueue = new ArrayList<Transaction>();
+               pendingSendArbitrationEntries = new ArrayList<Entry>();
+               pendingSendArbitrationEntriesToDelete = new ArrayList<Entry>();
+               transactionPartsSent = new HashMap<Transaction, List<Integer>>();
+               outstandingTransactionStatus = new HashMap<Long, TransactionStatus>();
+
+               // Other init stuff
+               numberOfSlots = buffer.capacity();
+               setResizeThreshold();
        }
 
        }
 
-       public void initTable() throws ServerException {
-               cloud.setSalt();//Set the salt
-               Slot s = new Slot(this, 1, localmachineid);
-               TableStatus status = new TableStatus(s, numslots);
+       /**
+        * Initialize the table by inserting a table status as the first entry into the table status
+        * also initialize the crypto stuff.
+        */
+       public synchronized void initTable() throws ServerException {
+               cloud.setSalt(); //Set the salt
+
+               // Create the first insertion into the block chain which is the table status
+               Slot s = new Slot(this, 1, localMachineId);
+               TableStatus status = new TableStatus(s, numberOfSlots);
                s.addEntry(status);
                s.addEntry(status);
-               Slot[] array = cloud.putSlot(s, numslots);
+               Slot[] array = cloud.putSlot(s, numberOfSlots);
+
                if (array == null) {
                        array = new Slot[] {s};
                if (array == null) {
                        array = new Slot[] {s};
-                       /* update data structure */
-                       validateandupdate(array, true);
+                       // update local block chain
+                       validateAndUpdate(array, true);
                } else {
                        throw new Error("Error on initialization");
                }
        }
 
                } else {
                        throw new Error("Error on initialization");
                }
        }
 
-       public void rebuild() throws ServerException, InterruptedException {
-               mutex.acquire();
-               Slot[] newslots = cloud.getSlots(sequencenumber + 1);
-               validateandupdate(newslots, true);
-               mutex.release();
-       }
-
-       // TODO: delete method
-       public void printSlots() {
-               long o = buffer.getOldestSeqNum();
-               long n = buffer.getNewestSeqNum();
-
-               int[] types = new int[10];
-
-               int num = 0;
-
-               int livec = 0;
-               int deadc = 0;
-               for (long i = o; i < (n + 1); i++) {
-                       Slot s = buffer.getSlot(i);
-
-                       Vector<Entry> entries = s.getEntries();
-
-                       for (Entry e : entries) {
-                               if (e.isLive()) {
-                                       int type = e.getType();
-                                       types[type] = types[type] + 1;
-                                       num++;
-                                       livec++;
-                               } else {
-                                       deadc++;
-                               }
-                       }
-               }
-
-               for (int i = 0; i < 10; i++) {
-                       System.out.println(i + "    " + types[i]);
-               }
-               System.out.println("Live count:   " + livec);
-               System.out.println("Dead count:   " + deadc);
-               System.out.println("Old:   " + o);
-               System.out.println("New:   " + n);
-               System.out.println("Size:   " + buffer.size());
-               System.out.println("Commits Key Map:   " + commitedTable.size());
-               // System.out.println("Commits Live Map:   " + commitMap.size());
-               System.out.println("Pending:   " + pendingTransQueue.size());
-
-               // List<IoTString> strList = new ArrayList<IoTString>();
-               // for (int i = 0; i < 100; i++) {
-               //      String keyA = "a" + i;
-               //      String keyB = "b" + i;
-               //      String keyC = "c" + i;
-               //      String keyD = "d" + i;
-
-               //      IoTString iKeyA = new IoTString(keyA);
-               //      IoTString iKeyB = new IoTString(keyB);
-               //      IoTString iKeyC = new IoTString(keyC);
-               //      IoTString iKeyD = new IoTString(keyD);
-
-               //      strList.add(iKeyA);
-               //      strList.add(iKeyB);
-               //      strList.add(iKeyC);
-               //      strList.add(iKeyD);
-               // }
-
-
-               // for (Long l : commitMap.keySet()) {
-               //      for (Long l2 : commitMap.get(l).keySet()) {
-               //              for (KeyValue kv : commitMap.get(l).get(l2).getkeyValueUpdateSet()) {
-               //                      strList.remove(kv.getKey());
-               //                      System.out.print(kv.getKey() + "    ");
-               //              }
-               //      }
-               // }
-
-               // System.out.println();
-               // System.out.println();
-
-               // for (IoTString s : strList) {
-               //      System.out.print(s + "    ");
-               // }
-               // System.out.println();
-               // System.out.println(strList.size());
-       }
-
-       public long getId() {
-               return localmachineid;
-       }
-
-       public boolean hasConnection() {
-               return cloud.hasConnection();
+       /**
+        * Rebuild the table from scratch by pulling the latest block chain from the server.
+        */
+       public synchronized void rebuild() throws ServerException {
+               // Just pull the latest slots from the server
+               Slot[] newslots = cloud.getSlots(sequenceNumber + 1);
+               validateAndUpdate(newslots, true);
        }
 
        }
 
-       public String toString() {
-               String retString = " Committed Table: \n";
-               retString += "---------------------------\n";
-               retString += commitedTable.toString();
+       // public String toString() {
+       //      String retString = " Committed Table: \n";
+       //      retString += "---------------------------\n";
+       //      retString += commitedTable.toString();
 
 
-               retString += "\n\n";
+       //      retString += "\n\n";
 
 
-               retString += " Speculative Table: \n";
-               retString += "---------------------------\n";
-               retString += speculativeTable.toString();
-
-               return retString;
-       }
-
-       public void addLocalComm(long machineId, LocalComm lc) {
-               localCommunicationChannels.put(machineId, lc);
-       }
-       public Long getArbitrator(IoTString key) throws InterruptedException {
+       //      retString += " Speculative Table: \n";
+       //      retString += "---------------------------\n";
+       //      retString += speculativeTable.toString();
 
 
-               mutex.acquire();
-               Long arb = arbitratorTable.get(key);
-               mutex.release();
+       //      return retString;
+       // }
 
 
-               return arb;
+       public synchronized Long getArbitrator(IoTString key) {
+               return arbitratorTable.get(key);
        }
 
        }
 
-       public IoTString getCommitted(IoTString key) throws InterruptedException {
-
-               mutex.acquire();
-               KeyValue kv = commitedTable.get(key);
-               mutex.release();
-
+       public synchronized IoTString getCommitted(IoTString key)  {
+               KeyValue kv = committedKeyValueTable.get(key);
 
                if (kv != null) {
                        return kv.getValue();
 
                if (kv != null) {
                        return kv.getValue();
@@ -273,21 +196,16 @@ final public class Table {
                }
        }
 
                }
        }
 
-       public IoTString getSpeculative(IoTString key) throws InterruptedException {
-
-               mutex.acquire();
-
-               KeyValue kv = pendingTransSpeculativeTable.get(key);
+       public synchronized IoTString getSpeculative(IoTString key) {
+               KeyValue kv = pendingTransactionSpeculatedKeyValueTable.get(key);
 
                if (kv == null) {
 
                if (kv == null) {
-                       kv = speculativeTable.get(key);
+                       kv = speculatedKeyValueTable.get(key);
                }
 
                if (kv == null) {
                }
 
                if (kv == null) {
-                       kv = commitedTable.get(key);
+                       kv = committedKeyValueTable.get(key);
                }
                }
-               mutex.release();
-
 
                if (kv != null) {
                        return kv.getValue();
 
                if (kv != null) {
                        return kv.getValue();
@@ -296,677 +214,419 @@ final public class Table {
                }
        }
 
                }
        }
 
-       public IoTString getCommittedAtomic(IoTString key) throws InterruptedException {
-
-               mutex.acquire();
-
-               KeyValue kv = commitedTable.get(key);
+       public synchronized IoTString getCommittedAtomic(IoTString key) {
+               KeyValue kv = committedKeyValueTable.get(key);
 
                if (arbitratorTable.get(key) == null) {
                        throw new Error("Key not Found.");
                }
 
                // Make sure new key value pair matches the current arbitrator
 
                if (arbitratorTable.get(key) == null) {
                        throw new Error("Key not Found.");
                }
 
                // Make sure new key value pair matches the current arbitrator
-               if (!pendingTransBuild.checkArbitrator(arbitratorTable.get(key))) {
+               if (!pendingTransactionBuilder.checkArbitrator(arbitratorTable.get(key))) {
                        // TODO: Maybe not throw en error
                        throw new Error("Not all Key Values Match Arbitrator.");
                }
 
                        // TODO: Maybe not throw en error
                        throw new Error("Not all Key Values Match Arbitrator.");
                }
 
-               mutex.release();
-
                if (kv != null) {
                if (kv != null) {
-                       pendingTransBuild.addKVGuard(new KeyValue(key, kv.getValue()));
+                       pendingTransactionBuilder.addKVGuard(new KeyValue(key, kv.getValue()));
                        return kv.getValue();
                } else {
                        return kv.getValue();
                } else {
-                       pendingTransBuild.addKVGuard(new KeyValue(key, null));
+                       pendingTransactionBuilder.addKVGuard(new KeyValue(key, null));
                        return null;
                }
        }
 
                        return null;
                }
        }
 
-       public IoTString getSpeculativeAtomic(IoTString key) throws InterruptedException {
-
-               mutex.acquire();
-
+       public synchronized IoTString getSpeculativeAtomic(IoTString key) {
                if (arbitratorTable.get(key) == null) {
                        throw new Error("Key not Found.");
                }
 
                // Make sure new key value pair matches the current arbitrator
                if (arbitratorTable.get(key) == null) {
                        throw new Error("Key not Found.");
                }
 
                // Make sure new key value pair matches the current arbitrator
-               if (!pendingTransBuild.checkArbitrator(arbitratorTable.get(key))) {
+               if (!pendingTransactionBuilder.checkArbitrator(arbitratorTable.get(key))) {
                        // TODO: Maybe not throw en error
                        throw new Error("Not all Key Values Match Arbitrator.");
                }
 
                        // TODO: Maybe not throw en error
                        throw new Error("Not all Key Values Match Arbitrator.");
                }
 
-               KeyValue kv = pendingTransSpeculativeTable.get(key);
+               KeyValue kv = pendingTransactionSpeculatedKeyValueTable.get(key);
 
                if (kv == null) {
 
                if (kv == null) {
-                       kv = speculativeTable.get(key);
+                       kv = speculatedKeyValueTable.get(key);
                }
 
                if (kv == null) {
                }
 
                if (kv == null) {
-                       kv = commitedTable.get(key);
+                       kv = committedKeyValueTable.get(key);
                }
 
                }
 
-               mutex.release();
-
                if (kv != null) {
                if (kv != null) {
-                       pendingTransBuild.addKVGuard(new KeyValue(key, kv.getValue()));
+                       pendingTransactionBuilder.addKVGuard(new KeyValue(key, kv.getValue()));
                        return kv.getValue();
                } else {
                        return kv.getValue();
                } else {
-                       pendingTransBuild.addKVGuard(new KeyValue(key, null));
+                       pendingTransactionBuilder.addKVGuard(new KeyValue(key, null));
                        return null;
                }
        }
 
                        return null;
                }
        }
 
-       public Pair<Boolean, Boolean> update() throws InterruptedException {
-
-               mutex.acquire();
-
-               boolean gotLatestFromServer = false;
-               boolean didSendLocal = false;
-
+       public synchronized void update()  {
                try {
                try {
-                       Slot[] newslots = cloud.getSlots(sequencenumber + 1);
-                       validateandupdate(newslots, false);
-                       gotLatestFromServer = true;
-
-                       if (!pendingTransQueue.isEmpty()) {
-
-                               // We have a pending transaction so do full insertion
-                               processPendingTrans();
-                       } else {
-
-                               // We dont have a pending transaction so do minimal effort
-                               updateWithNotPendingTrans();
-                       }
-
-                       didSendLocal = true;
-
-
+                       Slot[] newSlots = cloud.getSlots(sequenceNumber + 1);
+                       validateAndUpdate(newSlots, false);
+                       sendToServer(null);
                } catch (Exception e) {
                } catch (Exception e) {
-                       // could not update so do nothing
+                       e.printStackTrace();
                }
                }
-
-
-               mutex.release();
-               return new Pair<Boolean, Boolean>(gotLatestFromServer, didSendLocal);
        }
 
        }
 
-       public Boolean updateFromLocal(long arb) throws InterruptedException {
-               LocalComm lc = localCommunicationChannels.get(arb);
-               if (lc == null) {
-                       // Cant talk directly to arbitrator so cant do anything
-                       return false;
-               }
-
-               byte[] array = new byte[Long.BYTES ];
-               ByteBuffer bbEncode = ByteBuffer.wrap(array);
-               Long lastSeenCommit = lastCommitSeenSeqNumMap.get(arb);
-               if (lastSeenCommit != null) {
-                       bbEncode.putLong(lastSeenCommit);
-               } else {
-                       bbEncode.putLong(0);
-               }
-
-               mutex.acquire();
-               byte[] data = lc.sendDataToLocalDevice(arb, bbEncode.array());
-
-               // Decode the data
-               ByteBuffer bbDecode = ByteBuffer.wrap(data);
-               boolean didCommit = bbDecode.get() == 1;
-               int numberOfCommites = bbDecode.getInt();
-
-               List<Commit> newCommits = new LinkedList<Commit>();
-               for (int i = 0; i < numberOfCommites; i++ ) {
-                       bbDecode.get();
-                       Commit com = (Commit)Commit.decode(null, bbDecode);
-                       newCommits.add(com);
-               }
+       public synchronized boolean createNewKey(IoTString keyName, long machineId)  {
+               while (true) {
+                       if (arbitratorTable.get(keyName) != null) {
+                               // There is already an arbitrator
+                               return false;
+                       }
 
 
-               for (Commit commit : newCommits) {
-                       // Prepare to process the commit
-                       processEntry(commit);
+                       NewKey newKey = new NewKey(null, keyName, machineId);
+                       if (sendToServer(newKey)) {
+                               // If successfully inserted
+                               return true;
+                       }
                }
                }
-
-               boolean didCommitOrSpeculate = proccessAllNewCommits();
-
-               // Go through all uncommitted transactions and kill the ones that are dead
-               deleteDeadUncommittedTransactions();
-
-               // Speculate on key value pairs
-               didCommitOrSpeculate |= createSpeculativeTable();
-               createPendingTransactionSpeculativeTable(didCommitOrSpeculate);
-
-
-               mutex.release();
-
-               return true;
        }
 
        }
 
-       public void startTransaction() throws InterruptedException {
+       public void startTransaction() {
                // Create a new transaction, invalidates any old pending transactions.
                // Create a new transaction, invalidates any old pending transactions.
-               pendingTransBuild = new PendingTransaction();
+               pendingTransactionBuilder = new PendingTransaction(localMachineId);
        }
 
        }
 
-       public void addKV(IoTString key, IoTString value) {
+       public synchronized void addKV(IoTString key, IoTString value) {
 
 
+               // Make sure it is a valid key
                if (arbitratorTable.get(key) == null) {
                        throw new Error("Key not Found.");
                }
 
                // Make sure new key value pair matches the current arbitrator
                if (arbitratorTable.get(key) == null) {
                        throw new Error("Key not Found.");
                }
 
                // Make sure new key value pair matches the current arbitrator
-               if (!pendingTransBuild.checkArbitrator(arbitratorTable.get(key))) {
+               if (!pendingTransactionBuilder.checkArbitrator(arbitratorTable.get(key))) {
                        // TODO: Maybe not throw en error
                        throw new Error("Not all Key Values Match Arbitrator.");
                }
 
                        // TODO: Maybe not throw en error
                        throw new Error("Not all Key Values Match Arbitrator.");
                }
 
+               // Add the key value to this transaction
                KeyValue kv = new KeyValue(key, value);
                KeyValue kv = new KeyValue(key, value);
-               pendingTransBuild.addKV(kv);
+               pendingTransactionBuilder.addKV(kv);
        }
 
        }
 
-       public TransactionStatus commitTransaction() throws InterruptedException {
-
-               if (pendingTransBuild.getKVUpdates().size() == 0) {
+       public synchronized TransactionStatus commitTransaction() {
 
 
+               if (pendingTransactionBuilder.getKVUpdates().size() == 0) {
                        // transaction with no updates will have no effect on the system
                        return new TransactionStatus(TransactionStatus.StatusNoEffect, -1);
                }
 
                        // transaction with no updates will have no effect on the system
                        return new TransactionStatus(TransactionStatus.StatusNoEffect, -1);
                }
 
-               mutex.acquire();
-
-               TransactionStatus transStatus = null;
-
-               if (pendingTransBuild.getArbitrator() != localmachineid) {
-
-                       // set the local sequence number so we can recognize this transaction later
-                       pendingTransBuild.setMachineLocalTransSeqNum(localTransactionSequenceNumber);
-                       localTransactionSequenceNumber++;
-
-                       transStatus = new TransactionStatus(TransactionStatus.StatusPending, pendingTransBuild.getArbitrator());
-                       transactionStatusNotSentMap.put(pendingTransBuild.getMachineLocalTransSeqNum(), transStatus);
-
-                       // Add the pending transaction to the queue
-                       pendingTransQueue.add(pendingTransBuild);
+               // Set the local transaction sequence number and increment
+               pendingTransactionBuilder.setClientLocalSequenceNumber(localTransactionSequenceNumber);
+               localTransactionSequenceNumber++;
 
 
+               // Create the transaction status
+               TransactionStatus transactionStatus = new TransactionStatus(TransactionStatus.StatusPending, pendingTransactionBuilder.getArbitrator());
 
 
-                       for (int i = lastSeenPendingTransactionSpeculateIndex; i < pendingTransQueue.size(); i++) {
-                               PendingTransaction pt = pendingTransQueue.get(i);
+               // Create the new transaction
+               Transaction newTransaction = pendingTransactionBuilder.createTransaction();
+               newTransaction.setTransactionStatus(transactionStatus);
 
 
-                               if (pt.evaluateGuard(commitedTable, speculativeTable, pendingTransSpeculativeTable)) {
-
-                                       lastSeenPendingTransactionSpeculateIndex = i;
-
-                                       for (KeyValue kv : pt.getKVUpdates()) {
-                                               pendingTransSpeculativeTable.put(kv.getKey(), kv);
-                                       }
-
-                               }
-                       }
-               } else {
-                       Transaction ut = new Transaction(null,
-                                                        -1,
-                                                        localmachineid,
-                                                        pendingTransBuild.getArbitrator(),
-                                                        pendingTransBuild.getKVUpdates(),
-                                                        pendingTransBuild.getKVGuard());
-
-                       Pair<Boolean, List<Commit>> retData = doLocalUpdateAndArbitrate(ut, lastCommitSeenSeqNumMap.get(localmachineid));
-
-                       if (retData.getFirst()) {
-                               transStatus = new TransactionStatus(TransactionStatus.StatusCommitted, pendingTransBuild.getArbitrator());
-                       } else {
-                               transStatus = new TransactionStatus(TransactionStatus.StatusAborted, pendingTransBuild.getArbitrator());
-                       }
-               }
-
-               // Try to insert transactions if possible
-               if (!pendingTransQueue.isEmpty()) {
-                       // We have a pending transaction so do full insertion
-                       processPendingTrans();
+               if (pendingTransactionBuilder.getArbitrator() != localMachineId) {
+                       // Add it to the queue and invalidate the builder for safety
+                       pendingTransactionQueue.add(newTransaction);
                } else {
                } else {
-                       try {
-                               // We dont have a pending transaction so do minimal effort
-                               updateWithNotPendingTrans();
-                       } catch (Exception e) {
-                               // Do nothing
-                       }
+                       arbitrateOnLocalTransaction(newTransaction);
+                       updateLiveStateFromLocal();
                }
 
                }
 
-               // reset it so next time is fresh
-               pendingTransBuild = new PendingTransaction();
+               pendingTransactionBuilder = new PendingTransaction(localMachineId);
 
 
+               sendToServer(null);
 
 
-               mutex.release();
-               return transStatus;
+               return transactionStatus;
        }
 
        }
 
-       public boolean createNewKey(IoTString keyName, long machineId) throws ServerException, InterruptedException {
-               try {
-                       mutex.acquire();
+       /**
+        * Get the machine ID for this client
+        */
+       public long getMachineId() {
+               return localMachineId;
+       }
 
 
-                       while (true) {
-                               if (arbitratorTable.get(keyName) != null) {
-                                       // There is already an arbitrator
-                                       mutex.release();
-                                       return false;
-                               }
+       /**
+        * Decrement the number of live slots that we currently have
+        */
+       public void decrementLiveCount() {
+               liveSlotCount--;
+       }
 
 
-                               if (tryput(keyName, machineId, false)) {
-                                       // If successfully inserted
-                                       mutex.release();
-                                       return true;
-                               }
-                       }
-               } catch (ServerException e) {
-                       mutex.release();
-                       throw e;
-               }
+       /**
+        * Recalculate the new resize threshold
+        */
+       private void setResizeThreshold() {
+               int resizeLower = (int) (RESIZE_THRESHOLD * numberOfSlots);
+               bufferResizeThreshold = resizeLower - 1 + random.nextInt(numberOfSlots - resizeLower);
        }
 
        }
 
-       private void processPendingTrans() throws InterruptedException {
+       private boolean sendToServer(NewKey newKey) {
 
 
-               boolean sentAllPending = false;
                try {
                try {
-                       while (!pendingTransQueue.isEmpty()) {
-                               if (tryput( pendingTransQueue.peek(), false)) {
-                                       pendingTransQueue.poll();
-                               }
-                       }
+                       // While we have stuff that needs inserting into the block chain
+                       while ((pendingTransactionQueue.size() > 0) || (pendingSendArbitrationEntries.size() > 0) || (newKey != null)) {
 
 
-                       // if got here then all pending transactions were sent
-                       sentAllPending = true;
-               } catch (Exception e) {
-                       // There was a connection error
-                       sentAllPending = false;
-               }
+                               // try {
+                               //      Thread.sleep(300);
+                               // } catch (Exception e) {
 
 
-               if (!sentAllPending) {
+                               // }
 
 
-                       for (Iterator<PendingTransaction> i = pendingTransQueue.iterator(); i.hasNext(); ) {
-                               PendingTransaction pt = i.next();
-                               LocalComm lc = localCommunicationChannels.get(pt.getArbitrator());
-                               if (lc == null) {
-                                       // Cant talk directly to arbitrator so cant do anything
-                                       continue;
-                               }
+                               // Create the slot
+                               Slot slot = new Slot(this, sequenceNumber + 1, localMachineId, buffer.getSlot(sequenceNumber).getHMAC());
 
 
+                               // Try to fill the slot with data
+                               ThreeTuple<Boolean, Integer, Boolean> fillSlotsReturn = fillSlot(slot, false, newKey);
+                               boolean needsResize = fillSlotsReturn.getFirst();
+                               int newSize = fillSlotsReturn.getSecond();
+                               Boolean insertedNewKey = fillSlotsReturn.getThird();
 
 
-                               Transaction ut = new Transaction(null,
-                                                                -1,
-                                                                localmachineid,
-                                                                pendingTransBuild.getArbitrator(),
-                                                                pendingTransBuild.getKVUpdates(),
-                                                                pendingTransBuild.getKVGuard());
+                               if (needsResize) {
+                                       // Reset which transaction to send
+                                       for (Transaction transaction : transactionPartsSent.keySet()) {
+                                               transaction.resetNextPartToSend();
 
 
+                                               // Set the transaction sequence number back to nothing
+                                               if (!transaction.didSendAPartToServer()) {
+                                                       transaction.setSequenceNumber(-1);
+                                               }
+                                       }
 
 
-                               Pair<Boolean, List<Commit>> retData = sendTransactionToLocal(ut, lc);
+                                       // Clear the sent data since we are trying again
+                                       pendingSendArbitrationEntriesToDelete.clear();
+                                       transactionPartsSent.clear();
 
 
-                               for (Commit commit : retData.getSecond()) {
-                                       // Prepare to process the commit
-                                       processEntry(commit);
+                                       // We needed a resize so try again
+                                       fillSlot(slot, true, newKey);
                                }
 
                                }
 
-                               boolean didCommitOrSpeculate = proccessAllNewCommits();
-
-                               // Go through all uncommitted transactions and kill the ones that are dead
-                               deleteDeadUncommittedTransactions();
+                               // Try to send to the server
+                               Pair<Boolean, Slot[]> sendSlotsReturn = sendSlotsToServer(slot, newSize);
 
 
-                               // Speculate on key value pairs
-                               didCommitOrSpeculate |= createSpeculativeTable();
-                               createPendingTransactionSpeculativeTable(didCommitOrSpeculate);
-
-                               if (retData.getFirst()) {
-                                       TransactionStatus transStatus = transactionStatusNotSentMap.remove(pendingTransBuild.getMachineLocalTransSeqNum());
-                                       if (transStatus != null) {
-                                               transStatus.setStatus(TransactionStatus.StatusCommitted);
-                                       }
+                               if (sendSlotsReturn.getFirst()) {
+                                       // Did insert into the block chain
 
 
-                               } else {
-                                       TransactionStatus transStatus = transactionStatusNotSentMap.remove(pendingTransBuild.getMachineLocalTransSeqNum());
-                                       if (transStatus != null) {
-                                               transStatus.setStatus(TransactionStatus.StatusAborted);
-                                       }
-                               }
-                               i.remove();
-                       }
-               }
-       }
+                                       // New Key was successfully inserted into the block chain so dont want to insert it again
+                                       newKey = null;
 
 
-       private void updateWithNotPendingTrans() throws ServerException, InterruptedException {
-               boolean doEnd = false;
-               boolean needResize = false;
-               while (!doEnd && ((uncommittedTransactionsMap.keySet().size() > 0)  || (pendingCommitsList.size() > 0))   ) {
-                       boolean resize = needResize;
-                       needResize = false;
-
-                       Slot s = new Slot(this, sequencenumber + 1, localmachineid, buffer.getSlot(sequencenumber).getHMAC());
-                       int newsize = 0;
-                       if (liveslotcount > resizethreshold) {
-                               resize = true; //Resize is forced
-                       }
+                                       // Remove the aborts and commit parts that were sent from the pending to send queue
+                                       pendingSendArbitrationEntries.removeAll(pendingSendArbitrationEntriesToDelete);
 
 
-                       if (resize) {
-                               newsize = (int) (numslots * RESIZE_MULTIPLE);
-                               TableStatus status = new TableStatus(s, newsize);
-                               s.addEntry(status);
-                       }
+                                       for (Transaction transaction : transactionPartsSent.keySet()) {
 
 
-                       doRejectedMessages(s);
+                                               // Update which transactions parts still need to be sent
+                                               transaction.removeSentParts(transactionPartsSent.get(transaction));
 
 
-                       ThreeTuple<Boolean, Boolean, Long> retTup = doMandatoryResuce(s, resize);
+                                               // Add the transaction status to the outstanding list
+                                               outstandingTransactionStatus.put(transaction.getSequenceNumber(), transaction.getTransactionStatus());
 
 
-                       // Resize was needed so redo call
-                       if (retTup.getFirst()) {
-                               needResize = true;
-                               continue;
-                       }
+                                               // Update the transaction status
+                                               transaction.getTransactionStatus().setStatus(TransactionStatus.StatusSentPartial);
 
 
-                       // Extract working variables
-                       boolean seenliveslot = retTup.getSecond();
-                       long seqn = retTup.getThird();
+                                               // Check if all the transaction parts were successfully sent and if so then remove it from pending
+                                               if (transaction.didSendAllParts()) {
+                                                       transaction.getTransactionStatus().setStatus(TransactionStatus.StatusSentFully);
+                                                       pendingTransactionQueue.remove(transaction);
+                                               }
+                                       }
+                               } else {
+                                       // Reset which transaction to send
+                                       for (Transaction transaction : transactionPartsSent.keySet()) {
+                                               transaction.resetNextPartToSend();
 
 
-                       // Did need to arbitrate
-                       doEnd = !doArbitration(s);
+                                               // Set the transaction sequence number back to nothing
+                                               if (!transaction.didSendAPartToServer()) {
+                                                       transaction.setSequenceNumber(-1);
+                                               }
+                                       }
+                               }
 
 
-                       doOptionalRescue(s, seenliveslot, seqn, resize);
+                               // Clear the sent data in preparation for next send
+                               pendingSendArbitrationEntriesToDelete.clear();
+                               transactionPartsSent.clear();
 
 
-                       int max = 0;
-                       if (resize) {
-                               max = newsize;
+                               if (sendSlotsReturn.getSecond().length != 0) {
+                                       // insert into the local block chain
+                                       validateAndUpdate(sendSlotsReturn.getSecond(), true);
+                               }
                        }
                        }
+               } catch (ServerException e) {
 
 
-                       Slot[] array = cloud.putSlot(s, max);
-                       if (array == null) {
-                               array = new Slot[] {s};
-                               rejectedmessagelist.clear();
+                       if (e.getType() != ServerException.TypeInputTimeout) {
+                               e.printStackTrace();
 
 
-                               // Delete pending commits that were sent to the cloud
-                               deletePendingCommits();
+                               // Nothing was able to be sent to the server so just clear these data structures
+                               for (Transaction transaction : transactionPartsSent.keySet()) {
+                                       // Set the transaction sequence number back to nothing
+                                       if (!transaction.didSendAPartToServer()) {
+                                               transaction.setSequenceNumber(-1);
+                                       }
+                               }
 
 
-                       }       else {
-                               if (array.length == 0)
-                                       throw new Error("Server Error: Did not send any slots");
-                               rejectedmessagelist.add(s.getSequenceNumber());
-                               doEnd = false;
+                               pendingSendArbitrationEntriesToDelete.clear();
+                               transactionPartsSent.clear();
+                       } else {
+                               // There was a partial send to the server
                        }
                        }
-
-                       /* update data structure */
-                       validateandupdate(array, true);
-               }
-       }
-
-       private Pair<Boolean, List<Commit>> sendTransactionToLocal(Transaction ut, LocalComm lc) throws InterruptedException {
-
-               // encode the request
-               byte[] array = new byte[Long.BYTES + ut.getSize()];
-               ByteBuffer bbEncode = ByteBuffer.wrap(array);
-               Long lastSeenCommit = lastCommitSeenSeqNumMap.get(ut.getArbitrator());
-               if (lastSeenCommit != null) {
-                       bbEncode.putLong(lastSeenCommit);
-               } else {
-                       bbEncode.putLong(0);
                }
                }
-               ut.encode(bbEncode);
 
 
-               byte[] data = lc.sendDataToLocalDevice(ut.getArbitrator(), bbEncode.array());
-
-               // Decode the data
-               ByteBuffer bbDecode = ByteBuffer.wrap(data);
-               boolean didCommit = bbDecode.get() == 1;
-               int numberOfCommites = bbDecode.getInt();
-
-               List<Commit> newCommits = new LinkedList<Commit>();
-               for (int i = 0; i < numberOfCommites; i++ ) {
-                       bbDecode.get();
-                       Commit com = (Commit)Commit.decode(null, bbDecode);
-                       newCommits.add(com);
-               }
-
-               return new Pair<Boolean, List<Commit>>(didCommit, newCommits);
-       }
-
-       public byte[] localCommInput(byte[] data) throws InterruptedException {
-
-
-
-               // Decode the data
-               ByteBuffer bbDecode = ByteBuffer.wrap(data);
-               long lastSeenCommit = bbDecode.getLong();
-
-               Transaction ut = null;
-               if (data.length != Long.BYTES) {
-                       bbDecode.get();
-                       ut = (Transaction)Transaction.decode(null, bbDecode);
-               }
-
-               mutex.acquire();
-               // Do the local update and arbitrate
-               Pair<Boolean, List<Commit>> returnData = doLocalUpdateAndArbitrate(ut, lastSeenCommit);
-               mutex.release();
-
-
-               // Calculate the size of the response
-               int size = Byte.BYTES + Integer.BYTES;
-               for (Commit com : returnData.getSecond()) {
-                       size += com.getSize();
-               }
-
-               // encode the response
-               byte[] array = new byte[size];
-               ByteBuffer bbEncode = ByteBuffer.wrap(array);
-               if (returnData.getFirst()) {
-                       bbEncode.put((byte)1);
-               } else {
-                       bbEncode.put((byte)0);
-               }
-               bbEncode.putInt(returnData.getSecond().size());
-
-               for (Commit com : returnData.getSecond()) {
-                       com.encode(bbEncode);
-               }
-
-               return bbEncode.array();
+               return newKey == null;
        }
 
        }
 
-       private Pair<Boolean, List<Commit>> doLocalUpdateAndArbitrate(Transaction ut, Long lastCommitSeen) {
-
-               List<Commit> returnCommits = new ArrayList<Commit>();
-
-               if ((lastCommitSeenSeqNumMap.get(localmachineid) != null) && (lastCommitSeenSeqNumMap.get(localmachineid) > lastCommitSeen)) {
-                       // There is a commit that the other client has not seen yet
-
-                       Map<Long, Commit> cm = commitMap.get(localmachineid);
-                       if (cm != null) {
+       private Pair<Boolean, Slot[]> sendSlotsToServer(Slot slot, int newSize)  throws ServerException {
 
 
-                               List<Long> commitKeys = new ArrayList<Long>(cm.keySet());
-                               Collections.sort(commitKeys);
+               boolean inserted = true;
 
 
-
-                               for (int i = (commitKeys.size() - 1); i >= 0; i--) {
-                                       Commit com = cm.get(commitKeys.get(i));
-
-                                       if (com.getSequenceNumber() <= lastCommitSeen) {
-                                               break;
-                                       }
-                                       returnCommits.add((Commit)com.getCopy(null));
-                               }
+               Slot[] array = cloud.putSlot(slot, newSize);
+               if (array == null) {
+                       array = new Slot[] {slot};
+                       rejectedSlotList.clear();
+               }       else {
+                       if (array.length == 0) {
+                               throw new Error("Server Error: Did not send any slots");
                        }
                        }
+                       rejectedSlotList.add(slot.getSequenceNumber());
+                       inserted = false;
                }
 
                }
 
-
-               if ((ut == null) || (ut.getArbitrator() != localmachineid)) {
-                       // We are not the arbitrator for that transaction so the other device is talking to the wrong arbitrator
-                       // or there is no transaction to process
-                       return new Pair<Boolean, List<Commit>>(false, returnCommits);
-               }
-
-               if (!ut.evaluateGuard(commitedTable, null)) {
-                       // Guard evaluated as false so return only the commits that the other device has not seen yet
-                       return new Pair<Boolean, List<Commit>>(false, returnCommits);
-               }
-
-               // create the commit
-               Commit commit = new Commit(null,
-                                          -1,
-                                          commitSequenceNumber,
-                                          ut.getArbitrator(),
-                                          ut.getkeyValueUpdateSet());
-               commitSequenceNumber = commitSequenceNumber + 1;
-
-               // Add to the pending commits list
-               pendingCommitsList.add(commit);
-
-               // Add this commit so we can send it back
-               returnCommits.add(commit);
-
-               // Prepare to process the commit
-               processEntry(commit);
-
-               boolean didCommitOrSpeculate = proccessAllNewCommits();
-
-               // Go through all uncommitted transactions and kill the ones that are dead
-               deleteDeadUncommittedTransactions();
-
-               // Speculate on key value pairs
-               didCommitOrSpeculate |= createSpeculativeTable();
-               createPendingTransactionSpeculativeTable(didCommitOrSpeculate);
-
-               return new Pair<Boolean, List<Commit>>(true, returnCommits);
-       }
-
-       public void decrementLiveCount() {
-               liveslotcount--;
-       }
-
-       private void setResizeThreshold() {
-               int resize_lower = (int) (RESIZE_THRESHOLD * numslots);
-               resizethreshold = resize_lower - 1 + random.nextInt(numslots - resize_lower);
+               return new Pair<Boolean, Slot[]>(inserted, array);
        }
 
        }
 
-       private boolean tryput(PendingTransaction pendingTrans, boolean resize) throws ServerException {
-               Slot s = new Slot(this, sequencenumber + 1, localmachineid, buffer.getSlot(sequencenumber).getHMAC());
-
-               int newsize = 0;
-               if (liveslotcount > resizethreshold) {
+       /**
+        * Returns false if a resize was needed
+        */
+       private ThreeTuple<Boolean, Integer, Boolean> fillSlot(Slot slot, boolean resize, NewKey newKeyEntry) {
+               int newSize = 0;
+               if (liveSlotCount > bufferResizeThreshold) {
                        resize = true; //Resize is forced
                }
 
                if (resize) {
                        resize = true; //Resize is forced
                }
 
                if (resize) {
-                       newsize = (int) (numslots * RESIZE_MULTIPLE);
-                       TableStatus status = new TableStatus(s, newsize);
-                       s.addEntry(status);
+                       newSize = (int) (numberOfSlots * RESIZE_MULTIPLE);
+                       TableStatus status = new TableStatus(slot, newSize);
+                       slot.addEntry(status);
                }
 
                }
 
-               doRejectedMessages(s);
+               // Fill with rejected slots first before doing anything else
+               doRejectedMessages(slot);
 
 
-               ThreeTuple<Boolean, Boolean, Long> retTup = doMandatoryResuce(s, resize);
-
-               // Resize was needed so redo call
-               if (retTup.getFirst()) {
-                       return tryput(pendingTrans, true);
-               }
+               // Do mandatory rescue of entries
+               ThreeTuple<Boolean, Boolean, Long> mandatoryRescueReturn = doMandatoryResuce(slot, resize);
 
                // Extract working variables
 
                // Extract working variables
-               boolean seenliveslot = retTup.getSecond();
-               long seqn = retTup.getThird();
+               boolean needsResize = mandatoryRescueReturn.getFirst();
+               boolean seenLiveSlot = mandatoryRescueReturn.getSecond();
+               long currentRescueSequenceNumber = mandatoryRescueReturn.getThird();
 
 
-               doArbitration(s);
-
-               Transaction trans = new Transaction(s,
-                                                   s.getSequenceNumber(),
-                                                   localmachineid,
-                                                   pendingTrans.getArbitrator(),
-                                                   pendingTrans.getKVUpdates(),
-                                                   pendingTrans.getKVGuard());
-               boolean insertedTrans = false;
-               if (s.hasSpace(trans)) {
-                       s.addEntry(trans);
-                       insertedTrans = true;
+               if (needsResize && !resize) {
+                       // We need to resize but we are not resizing so return false
+                       return new ThreeTuple<Boolean, Integer, Boolean>(true, null, null);
                }
 
                }
 
-               doOptionalRescue(s, seenliveslot, seqn, resize);
-               Pair<Boolean, Slot[]> sendRetData = doSendSlots(s, insertedTrans, resize, newsize);
-
-               if (sendRetData.getFirst()) {
-                       // update the status and change what the sequence number is for the
-                       TransactionStatus transStatus = transactionStatusNotSentMap.remove(pendingTrans.getMachineLocalTransSeqNum());
-                       transStatus.setStatus(TransactionStatus.StatusSent);
-                       transStatus.setSentTransaction();
-                       transactionStatusMap.put(trans.getSequenceNumber(), transStatus);
+               boolean inserted = false;
+               if (newKeyEntry != null) {
+                       newKeyEntry.setSlot(slot);
+                       if (slot.hasSpace(newKeyEntry)) {
+                               slot.addEntry(newKeyEntry);
+                               inserted = true;
+                       }
                }
 
                }
 
+               // Clear the transactions, aborts and commits that were sent previously
+               transactionPartsSent.clear();
+               pendingSendArbitrationEntriesToDelete.clear();
 
 
-               if (sendRetData.getSecond().length != 0) {
-                       // insert into the local block chain
-                       validateandupdate(sendRetData.getSecond(), true);
-               }
+               // Insert pending arbitration data
+               for (Entry arbitrationData : pendingSendArbitrationEntries) {
 
 
-               return sendRetData.getFirst();
-       }
+                       // If it is an abort then we need to set some information
+                       if (arbitrationData instanceof Abort) {
+                               ((Abort)arbitrationData).setSequenceNumber(slot.getSequenceNumber());
+                       }
 
 
-       private boolean tryput(IoTString keyName, long arbMachineid, boolean resize) throws ServerException {
-               Slot s = new Slot(this, sequencenumber + 1, localmachineid, buffer.getSlot(sequencenumber).getHMAC());
-               int newsize = 0;
-               if (liveslotcount > resizethreshold) {
-                       resize = true; //Resize is forced
-               }
+                       if (!slot.hasSpace(arbitrationData)) {
+                               // No space so cant do anything else with these data entries
+                               break;
+                       }
 
 
-               if (resize) {
-                       newsize = (int) (numslots * RESIZE_MULTIPLE);
-                       TableStatus status = new TableStatus(s, newsize);
-                       s.addEntry(status);
+                       // Add to this current slot and add it to entries to delete
+                       slot.addEntry(arbitrationData);
+                       pendingSendArbitrationEntriesToDelete.add(arbitrationData);
                }
 
                }
 
-               doRejectedMessages(s);
-               ThreeTuple<Boolean, Boolean, Long> retTup = doMandatoryResuce(s, resize);
+               // Insert as many transactions as possible while keeping order
+               for (Transaction transaction : pendingTransactionQueue) {
 
 
-               // Resize was needed so redo call
-               if (retTup.getFirst()) {
-                       return tryput(keyName, arbMachineid, true);
-               }
+                       // Set the transaction sequence number if it has yet to be inserted into the block chain
+                       if (!transaction.didSendAPartToServer()) {
+                               transaction.setSequenceNumber(slot.getSequenceNumber());
+                       }
 
 
-               // Extract working variables
-               boolean seenliveslot = retTup.getSecond();
-               long seqn = retTup.getThird();
+                       boolean ranOutOfSpace = false;
 
 
-               doArbitration(s);
+                       while (true) {
+                               TransactionPart part = transaction.getNextPartToSend();
+
+                               if (part == null) {
+                                       // Ran out of parts to send for this transaction so move on
+                                       break;
+                               }
 
 
-               NewKey newKey = new NewKey(s, keyName, arbMachineid);
+                               if (slot.hasSpace(part)) {
+                                       slot.addEntry(part);
 
 
-               boolean insertedNewKey = false;
-               if (s.hasSpace(newKey)) {
-                       s.addEntry(newKey);
-                       insertedNewKey = true;
-               }
+                                       List<Integer> partsSent = transactionPartsSent.get(transaction);
+                                       if (partsSent == null) {
+                                               partsSent = new ArrayList<Integer>();
+                                               transactionPartsSent.put(transaction, partsSent);
+                                       }
+
+                                       partsSent.add(part.getPartNumber());
+                                       transactionPartsSent.put(transaction, partsSent);
 
 
-               doOptionalRescue(s, seenliveslot, seqn, resize);
-               Pair<Boolean, Slot[]> sendRetData = doSendSlots(s, insertedNewKey, resize, newsize);
+                               } else {
+                                       ranOutOfSpace = true;
+                                       break;
+                               }
+                       }
 
 
-               if (sendRetData.getSecond().length != 0) {
-                       // insert into the local block chain
-                       validateandupdate(sendRetData.getSecond(), true);
+                       if (ranOutOfSpace) {
+                               break;
+                       }
                }
 
                }
 
-               return sendRetData.getFirst();
+               // Fill the remainder of the slot with rescue data
+               doOptionalRescue(slot, seenLiveSlot, currentRescueSequenceNumber, resize);
+
+               return new ThreeTuple<Boolean, Integer, Boolean>(false, newSize, inserted);
        }
 
        private void doRejectedMessages(Slot s) {
        }
 
        private void doRejectedMessages(Slot s) {
-               if (! rejectedmessagelist.isEmpty()) {
+               if (! rejectedSlotList.isEmpty()) {
                        /* TODO: We should avoid generating a rejected message entry if
                         * there is already a sufficient entry in the queue (e.g.,
                         * equalsto value of true and same sequence number).  */
 
                        /* TODO: We should avoid generating a rejected message entry if
                         * there is already a sufficient entry in the queue (e.g.,
                         * equalsto value of true and same sequence number).  */
 
-                       long old_seqn = rejectedmessagelist.firstElement();
-                       if (rejectedmessagelist.size() > REJECTED_THRESHOLD) {
-                               long new_seqn = rejectedmessagelist.lastElement();
-                               RejectedMessage rm = new RejectedMessage(s, localmachineid, old_seqn, new_seqn, false);
+                       long old_seqn = rejectedSlotList.firstElement();
+                       if (rejectedSlotList.size() > REJECTED_THRESHOLD) {
+                               long new_seqn = rejectedSlotList.lastElement();
+                               RejectedMessage rm = new RejectedMessage(s, localMachineId, old_seqn, new_seqn, false);
                                s.addEntry(rm);
                        } else {
                                long prev_seqn = -1;
                                int i = 0;
                                /* Go through list of missing messages */
                                s.addEntry(rm);
                        } else {
                                long prev_seqn = -1;
                                int i = 0;
                                /* Go through list of missing messages */
-                               for (; i < rejectedmessagelist.size(); i++) {
-                                       long curr_seqn = rejectedmessagelist.get(i);
+                               for (; i < rejectedSlotList.size(); i++) {
+                                       long curr_seqn = rejectedSlotList.get(i);
                                        Slot s_msg = buffer.getSlot(curr_seqn);
                                        if (s_msg != null)
                                                break;
                                        Slot s_msg = buffer.getSlot(curr_seqn);
                                        if (s_msg != null)
                                                break;
@@ -974,12 +634,12 @@ final public class Table {
                                }
                                /* Generate rejected message entry for missing messages */
                                if (prev_seqn != -1) {
                                }
                                /* Generate rejected message entry for missing messages */
                                if (prev_seqn != -1) {
-                                       RejectedMessage rm = new RejectedMessage(s, localmachineid, old_seqn, prev_seqn, false);
+                                       RejectedMessage rm = new RejectedMessage(s, localMachineId, old_seqn, prev_seqn, false);
                                        s.addEntry(rm);
                                }
                                /* Generate rejected message entries for present messages */
                                        s.addEntry(rm);
                                }
                                /* Generate rejected message entries for present messages */
-                               for (; i < rejectedmessagelist.size(); i++) {
-                                       long curr_seqn = rejectedmessagelist.get(i);
+                               for (; i < rejectedSlotList.size(); i++) {
+                                       long curr_seqn = rejectedSlotList.get(i);
                                        Slot s_msg = buffer.getSlot(curr_seqn);
                                        long machineid = s_msg.getMachineID();
                                        RejectedMessage rm = new RejectedMessage(s, machineid, curr_seqn, curr_seqn, true);
                                        Slot s_msg = buffer.getSlot(curr_seqn);
                                        long machineid = s_msg.getMachineID();
                                        RejectedMessage rm = new RejectedMessage(s, machineid, curr_seqn, curr_seqn, true);
@@ -989,124 +649,54 @@ final public class Table {
                }
        }
 
                }
        }
 
-       private ThreeTuple<Boolean, Boolean, Long> doMandatoryResuce(Slot s, boolean resize) {
-               long newestseqnum = buffer.getNewestSeqNum();
-               long oldestseqnum = buffer.getOldestSeqNum();
-               if (lastliveslotseqn < oldestseqnum)
-                       lastliveslotseqn = oldestseqnum;
+       private ThreeTuple<Boolean, Boolean, Long> doMandatoryResuce(Slot slot, boolean resize) {
+               long newestSequenceNumber = buffer.getNewestSeqNum();
+               long oldestSequenceNumber = buffer.getOldestSeqNum();
+               if (oldestLiveSlotSequenceNumver < oldestSequenceNumber) {
+                       oldestLiveSlotSequenceNumver = oldestSequenceNumber;
+               }
 
 
-               long seqn = lastliveslotseqn;
-               boolean seenliveslot = false;
-               long firstiffull = newestseqnum + 1 - numslots; // smallest seq number in the buffer if it is full
-               long threshold = firstiffull + FREE_SLOTS;      // we want the buffer to be clear of live entries up to this point
+               long currentSequenceNumber = oldestLiveSlotSequenceNumver;
+               boolean seenLiveSlot = false;
+               long firstIfFull = newestSequenceNumber + 1 - numberOfSlots;    // smallest seq number in the buffer if it is full
+               long threshold = firstIfFull + FREE_SLOTS;      // we want the buffer to be clear of live entries up to this point
 
 
                // Mandatory Rescue
 
 
                // Mandatory Rescue
-               for (; seqn < threshold; seqn++) {
-                       Slot prevslot = buffer.getSlot(seqn);
+               for (; currentSequenceNumber < threshold; currentSequenceNumber++) {
+                       Slot previousSlot = buffer.getSlot(currentSequenceNumber);
                        // Push slot number forward
                        // Push slot number forward
-                       if (! seenliveslot)
-                               lastliveslotseqn = seqn;
+                       if (! seenLiveSlot) {
+                               oldestLiveSlotSequenceNumver = currentSequenceNumber;
+                       }
 
 
-                       if (! prevslot.isLive())
+                       if (!previousSlot.isLive()) {
                                continue;
                                continue;
-                       seenliveslot = true;
-                       Vector<Entry> liveentries = prevslot.getLiveEntries(resize);
-                       for (Entry liveentry : liveentries) {
-                               if (s.hasSpace(liveentry)) {
-                                       s.addEntry(liveentry);
-                               } else if (seqn == firstiffull) { //if there's no space but the entry is about to fall off the queue
-                                       if (!resize) {
-                                               System.out.println("B"); //?
-                                               return new ThreeTuple<Boolean, Boolean, Long>(true, seenliveslot, seqn);
-                                       }
-                               }
                        }
                        }
-               }
 
 
-               // Did not resize
-               return new ThreeTuple<Boolean, Boolean, Long>(false, seenliveslot, seqn);
-       }
+                       // We have seen a live slot
+                       seenLiveSlot = true;
 
 
-       private boolean doArbitration(Slot s) {
+                       // Get all the live entries for a slot
+                       Vector<Entry> liveEntries = previousSlot.getLiveEntries(resize);
 
 
-               // flag whether we have finished all arbitration
-               boolean stillHasArbitration = false;
+                       // Iterate over all the live entries and try to rescue them
+                       for (Entry liveEntry : liveEntries) {
+                               if (slot.hasSpace(liveEntry)) {
 
 
-               pendingCommitsToDelete.clear();
+                                       // Enough space to rescue the entry
+                                       slot.addEntry(liveEntry);
+                               } else if (currentSequenceNumber == firstIfFull) {
+                                       //if there's no space but the entry is about to fall off the queue
+                                       System.out.println("B"); //?
+                                       return new ThreeTuple<Boolean, Boolean, Long>(true, seenLiveSlot, currentSequenceNumber);
 
 
-               // First add queue commits
-               for (Commit commit : pendingCommitsList) {
-                       if (s.hasSpace(commit)) {
-                               s.addEntry(commit);
-                               pendingCommitsToDelete.add(commit);
-                       } else {
-                               // Ran out of space so move on but still not done
-                               stillHasArbitration = true;
-                               return stillHasArbitration;
+                               }
                        }
                }
 
                        }
                }
 
-               // Arbitrate
-               Map<IoTString, KeyValue> speculativeTableTmp = new HashMap<IoTString, KeyValue>();
-               List<Long> transSeqNums = new ArrayList<Long>(uncommittedTransactionsMap.keySet());
-
-               // Sort from oldest to newest
-               Collections.sort(transSeqNums);
-
-               for (Long transNum : transSeqNums) {
-                       Transaction ut = uncommittedTransactionsMap.get(transNum);
-
-                       // Check if this machine arbitrates for this transaction
-                       if (ut.getArbitrator() != localmachineid ) {
-                               continue;
-                       }
-
-                       // we did have something to arbitrate on
-                       stillHasArbitration = true;
-
-                       Entry newEntry = null;
-
-                       if (ut.evaluateGuard(commitedTable, speculativeTableTmp)) {
-                               // Guard evaluated as true
-
-                               // update the local tmp current key set
-                               for (KeyValue kv : ut.getkeyValueUpdateSet()) {
-                                       speculativeTableTmp.put(kv.getKey(), kv);
-                               }
-
-                               // create the commit
-                               newEntry = new Commit(s,
-                                                     ut.getSequenceNumber(),
-                                                     commitSequenceNumber,
-                                                     ut.getArbitrator(),
-                                                     ut.getkeyValueUpdateSet());
-                               commitSequenceNumber = commitSequenceNumber + 1;
-                       } else {
-                               // Guard was false
-
-                               // create the abort
-                               newEntry = new Abort(s,
-                                                    ut.getSequenceNumber(),
-                                                    ut.getMachineID(),
-                                                    ut.getArbitrator());
-                       }
-
-                       if ((newEntry != null) && s.hasSpace(newEntry)) {
-                               s.addEntry(newEntry);
-                       } else {
-                               break;
-                       }
-               }
-
-               return stillHasArbitration;
-       }
-
-       private void deletePendingCommits() {
-               for (Commit com : pendingCommitsToDelete) {
-                       pendingCommitsList.remove(com);
-               }
-               pendingCommitsToDelete.clear();
+               // Did not resize
+               return new ThreeTuple<Boolean, Boolean, Long>(false, seenLiveSlot, currentSequenceNumber);
        }
 
        private void  doOptionalRescue(Slot s, boolean seenliveslot, long seqn, boolean resize) {
        }
 
        private void  doOptionalRescue(Slot s, boolean seenliveslot, long seqn, boolean resize) {
@@ -1120,7 +710,7 @@ final public class Table {
                        Slot prevslot = buffer.getSlot(seqn);
                        //Push slot number forward
                        if (!seenliveslot)
                        Slot prevslot = buffer.getSlot(seqn);
                        //Push slot number forward
                        if (!seenliveslot)
-                               lastliveslotseqn = seqn;
+                               oldestLiveSlotSequenceNumver = seqn;
 
                        if (!prevslot.isLive())
                                continue;
 
                        if (!prevslot.isLive())
                                continue;
@@ -1138,501 +728,943 @@ final public class Table {
                }
        }
 
                }
        }
 
-       private Pair<Boolean, Slot[]> doSendSlots(Slot s, boolean inserted, boolean resize, int newsize)  throws ServerException {
-               int max = 0;
-               if (resize)
-                       max = newsize;
-
-               Slot[] array = cloud.putSlot(s, max);
-               if (array == null) {
-                       array = new Slot[] {s};
-                       rejectedmessagelist.clear();
+       /**
+        * Checks for malicious activity and updates the local copy of the block chain.
+        */
+       private void validateAndUpdate(Slot[] newSlots, boolean acceptUpdatesToLocal) {
 
 
-                       // Delete pending commits that were sent to the cloud
-                       deletePendingCommits();
-               }       else {
-                       // if (array.length == 0)
-                       // throw new Error("Server Error: Did not send any slots");
-                       rejectedmessagelist.add(s.getSequenceNumber());
-                       inserted = false;
+               // The cloud communication layer has checked slot HMACs already before decoding
+               if (newSlots.length == 0) {
+                       return;
                }
 
                }
 
-               return new Pair<Boolean, Slot[]>(inserted, array);
-       }
-
-       private void validateandupdate(Slot[] newslots, boolean acceptupdatestolocal) {
-               /* The cloud communication layer has checked slot HMACs already
-                        before decoding */
-               if (newslots.length == 0) return;
-
                // Reset the table status declared sizes
                smallestTableStatusSeen = -1;
                largestTableStatusSeen = -1;
 
                // Reset the table status declared sizes
                smallestTableStatusSeen = -1;
                largestTableStatusSeen = -1;
 
-               long firstseqnum = newslots[0].getSequenceNumber();
-               if (firstseqnum <= sequencenumber) {
+
+               // Make sure all slots are newer than the last largest slot this client has seen
+               long firstSeqNum = newSlots[0].getSequenceNumber();
+               if (firstSeqNum <= sequenceNumber) {
                        throw new Error("Server Error: Sent older slots!");
                }
 
                        throw new Error("Server Error: Sent older slots!");
                }
 
-               SlotIndexer indexer = new SlotIndexer(newslots, buffer);
-               checkHMACChain(indexer, newslots);
+               // Create an object that can access both new slots and slots in our local chain
+               // without committing slots to our local chain
+               SlotIndexer indexer = new SlotIndexer(newSlots, buffer);
+
+               // Check that the HMAC chain is not broken
+               checkHMACChain(indexer, newSlots);
 
 
-               HashSet<Long> machineSet = new HashSet<Long>(lastmessagetable.keySet()); //
+               // Set to keep track of messages from clients
+               HashSet<Long> machineSet = new HashSet<Long>(lastMessageTable.keySet());
 
 
-               // initExpectedSize(firstseqnum);
-               for (Slot slot : newslots) {
-                       processSlot(indexer, slot, acceptupdatestolocal, machineSet);
-                       // updateExpectedSize();
+               // Process each slots data
+               for (Slot slot : newSlots) {
+                       processSlot(indexer, slot, acceptUpdatesToLocal, machineSet);
                }
 
                }
 
-               /* If there is a gap, check to see if the server sent us everything. */
-               if (firstseqnum != (sequencenumber + 1)) {
+               // If there is a gap, check to see if the server sent us everything.
+               if (firstSeqNum != (sequenceNumber + 1)) {
 
 
-                       // TODO: Check size
-                       checkNumSlots(newslots.length);
+                       // Check the size of the slots that were sent down by the server.
+                       // Can only check the size if there was a gap
+                       checkNumSlots(newSlots.length);
+
+                       // Since there was a gap every machine must have pushed a slot or must have
+                       // a last message message.  If not then the server is hiding slots
                        if (!machineSet.isEmpty()) {
                                throw new Error("Missing record for machines: " + machineSet);
                        }
                }
 
                        if (!machineSet.isEmpty()) {
                                throw new Error("Missing record for machines: " + machineSet);
                        }
                }
 
-
+               // Update the size of our local block chain.
                commitNewMaxSize();
 
                commitNewMaxSize();
 
-               /* Commit new to slots. */
-               for (Slot slot : newslots) {
+               // Commit new to slots to the local block chain.
+               for (Slot slot : newSlots) {
+
+                       // Insert this slot into our local block chain copy.
                        buffer.putSlot(slot);
                        buffer.putSlot(slot);
-                       liveslotcount++;
+
+                       // Keep track of how many slots are currently live (have live data in them).
+                       liveSlotCount++;
                }
                }
-               sequencenumber = newslots[newslots.length - 1].getSequenceNumber();
 
 
-               // Process all on key value pairs
-               boolean didCommitOrSpeculate = proccessAllNewCommits();
+               // Get the sequence number of the latest slot in the system
+               sequenceNumber = newSlots[newSlots.length - 1].getSequenceNumber();
+
+               updateLiveStateFromServer();
+       }
+
+       private void updateLiveStateFromServer() {
+               // Process the new transaction parts
+               processNewTransactionParts();
+
+               // Do arbitration on new transactions that were received
+               arbitrateFromServer();
 
 
-               // Go through all uncommitted transactions and kill the ones that are dead
-               deleteDeadUncommittedTransactions();
+               // Update all the committed keys
+               boolean didCommitOrSpeculate = updateCommittedTable();
 
 
-               // Speculate on key value pairs
-               didCommitOrSpeculate |= createSpeculativeTable();
+               // Delete the transactions that are now dead
+               updateLiveTransactionsAndStatus();
 
 
-               createPendingTransactionSpeculativeTable(didCommitOrSpeculate);
+               // Do speculations
+               didCommitOrSpeculate |= updateSpeculativeTable(didCommitOrSpeculate);
+               updatePendingTransactionSpeculativeTable(didCommitOrSpeculate);
        }
 
        }
 
-       private boolean proccessAllNewCommits() {
-               // Process only if there are commit
-               if (newCommitMap.keySet().size() == 0) {
-                       return false;
+       private void updateLiveStateFromLocal() {
+               // Update all the committed keys
+               boolean didCommitOrSpeculate = updateCommittedTable();
+
+               // Delete the transactions that are now dead
+               updateLiveTransactionsAndStatus();
+
+               // Do speculations
+               didCommitOrSpeculate |= updateSpeculativeTable(didCommitOrSpeculate);
+               updatePendingTransactionSpeculativeTable(didCommitOrSpeculate);
+       }
+
+       /**
+        * Check the size of the block chain to make sure there are enough slots sent back by the server.
+        * This is only called when we have a gap between the slots that we have locally and the slots
+        * sent by the server therefore in the slots sent by the server there will be at least 1 Table
+        * status message
+        */
+       private void checkNumSlots(int numberOfSlots) {
+
+               // We only have 1 size so we must have this many slots
+               if (largestTableStatusSeen == smallestTableStatusSeen) {
+                       if (numberOfSlots != smallestTableStatusSeen) {
+                               throw new Error("Server Error: Server did not send all slots.  Expected: " + smallestTableStatusSeen + " Received:" + numberOfSlots);
+                       }
+               } else {
+                       // We have more than 1
+                       if (numberOfSlots < smallestTableStatusSeen) {
+                               throw new Error("Server Error: Server did not send all slots.  Expected at least: " + smallestTableStatusSeen + " Received:" + numberOfSlots);
+                       }
                }
                }
-               boolean didProcessNewCommit = false;
+       }
 
 
-               for (Long arb : newCommitMap.keySet()) {
+       /**
+        * Update the size of of the local buffer if it is needed.
+        */
+       private void commitNewMaxSize() {
 
 
-                       List<Long> commitSeqNums = new ArrayList<Long>(newCommitMap.get(arb).keySet());
+               int currMaxSize = 0;
 
 
-                       // Sort from oldest to newest commit
-                       Collections.sort(commitSeqNums);
+               if (largestTableStatusSeen == -1) {
+                       // No table status seen so the current max size does not change
+                       currMaxSize = numberOfSlots;
+               } else {
+                       currMaxSize = largestTableStatusSeen;
+               }
 
 
-                       // Go through each new commit one by one
-                       for (Long entrySeqNum : commitSeqNums) {
-                               Commit entry = newCommitMap.get(arb).get(entrySeqNum);
+               // Resize the local slot buffer
+               if (numberOfSlots != currMaxSize) {
+                       buffer.resize(currMaxSize);
+               }
 
 
-                               long lastCommitSeenSeqNum = -1;
-                               if (lastCommitSeenSeqNumMap.get(entry.getTransArbitrator()) != null) {
-                                       lastCommitSeenSeqNum = lastCommitSeenSeqNumMap.get(entry.getTransArbitrator());
-                               }
+               // Change the number of local slots to the new size
+               numberOfSlots = currMaxSize;
 
 
-                               if (entry.getSequenceNumber() <= lastCommitSeenSeqNum) {
-                                       Map<Long, Commit> cm = commitMap.get(arb);
-                                       if (cm == null) {
-                                               cm = new HashMap<Long, Commit>();
-                                       }
+               // Recalculate the resize threshold since the size of the local buffer has changed
+               setResizeThreshold();
+       }
 
 
-                                       Commit prevCommit = cm.put(entry.getSequenceNumber(), entry);
-                                       commitMap.put(arb, cm);
+       /**
+        * Process the new transaction parts from this latest round of slots received from the server
+        */
+       private void processNewTransactionParts() {
 
 
-                                       if (prevCommit != null) {
-                                               prevCommit.setDead();
+               if (newTransactionParts.size() == 0) {
+                       // Nothing new to process
+                       return;
+               }
 
 
-                                               for (KeyValue kv : prevCommit.getkeyValueUpdateSet()) {
-                                                       committedMapByKey.put(kv.getKey(), entry);
-                                               }
-                                       }
+               // Iterate through all the machine Ids that we received new parts for
+               for (Long machineId : newTransactionParts.keySet()) {
+                       Map<Pair<Long, Integer>, TransactionPart> parts = newTransactionParts.get(machineId);
+
+                       // Iterate through all the parts for that machine Id
+                       for (Pair<Long, Integer> partId : parts.keySet()) {
+                               TransactionPart part = parts.get(partId);
 
 
+                               Long lastTransactionNumber = lastArbitratedTransactionNumberByArbitratorTable.get(part.getArbitratorId());
+                               if ((lastTransactionNumber != null) && (lastTransactionNumber >= part.getSequenceNumber())) {
+                                       // Set dead the transaction part
+                                       part.setDead();
                                        continue;
                                }
 
                                        continue;
                                }
 
-                               Set<Commit> commitsToEditSet = new HashSet<Commit>();
+                               // Get the transaction object for that sequence number
+                               Transaction transaction = liveTransactionBySequenceNumberTable.get(part.getSequenceNumber());
+
+                               if (transaction == null) {
+                                       // This is a new transaction that we dont have so make a new one
+                                       transaction = new Transaction();
 
 
-                               for (KeyValue kv : entry.getkeyValueUpdateSet()) {
-                                       commitsToEditSet.add(committedMapByKey.get(kv.getKey()));
+                                       // Insert this new transaction into the live tables
+                                       liveTransactionBySequenceNumberTable.put(part.getSequenceNumber(), transaction);
+                                       liveTransactionByTransactionIdTable.put(part.getTransactionId(), transaction);
                                }
 
                                }
 
-                               commitsToEditSet.remove(null);
+                               // Add that part to the transaction
+                               transaction.addPartDecode(part);
+                       }
+               }
 
 
-                               for (Commit prevCommit : commitsToEditSet) {
+               // Clear all the new transaction parts in preparation for the next time the server sends slots
+               newTransactionParts.clear();
+       }
 
 
-                                       Set<KeyValue> deletedKV = prevCommit.updateLiveKeys(entry.getkeyValueUpdateSet());
+       public void arbitrateFromServer() {
 
 
-                                       if (!prevCommit.isLive()) {
-                                               Map<Long, Commit> cm = commitMap.get(arb);
+               if (liveTransactionBySequenceNumberTable.size() == 0) {
+                       // Nothing to arbitrate on so move on
+                       return;
+               }
 
 
-                                               // remove it from the map so that it can be set as dead
-                                               if (cm != null) {
-                                                       cm.remove(prevCommit.getSequenceNumber());
-                                                       commitMap.put(arb, cm);
-                                               }
-                                       }
-                               }
+               // Get the transaction sequence numbers and sort from oldest to newest
+               List<Long> transactionSequenceNumbers = new ArrayList<Long>(liveTransactionBySequenceNumberTable.keySet());
+               Collections.sort(transactionSequenceNumbers);
 
 
-                               // Add the new commit
-                               Map<Long, Commit> cm = commitMap.get(arb);
-                               if (cm == null) {
-                                       cm = new HashMap<Long, Commit>();
-                               }
-                               cm.put(entry.getSequenceNumber(), entry);
-                               commitMap.put(arb, cm);
+               // Collection of key value pairs that are
+               Map<IoTString, KeyValue> speculativeTableTmp = new HashMap<IoTString, KeyValue>();
 
 
-                               lastCommitSeenSeqNumMap.put(entry.getTransArbitrator(), entry.getSequenceNumber());
+               // The last transaction arbitrated on
+               long lastTransactionCommitted = -1;
 
 
-                               // set the trans sequence number if we are able to
-                               if (entry.getTransSequenceNumber() != -1) {
-                                       lastCommitSeenTransSeqNumMap.put(entry.getTransArbitrator(), entry.getTransSequenceNumber());
-                               }
+               for (Long transactionSequenceNumber : transactionSequenceNumbers) {
+                       Transaction transaction = liveTransactionBySequenceNumberTable.get(transactionSequenceNumber);
 
 
-                               didProcessNewCommit = true;
+                       // Check if this machine arbitrates for this transaction if not then we cant arbitrate this transaction
+                       if (transaction.getArbitrator() != localMachineId) {
+                               continue;
+                       }
+
+
+                       if (!transaction.isComplete()) {
+                               // Will arbitrate in incorrect order if we continue so just break
+                               // Most likely this
+                               break;
+                       }
 
 
-                               // Update the committed table list
-                               for (KeyValue kv : entry.getkeyValueUpdateSet()) {
-                                       IoTString key = kv.getKey();
-                                       commitedTable.put(key, kv);
-                                       committedMapByKey.put(key, entry);
+
+                       if (transaction.evaluateGuard(committedKeyValueTable, speculativeTableTmp, null)) {
+                               // Guard evaluated as true
+
+                               // Update the local changes so we can make the commit
+                               for (KeyValue kv : transaction.getKeyValueUpdateSet()) {
+                                       speculativeTableTmp.put(kv.getKey(), kv);
                                }
                                }
+
+                               // Update what the last transaction committed was for use in batch commit
+                               lastTransactionCommitted = transaction.getSequenceNumber();
+
+                       } else {
+                               // Guard evaluated was false so create abort
+
+                               // Create the abort
+                               Abort newAbort = new Abort(null,
+                                                          transaction.getClientLocalSequenceNumber(),
+                                                          transaction.getSequenceNumber(),
+                                                          transaction.getMachineId(),
+                                                          transaction.getArbitrator());
+
+                               // Add the abort to the queue of aborts to send out
+                               pendingSendArbitrationEntries.add(newAbort);
+
+                               // Insert the abort so we can process
+                               processEntry(newAbort);
                        }
                }
                        }
                }
-               // Clear the new commits storage so we can use it later
-               newCommitMap.clear();
 
 
+               // If there is something to commit
+               if (speculativeTableTmp.size() != 0) {
 
 
-               // go through all saved transactions and update the status of those that can be updated
-               for (Iterator<Map.Entry<Long, TransactionStatus>> i = transactionStatusMap.entrySet().iterator(); i.hasNext();) {
-                       Map.Entry<Long, TransactionStatus> entry = i.next();
-                       long seqnum = entry.getKey();
-                       TransactionStatus status = entry.getValue();
+                       // Create the commit and increment the commit sequence number
+                       Commit newCommit = new Commit(localCommitSequenceNumber, localMachineId, lastTransactionCommitted);
+                       localCommitSequenceNumber++;
 
 
-                       if (status.getSentTransaction()) {
+                       // Add all the new keys to the commit
+                       for (KeyValue kv : speculativeTableTmp.values()) {
+                               newCommit.addKV(kv);
+                       }
 
 
-                               Long commitSeqNum = lastCommitSeenTransSeqNumMap.get(status.getArbitrator());
-                               Long abortSeqNum = lastAbortSeenSeqNumMap.get(status.getArbitrator());
+                       // create the commit parts
+                       newCommit.createCommitParts();
 
 
-                               if (((commitSeqNum != null) && (seqnum <= commitSeqNum)) ||
-                                       ((abortSeqNum != null) && (seqnum <= abortSeqNum))) {
-                                       status.setStatus(TransactionStatus.StatusCommitted);
-                                       i.remove();
-                               }
+                       // Append all the commit parts to the end of the pending queue waiting for sending to the server
+                       pendingSendArbitrationEntries.addAll(newCommit.getParts().values());
+
+                       // Insert the commit so we can process it
+                       for (CommitPart commitPart : newCommit.getParts().values()) {
+                               processEntry(commitPart);
                        }
                }
                        }
                }
-
-               return didProcessNewCommit;
        }
 
        }
 
-       private void deleteDeadUncommittedTransactions() {
-               // Make dead the transactions
-               for (Iterator<Map.Entry<Long, Transaction>> i = uncommittedTransactionsMap.entrySet().iterator(); i.hasNext();) {
-                       Transaction prevtrans = i.next().getValue();
-                       long transArb = prevtrans.getArbitrator();
+       public void arbitrateOnLocalTransaction(Transaction transaction) {
 
 
-                       Long commitSeqNum = lastCommitSeenTransSeqNumMap.get(transArb);
-                       Long abortSeqNum = lastAbortSeenSeqNumMap.get(transArb);
+               // Check if this machine arbitrates for this transaction if not then we cant arbitrate this transaction
+               if (transaction.getArbitrator() != localMachineId) {
+                       return;
+               }
 
 
-                       if (((commitSeqNum != null) && (prevtrans.getSequenceNumber() <= commitSeqNum)) ||
-                               ((abortSeqNum != null) && (prevtrans.getSequenceNumber() <= abortSeqNum))) {
-                               i.remove();
-                               prevtrans.setDead();
+               if (!transaction.isComplete()) {
+                       // Will arbitrate in incorrect order if we continue so just break
+                       // Most likely this
+                       return;
+               }
+
+               if (transaction.evaluateGuard(committedKeyValueTable, null, null)) {
+                       // Guard evaluated as true
+
+                       // Create the commit and increment the commit sequence number
+                       Commit newCommit = new Commit(localCommitSequenceNumber, localMachineId, -1);
+                       localCommitSequenceNumber++;
+
+                       // Update the local changes so we can make the commit
+                       for (KeyValue kv : transaction.getKeyValueUpdateSet()) {
+                               newCommit.addKV(kv);
+                       }
+
+                       // create the commit parts
+                       newCommit.createCommitParts();
+
+                       // Append all the commit parts to the end of the pending queue waiting for sending to the server
+                       pendingSendArbitrationEntries.addAll(newCommit.getParts().values());
+
+                       // Insert the commit so we can process it
+                       for (CommitPart commitPart : newCommit.getParts().values()) {
+                               processEntry(commitPart);
                        }
                        }
+
+                       TransactionStatus status = transaction.getTransactionStatus();
+                       status.setStatus(TransactionStatus.StatusCommitted);
+
+               } else {
+                       // Guard evaluated was false so create abort
+                       TransactionStatus status = transaction.getTransactionStatus();
+                       status.setStatus(TransactionStatus.StatusAborted);
                }
        }
 
                }
        }
 
-       private boolean createSpeculativeTable() {
-               if (uncommittedTransactionsMap.keySet().size() == 0) {
+       /**
+        * Update all the commits and the committed tables, sets dead the dead transactions
+        */
+       private boolean updateCommittedTable() {
+
+               if (newCommitParts.size() == 0) {
+                       // Nothing new to process
                        return false;
                }
 
                        return false;
                }
 
-               Map<IoTString, KeyValue> speculativeTableTmp = new HashMap<IoTString, KeyValue>();
-               List<Long> utSeqNums = new ArrayList<Long>(uncommittedTransactionsMap.keySet());
+               // Iterate through all the machine Ids that we received new parts for
+               for (Long machineId : newCommitParts.keySet()) {
+                       Map<Pair<Long, Integer>, CommitPart> parts = newCommitParts.get(machineId);
 
 
-               // Sort from oldest to newest commit
-               Collections.sort(utSeqNums);
+                       // Iterate through all the parts for that machine Id
+                       for (Pair<Long, Integer> partId : parts.keySet()) {
+                               CommitPart part = parts.get(partId);
 
 
-               if (utSeqNums.get(0) > (lastUncommittedTransaction)) {
+                               // Get the transaction object for that sequence number
+                               Map<Long, Commit> commitForClientTable = liveCommitsTable.get(part.getMachineId());
 
 
-                       speculativeTable.clear();
-                       lastUncommittedTransaction = -1;
+                               if (commitForClientTable == null) {
+                                       // This is the first commit from this device
+                                       commitForClientTable = new HashMap<Long, Commit>();
+                                       liveCommitsTable.put(part.getMachineId(), commitForClientTable);
+                               }
 
 
-                       for (Long key : utSeqNums) {
-                               Transaction trans = uncommittedTransactionsMap.get(key);
+                               Commit commit = commitForClientTable.get(part.getSequenceNumber());
 
 
-                               lastUncommittedTransaction = key;
+                               if (commit == null) {
+                                       // This is a new commit that we dont have so make a new one
+                                       commit = new Commit();
 
 
-                               if (trans.evaluateGuard(commitedTable, speculativeTableTmp)) {
-                                       for (KeyValue kv : trans.getkeyValueUpdateSet()) {
-                                               speculativeTableTmp.put(kv.getKey(), kv);
-                                       }
+                                       // Insert this new commit into the live tables
+                                       commitForClientTable.put(part.getSequenceNumber(), commit);
                                }
 
                                }
 
+                               // Add that part to the commit
+                               commit.addPartDecode(part);
                        }
                        }
-               } else {
-                       for (Long key : utSeqNums) {
+               }
+
+               // Clear all the new commits parts in preparation for the next time the server sends slots
+               newCommitParts.clear();
+
+               // If we process a new commit keep track of it for future use
+               boolean didProcessANewCommit = false;
+
+               // Process the commits one by one
+               for (Long arbitratorId : liveCommitsTable.keySet()) {
+
+                       // Get all the commits for a specific arbitrator
+                       Map<Long, Commit> commitForClientTable = liveCommitsTable.get(arbitratorId);
+
+                       // Sort the commits in order
+                       List<Long> commitSequenceNumbers = new ArrayList<Long>(commitForClientTable.keySet());
+                       Collections.sort(commitSequenceNumbers);
+
+                       // Go through each new commit one by one
+                       for (int i = 0; i < commitSequenceNumbers.size(); i++) {
+                               Long commitSequenceNumber = commitSequenceNumbers.get(i);
+                               Commit commit = commitForClientTable.get(commitSequenceNumber);
+
+                               // Special processing if a commit is not complete
+                               if (!commit.isComplete()) {
+                                       if (i == (commitSequenceNumbers.size() - 1)) {
+                                               // If there is an incomplete commit and this commit is the latest one seen then this commit cannot be processed and there are no other commits
+                                               break;
+                                       } else {
+                                               // This is a commit that was already dead but parts of it are still in the block chain (not flushed out yet).
+                                               // Delete it and move on
+                                               commit.setDead();
+                                               commitForClientTable.remove(commit.getSequenceNumber());
+                                               continue;
+                                       }
+                               }
+
+                               // Get the last commit seen from this arbitrator
+                               long lastCommitSeenSequenceNumber = -1;
+                               if (lastCommitSeenSequenceNumberByArbitratorTable.get(commit.getMachineId()) != null) {
+                                       lastCommitSeenSequenceNumber = lastCommitSeenSequenceNumberByArbitratorTable.get(commit.getMachineId());
+                               }
+
+
+
+
+
+
+                               // We have already seen this commit before so need to do the full processing on this commit
+                               if (commit.getSequenceNumber() <= lastCommitSeenSequenceNumber) {
+
+                                       // Update the last transaction that was updated if we can
+                                       if (commit.getTransactionSequenceNumber() != -1) {
+                                               Long lastTransactionNumber = lastArbitratedTransactionNumberByArbitratorTable.get(commit.getMachineId());
+
+                                               // Update the last transaction sequence number that the arbitrator arbitrated on
+                                               if ((lastTransactionNumber == null) || (lastTransactionNumber < commit.getTransactionSequenceNumber())) {
+                                                       lastArbitratedTransactionNumberByArbitratorTable.put(commit.getMachineId(), commit.getTransactionSequenceNumber());
+                                               }
+                                       }
 
 
-                               if (key <= lastUncommittedTransaction) {
                                        continue;
                                }
 
                                        continue;
                                }
 
-                               lastUncommittedTransaction = key;
 
 
-                               Transaction trans = uncommittedTransactionsMap.get(key);
+                               // If we got here then this is a brand new commit and needs full processing
 
 
-                               if (trans.evaluateGuard(speculativeTable, speculativeTableTmp)) {
-                                       for (KeyValue kv : trans.getkeyValueUpdateSet()) {
-                                               speculativeTableTmp.put(kv.getKey(), kv);
+                               // Get what commits should be edited, these are the commits that have live values for their keys
+                               Set<Commit> commitsToEdit = new HashSet<Commit>();
+                               for (KeyValue kv : commit.getKeyValueUpdateSet()) {
+                                       commitsToEdit.add(liveCommitsByKeyTable.get(kv.getKey()));
+                               }
+                               commitsToEdit.remove(null); // remove null since it could be in this set
+
+                               // Update each previous commit that needs to be updated
+                               for (Commit previousCommit : commitsToEdit) {
+
+                                       // Only bother with live commits (TODO: Maybe remove this check)
+                                       if (previousCommit.isLive()) {
+
+                                               // Update which keys in the old commits are still live
+                                               for (KeyValue kv : commit.getKeyValueUpdateSet()) {
+                                                       previousCommit.invalidateKey(kv.getKey());
+                                               }
+
+                                               // if the commit is now dead then remove it
+                                               if (!previousCommit.isLive()) {
+                                                       commitForClientTable.remove(previousCommit);
+                                               }
                                        }
                                }
                                        }
                                }
+
+                               // Update the last seen sequence number from this arbitrator
+                               lastCommitSeenSequenceNumberByArbitratorTable.put(commit.getMachineId(), commit.getSequenceNumber());
+
+                               // Update the last transaction that was updated if we can
+                               if (commit.getTransactionSequenceNumber() != -1) {
+                                       Long lastTransactionNumber = lastArbitratedTransactionNumberByArbitratorTable.get(commit.getMachineId());
+
+                                       // Update the last transaction sequence number that the arbitrator arbitrated on
+                                       if ((lastTransactionNumber == null) || (lastTransactionNumber < commit.getTransactionSequenceNumber())) {
+                                               lastArbitratedTransactionNumberByArbitratorTable.put(commit.getMachineId(), commit.getTransactionSequenceNumber());
+                                       }
+                               }
+
+                               // We processed a new commit that we havent seen before
+                               didProcessANewCommit = true;
+
+                               // Update the committed table of keys and which commit is using which key
+                               for (KeyValue kv : commit.getKeyValueUpdateSet()) {
+                                       committedKeyValueTable.put(kv.getKey(), kv);
+                                       liveCommitsByKeyTable.put(kv.getKey(), commit);
+                               }
+                       }
+               }
+
+               return didProcessANewCommit;
+       }
+
+       /**
+        * Create the speculative table from transactions that are still live and have come from the cloud
+        */
+       private boolean updateSpeculativeTable(boolean didProcessNewCommits) {
+               if (liveTransactionBySequenceNumberTable.keySet().size() == 0) {
+                       // There is nothing to speculate on
+                       return false;
+               }
+
+               // Create a list of the transaction sequence numbers and sort them from oldest to newest
+               List<Long> transactionSequenceNumbersSorted = new ArrayList<Long>(liveTransactionBySequenceNumberTable.keySet());
+               Collections.sort(transactionSequenceNumbersSorted);
+
+               boolean hasGapInTransactionSequenceNumbers = transactionSequenceNumbersSorted.get(0) != oldestTransactionSequenceNumberSpeculatedOn;
+
+
+               if (hasGapInTransactionSequenceNumbers || didProcessNewCommits) {
+                       // If there is a gap in the transaction sequence numbers then there was a commit or an abort of a transaction
+                       // OR there was a new commit (Could be from offline commit) so a redo the speculation from scratch
+
+                       // Start from scratch
+                       speculatedKeyValueTable.clear();
+                       lastTransactionSequenceNumberSpeculatedOn = -1;
+                       oldestTransactionSequenceNumberSpeculatedOn = -1;
+
+               }
+
+               // Remember the front of the transaction list
+               oldestTransactionSequenceNumberSpeculatedOn = transactionSequenceNumbersSorted.get(0);
+
+               // Find where to start arbitration from
+               int startIndex = transactionSequenceNumbersSorted.indexOf(lastTransactionSequenceNumberSpeculatedOn) + 1;
+
+               if (startIndex >= transactionSequenceNumbersSorted.size()) {
+                       // Make sure we are not out of bounds
+                       return false; // did not speculate
+               }
+
+               Set<Long> incompleteTransactionArbitrator = new HashSet<Long>();
+               boolean didSkip = true;
+
+               for (int i = startIndex; i < transactionSequenceNumbersSorted.size(); i++) {
+                       long transactionSequenceNumber = transactionSequenceNumbersSorted.get(i);
+                       Transaction transaction = liveTransactionBySequenceNumberTable.get(transactionSequenceNumber);
+
+                       if (!transaction.isComplete()) {
+                               // If there is an incomplete transaction then there is nothing we can do
+                               // add this transactions arbitrator to the list of arbitrators we should ignore
+                               incompleteTransactionArbitrator.add(transaction.getArbitrator());
+                               didSkip = true;
+                               continue;
+                       }
+
+                       if (incompleteTransactionArbitrator.contains(transaction.getArbitrator())) {
+                               continue;
+                       }
+
+                       lastTransactionSequenceNumberSpeculatedOn = transactionSequenceNumber;
+
+                       if (transaction.evaluateGuard(committedKeyValueTable, speculatedKeyValueTable, null)) {
+                               // Guard evaluated to true so update the speculative table
+                               for (KeyValue kv : transaction.getKeyValueUpdateSet()) {
+                                       speculatedKeyValueTable.put(kv.getKey(), kv);
+                               }
                        }
                }
 
                        }
                }
 
-               for (IoTString key : speculativeTableTmp.keySet()) {
-                       speculativeTable.put(key, speculativeTableTmp.get(key));
+               if (didSkip) {
+                       // Since there was a skip we need to redo the speculation next time around
+                       lastTransactionSequenceNumberSpeculatedOn = -1;
+                       oldestTransactionSequenceNumberSpeculatedOn = -1;
                }
 
                }
 
+               // We did some speculation
                return true;
        }
 
                return true;
        }
 
-       private void createPendingTransactionSpeculativeTable(boolean didCommitOrSpeculate) {
+       /**
+        * Create the pending transaction speculative table from transactions that are still in the pending transaction buffer
+        */
+       private void updatePendingTransactionSpeculativeTable(boolean didProcessNewCommitsOrSpeculate) {
+               if (pendingTransactionQueue.size() == 0) {
+                       // There is nothing to speculate on
+                       return;
+               }
 
 
-               if (didCommitOrSpeculate) {
-                       pendingTransSpeculativeTable.clear();
-                       lastSeenPendingTransactionSpeculateIndex = 0;
 
 
-                       int index = 0;
-                       for (PendingTransaction pt : pendingTransQueue) {
-                               if (pt.evaluateGuard(commitedTable, speculativeTable, pendingTransSpeculativeTable)) {
+               if (didProcessNewCommitsOrSpeculate || (firstPendingTransaction != pendingTransactionQueue.get(0))) {
+                       // need to reset on the pending speculation
+                       lastPendingTransactionSpeculatedOn = null;
+                       firstPendingTransaction = pendingTransactionQueue.get(0);
+                       pendingTransactionSpeculatedKeyValueTable.clear();
+               }
 
 
-                                       lastSeenPendingTransactionSpeculateIndex = index;
-                                       index++;
+               // Find where to start arbitration from
+               int startIndex = pendingTransactionQueue.indexOf(firstPendingTransaction) + 1;
 
 
-                                       for (KeyValue kv : pt.getKVUpdates()) {
-                                               pendingTransSpeculativeTable.put(kv.getKey(), kv);
-                                       }
+               if (startIndex >= pendingTransactionQueue.size()) {
+                       // Make sure we are not out of bounds
+                       return;
+               }
+
+               for (int i = startIndex; i < pendingTransactionQueue.size(); i++) {
+                       Transaction transaction = pendingTransactionQueue.get(i);
 
 
+                       lastPendingTransactionSpeculatedOn = transaction;
+
+                       if (transaction.evaluateGuard(committedKeyValueTable, speculatedKeyValueTable, pendingTransactionSpeculatedKeyValueTable)) {
+                               // Guard evaluated to true so update the speculative table
+                               for (KeyValue kv : transaction.getKeyValueUpdateSet()) {
+                                       pendingTransactionSpeculatedKeyValueTable.put(kv.getKey(), kv);
                                }
                        }
                }
        }
 
                                }
                        }
                }
        }
 
-       private int expectedsize, currmaxsize;
+       /**
+        * Set dead and remove from the live transaction tables the transactions that are dead
+        */
+       private void updateLiveTransactionsAndStatus() {
 
 
-       private void checkNumSlots(int numslots) {
+               // Go through each of the transactions
+               for (Iterator<Map.Entry<Long, Transaction>> iter = liveTransactionBySequenceNumberTable.entrySet().iterator(); iter.hasNext();) {
+                       Transaction transaction = iter.next().getValue();
 
 
+                       // Check if the transaction is dead
+                       Long lastTransactionNumber = lastArbitratedTransactionNumberByArbitratorTable.get(transaction.getArbitrator());
+                       if ((lastTransactionNumber != null) && (lastTransactionNumber >= transaction.getSequenceNumber())) {
 
 
-               // We only have 1 size so we must have this many slots
-               if (largestTableStatusSeen == smallestTableStatusSeen) {
-                       if (numslots != smallestTableStatusSeen) {
-                               throw new Error("Server Error: Server did not send all slots.  Expected: " + smallestTableStatusSeen + " Received:" + numslots);
-                       }
-               } else {
-                       // We have more than 1
-                       if (numslots < smallestTableStatusSeen) {
-                               throw new Error("Server Error: Server did not send all slots.  Expected at least: " + smallestTableStatusSeen + " Received:" + numslots);
+                               // Set dead the transaction
+                               transaction.setDead();
+
+                               // Remove the transaction from the live table
+                               iter.remove();
+                               liveTransactionByTransactionIdTable.remove(transaction.getId());
                        }
                }
 
                        }
                }
 
-               // if (numslots != expectedsize) {
-               // throw new Error("Server Error: Server did not send all slots.  Expected: " + expectedsize + " Received:" + numslots);
-               // }
-       }
+               // Go through each of the transactions
+               for (Iterator<Map.Entry<Long, TransactionStatus>> iter = outstandingTransactionStatus.entrySet().iterator(); iter.hasNext();) {
+                       TransactionStatus status = iter.next().getValue();
 
 
-       private void initExpectedSize(long firstsequencenumber) {
-               long prevslots = firstsequencenumber;
-               expectedsize = (prevslots < ((long) numslots)) ? (int) prevslots : numslots;
-               currmaxsize = numslots;
+                       // Check if the transaction is dead
+                       Long lastTransactionNumber = lastArbitratedTransactionNumberByArbitratorTable.get(status.getTransactionArbitrator());
+                       if ((lastTransactionNumber != null) && (lastTransactionNumber >= status.getTransactionSequenceNumber())) {
+
+                               // Set committed
+                               status.setStatus(TransactionStatus.StatusCommitted);
+
+                               // Remove
+                               iter.remove();
+                       }
+               }
        }
 
        }
 
-       private void updateExpectedSize() {
-               expectedsize++;
-               if (expectedsize > currmaxsize) {
-                       expectedsize = currmaxsize;
+
+       /**
+        * Process this slot, entry by entry.  Also update the latest message sent by slot
+        */
+       private void processSlot(SlotIndexer indexer, Slot slot, boolean acceptUpdatesToLocal, HashSet<Long> machineSet) {
+
+               // Update the last message seen
+               updateLastMessage(slot.getMachineID(), slot.getSequenceNumber(), slot, acceptUpdatesToLocal, machineSet);
+
+               // Process each entry in the slot
+               for (Entry entry : slot.getEntries()) {
+                       switch (entry.getType()) {
+
+                       case Entry.TypeCommitPart:
+                               processEntry((CommitPart)entry);
+                               break;
+
+                       case Entry.TypeAbort:
+                               processEntry((Abort)entry);
+                               break;
+
+                       case Entry.TypeTransactionPart:
+                               processEntry((TransactionPart)entry);
+                               break;
+
+                       case Entry.TypeNewKey:
+                               processEntry((NewKey)entry);
+                               break;
+
+                       case Entry.TypeLastMessage:
+                               processEntry((LastMessage)entry, machineSet);
+                               break;
+
+                       case Entry.TypeRejectedMessage:
+                               processEntry((RejectedMessage)entry, indexer);
+                               break;
+
+                       case Entry.TypeTableStatus:
+                               processEntry((TableStatus)entry);
+                               break;
+
+                       default:
+                               throw new Error("Unrecognized type: " + entry.getType());
+                       }
                }
        }
 
                }
        }
 
-       private void updateCurrMaxSize(int newmaxsize) {
-               currmaxsize = newmaxsize;
+       /**
+        * Update the last message that was sent for a machine Id
+        */
+       private void processEntry(LastMessage entry, HashSet<Long> machineSet) {
+               // Update what the last message received by a machine was
+               updateLastMessage(entry.getMachineID(), entry.getSequenceNumber(), entry, false, machineSet);
        }
 
        }
 
-       private void commitNewMaxSize() {
+       /**
+        * Add the new key to the arbitrators table and update the set of live new keys (in case of a rescued new key message)
+        */
+       private void processEntry(NewKey entry) {
 
 
-               if (largestTableStatusSeen == -1) {
-                       currmaxsize = numslots;
-               } else {
-                       currmaxsize = largestTableStatusSeen;
+               // Update the arbitrator table with the new key information
+               arbitratorTable.put(entry.getKey(), entry.getMachineID());
+
+               // Update what the latest live new key is
+               NewKey oldNewKey = liveNewKeyTable.put(entry.getKey(), entry);
+               if (oldNewKey != null) {
+                       // Delete the old new key messages
+                       oldNewKey.setDead();
                }
                }
+       }
+
+       /**
+        * Process new table status entries and set dead the old ones as new ones come in.
+        * keeps track of the largest and smallest table status seen in this current round
+        * of updating the local copy of the block chain
+        */
+       private void processEntry(TableStatus entry) {
+               int newNumSlots = entry.getMaxSlots();
 
 
-               if (numslots != currmaxsize) {
-                       buffer.resize(currmaxsize);
+               if (liveTableStatus != null) {
+                       // We have a larger table status so the old table status is no longer alive
+                       liveTableStatus.setDead();
                }
 
                }
 
-               numslots = currmaxsize;
-               setResizeThreshold();
-       }
+               // Make this new table status the latest alive table status
+               liveTableStatus = entry;
 
 
-       private void processEntry(LastMessage entry, HashSet<Long> machineSet) {
-               updateLastMessage(entry.getMachineID(), entry.getSequenceNumber(), entry, false, machineSet);
+               if ((smallestTableStatusSeen == -1) || (newNumSlots < smallestTableStatusSeen)) {
+                       smallestTableStatusSeen = newNumSlots;
+               }
+
+               if ((largestTableStatusSeen == -1) || (newNumSlots > largestTableStatusSeen)) {
+                       largestTableStatusSeen = newNumSlots;
+               }
        }
 
        }
 
+       /**
+        * Check old messages to see if there is a block chain violation. Also
+        */
        private void processEntry(RejectedMessage entry, SlotIndexer indexer) {
        private void processEntry(RejectedMessage entry, SlotIndexer indexer) {
-               long oldseqnum = entry.getOldSeqNum();
-               long newseqnum = entry.getNewSeqNum();
+               long oldSeqNum = entry.getOldSeqNum();
+               long newSeqNum = entry.getNewSeqNum();
                boolean isequal = entry.getEqual();
                boolean isequal = entry.getEqual();
-               long machineid = entry.getMachineID();
-               for (long seqnum = oldseqnum; seqnum <= newseqnum; seqnum++) {
-                       Slot slot = indexer.getSlot(seqnum);
+               long machineId = entry.getMachineID();
+
+
+               // Check if we have messages that were supposed to be rejected in our local block chain
+               for (long seqNum = oldSeqNum; seqNum <= newSeqNum; seqNum++) {
+
+                       // Get the slot
+                       Slot slot = indexer.getSlot(seqNum);
+
                        if (slot != null) {
                        if (slot != null) {
-                               long slotmachineid = slot.getMachineID();
-                               if (isequal != (slotmachineid == machineid)) {
-                                       throw new Error("Server Error: Trying to insert rejected message for slot " + seqnum);
+                               // If we have this slot make sure that it was not supposed to be a rejected slot
+
+                               long slotMachineId = slot.getMachineID();
+                               if (isequal != (slotMachineId == machineId)) {
+                                       throw new Error("Server Error: Trying to insert rejected message for slot " + seqNum);
                                }
                        }
                }
 
                                }
                        }
                }
 
-               HashSet<Long> watchset = new HashSet<Long>();
-               for (Map.Entry<Long, Pair<Long, Liveness> > lastmsg_entry : lastmessagetable.entrySet()) {
-                       long entry_mid = lastmsg_entry.getKey();
-                       /* We've seen it, don't need to continue to watch.  Our next
-                        * message will implicitly acknowledge it. */
-                       if (entry_mid == localmachineid)
-                               continue;
-                       Pair<Long, Liveness> v = lastmsg_entry.getValue();
-                       long entry_seqn = v.getFirst();
-                       if (entry_seqn < newseqnum) {
-                               addWatchList(entry_mid, entry);
-                               watchset.add(entry_mid);
-                       }
-               }
-               if (watchset.isEmpty())
-                       entry.setDead();
-               else
-                       entry.setWatchSet(watchset);
-       }
 
 
-       private void processEntry(NewKey entry) {
-               arbitratorTable.put(entry.getKey(), entry.getMachineID());
+               // Create a list of clients to watch until they see this rejected message entry.
+               HashSet<Long> deviceWatchSet = new HashSet<Long>();
+               for (Map.Entry<Long, Pair<Long, Liveness>> lastMessageEntry : lastMessageTable.entrySet()) {
 
 
-               NewKey oldNewKey = newKeyTable.put(entry.getKey(), entry);
+                       // Machine ID for the last message entry
+                       long lastMessageEntryMachineId = lastMessageEntry.getKey();
 
 
-               if (oldNewKey != null) {
-                       oldNewKey.setDead();
-               }
-       }
+                       // We've seen it, don't need to continue to watch.  Our next
+                       // message will implicitly acknowledge it.
+                       if (lastMessageEntryMachineId == localMachineId) {
+                               continue;
+                       }
 
 
-       private void processEntry(Transaction entry) {
+                       Pair<Long, Liveness> lastMessageValue = lastMessageEntry.getValue();
+                       long entrySequenceNumber = lastMessageValue.getFirst();
 
 
-               long arb = entry.getArbitrator();
-               Long comLast = lastCommitSeenTransSeqNumMap.get(arb);
-               Long abLast = lastAbortSeenSeqNumMap.get(arb);
+                       if (entrySequenceNumber < newSeqNum) {
 
 
-               Transaction prevTrans = null;
+                               // Add this rejected message to the set of messages that this machine ID did not see yet
+                               addWatchList(lastMessageEntryMachineId, entry);
 
 
-               if ((comLast != null) && (comLast >= entry.getSequenceNumber())) {
-                       prevTrans = uncommittedTransactionsMap.remove(entry.getSequenceNumber());
-               } else if ((abLast != null) && (abLast >= entry.getSequenceNumber())) {
-                       prevTrans = uncommittedTransactionsMap.remove(entry.getSequenceNumber());
-               } else {
-                       prevTrans = uncommittedTransactionsMap.put(entry.getSequenceNumber(), entry);
+                               // This client did not see this rejected message yet so add it to the watch set to monitor
+                               deviceWatchSet.add(lastMessageEntryMachineId);
+                       }
                }
 
                }
 
-               // Duplicate so delete old copy
-               if (prevTrans != null) {
-                       prevTrans.setDead();
+               if (deviceWatchSet.isEmpty()) {
+                       // This rejected message has been seen by all the clients so
+                       entry.setDead();
+               } else {
+                       // We need to watch this rejected message
+                       entry.setWatchSet(deviceWatchSet);
                }
        }
 
                }
        }
 
+       /**
+        * Check if this abort is live, if not then save it so we can kill it later.
+        * update the last transaction number that was arbitrated on.
+        */
        private void processEntry(Abort entry) {
        private void processEntry(Abort entry) {
-               if (lastmessagetable.get(entry.getMachineID()).getFirst() < entry.getTransSequenceNumber()) {
-                       // Abort has not been seen yet so we need to keep track of it
 
 
-                       Abort prevAbort = abortMap.put(entry.getTransSequenceNumber(), entry);
-                       if (prevAbort != null) {
-                               prevAbort.setDead(); // delete old version of the duplicate
-                       }
+               // Abort has not been seen by the client it is for yet so we need to keep track of it
+               Abort previouslySeenAbort = liveAbortTable.put(entry.getAbortId(), entry);
+               if (previouslySeenAbort != null) {
+                       previouslySeenAbort.setDead(); // Delete old version of the abort since we got a rescued newer version
+               }
+
+               if ((entry.getSequenceNumber() != -1) && (lastMessageTable.get(entry.getTransactionMachineId()).getFirst() >= entry.getSequenceNumber())) {
 
 
-                       if ((lastAbortSeenSeqNumMap.get(entry.getTransArbitrator()) != null) &&   (entry.getTransSequenceNumber() > lastAbortSeenSeqNumMap.get(entry.getTransArbitrator()))) {
-                               lastAbortSeenSeqNumMap.put(entry.getTransArbitrator(), entry.getTransSequenceNumber());
-                       }
-               } else {
                        // The machine already saw this so it is dead
                        entry.setDead();
                        // The machine already saw this so it is dead
                        entry.setDead();
+                       liveAbortTable.remove(entry);
+                       return;
                }
 
                }
 
-               // Update the status of the transaction and remove it since we are done with this transaction
-               TransactionStatus status = transactionStatusMap.remove(entry.getTransSequenceNumber());
+
+               // update the transaction status
+               TransactionStatus status = outstandingTransactionStatus.remove(entry.getTransactionSequenceNumber());
                if (status != null) {
                        status.setStatus(TransactionStatus.StatusAborted);
                }
                if (status != null) {
                        status.setStatus(TransactionStatus.StatusAborted);
                }
-       }
 
 
-       private void processEntry(Commit entry) {
-               Map<Long, Commit> arbMap = newCommitMap.get(entry.getTransArbitrator());
 
 
-               if (arbMap == null) {
-                       arbMap = new HashMap<Long, Commit>();
+               // Set dead a transaction if we can
+               Transaction transactionToSetDead = liveTransactionByTransactionIdTable.remove(new Pair<Long, Long>(entry.getTransactionMachineId(), entry.getTransactionClientLocalSequenceNumber()));
+               if (transactionToSetDead != null) {
+                       liveTransactionBySequenceNumberTable.remove(transactionToSetDead.getSequenceNumber());
                }
 
                }
 
-               Commit prevCommit = arbMap.put(entry.getSequenceNumber(), entry);
-               newCommitMap.put(entry.getTransArbitrator(), arbMap);
+               // Update the last transaction sequence number that the arbitrator arbitrated on
+               Long lastTransactionNumber = lastArbitratedTransactionNumberByArbitratorTable.get(entry.getTransactionArbitrator());
+               if ((lastTransactionNumber == null) || (lastTransactionNumber < entry.getTransactionSequenceNumber())) {
 
 
-               if (prevCommit != null) {
-                       prevCommit.setDead();
+                       // Is a valid one
+                       if (entry.getTransactionSequenceNumber() != -1) {
+                               lastArbitratedTransactionNumberByArbitratorTable.put(entry.getTransactionArbitrator(), entry.getTransactionSequenceNumber());
+                       }
                }
        }
 
                }
        }
 
-       private void processEntry(TableStatus entry) {
-               int newnumslots = entry.getMaxSlots();
-               // updateCurrMaxSize(newnumslots);
-               if (lastTableStatus != null)
-                       lastTableStatus.setDead();
-               lastTableStatus = entry;
+       /**
+        * Set dead the transaction part if that transaction is dead and keep track of all new parts
+        */
+       private void processEntry(TransactionPart entry) {
+               // Check if we have already seen this transaction and set it dead OR if it is not alive
+               Long lastTransactionNumber = lastArbitratedTransactionNumberByArbitratorTable.get(entry.getArbitratorId());
+               if ((lastTransactionNumber != null) && (lastTransactionNumber >= entry.getSequenceNumber())) {
+                       // This transaction is dead, it was already committed or aborted
+                       entry.setDead();
+                       return;
+               }
 
 
-               if ((smallestTableStatusSeen == -1) || (newnumslots < smallestTableStatusSeen)) {
-                       smallestTableStatusSeen = newnumslots;
+               // This part is still alive
+               Map<Pair<Long, Integer>, TransactionPart> transactionPart = newTransactionParts.get(entry.getMachineId());
+
+               if (transactionPart == null) {
+                       // Dont have a table for this machine Id yet so make one
+                       transactionPart = new HashMap<Pair<Long, Integer>, TransactionPart>();
+                       newTransactionParts.put(entry.getMachineId(), transactionPart);
                }
 
                }
 
-               if ((largestTableStatusSeen == -1) || (newnumslots > largestTableStatusSeen)) {
-                       largestTableStatusSeen = newnumslots;
+               // Update the part and set dead ones we have already seen (got a rescued version)
+               TransactionPart previouslySeenPart = transactionPart.put(entry.getPartId(), entry);
+               if (previouslySeenPart != null) {
+                       previouslySeenPart.setDead();
                }
        }
 
                }
        }
 
-       private void addWatchList(long machineid, RejectedMessage entry) {
-               HashSet<RejectedMessage> entries = watchlist.get(machineid);
-               if (entries == null)
-                       watchlist.put(machineid, entries = new HashSet<RejectedMessage>());
-               entries.add(entry);
+       /**
+        * Process new commit entries and save them for future use.  Delete duplicates
+        */
+       private void processEntry(CommitPart entry) {
+               Map<Pair<Long, Integer>, CommitPart> commitPart = newCommitParts.get(entry.getMachineId());
+
+               if (commitPart == null) {
+                       // Dont have a table for this machine Id yet so make one
+                       commitPart = new HashMap<Pair<Long, Integer>, CommitPart>();
+                       newCommitParts.put(entry.getMachineId(), commitPart);
+               }
+
+               // Update the part and set dead ones we have already seen (got a rescued version)
+               CommitPart previouslySeenPart = commitPart.put(entry.getPartId(), entry);
+               if (previouslySeenPart != null) {
+                       previouslySeenPart.setDead();
+               }
        }
 
        }
 
-       private void updateLastMessage(long machineid, long seqnum, Liveness liveness, boolean acceptupdatestolocal, HashSet<Long> machineSet) {
-               machineSet.remove(machineid);
+       /**
+        * Update the last message seen table.  Update and set dead the appropriate RejectedMessages as clients see them.
+        * Updates the live aborts, removes those that are dead and sets them dead.
+        * Check that the last message seen is correct and that there is no mismatch of our own last message or that
+        * other clients have not had a rollback on the last message.
+        */
+       private void updateLastMessage(long machineId, long seqNum, Liveness liveness, boolean acceptUpdatesToLocal, HashSet<Long> machineSet) {
 
 
-               HashSet<RejectedMessage> watchset = watchlist.get(machineid);
+               // We have seen this machine ID
+               machineSet.remove(machineId);
+
+               // Get the set of rejected messages that this machine Id is has not seen yet
+               HashSet<RejectedMessage> watchset = rejectedMessageWatchListTable.get(machineId);
+
+               // If there is a rejected message that this machine Id has not seen yet
                if (watchset != null) {
                if (watchset != null) {
+
+                       // Go through each rejected message that this machine Id has not seen yet
                        for (Iterator<RejectedMessage> rmit = watchset.iterator(); rmit.hasNext(); ) {
                        for (Iterator<RejectedMessage> rmit = watchset.iterator(); rmit.hasNext(); ) {
+
                                RejectedMessage rm = rmit.next();
                                RejectedMessage rm = rmit.next();
-                               if (rm.getNewSeqNum() <= seqnum) {
-                                       /* Remove it from our watchlist */
+
+                               // If this machine Id has seen this rejected message...
+                               if (rm.getNewSeqNum() <= seqNum) {
+
+                                       // Remove it from our watchlist
                                        rmit.remove();
                                        rmit.remove();
-                                       /* Decrement machines that need to see this notification */
-                                       rm.removeWatcher(machineid);
+
+                                       // Decrement machines that need to see this notification
+                                       rm.removeWatcher(machineId);
                                }
                        }
                }
 
                                }
                        }
                }
 
-               if (machineid == localmachineid) {
-                       /* Our own messages are immediately dead. */
+               // Set dead the abort
+               for (Iterator<Map.Entry<Pair<Long, Long>, Abort>> i = liveAbortTable.entrySet().iterator(); i.hasNext();) {
+                       Abort abort = i.next().getValue();
+
+                       if ((abort.getTransactionMachineId() == machineId) && (abort.getSequenceNumber() <= seqNum)) {
+                               abort.setDead();
+                               i.remove();
+                       }
+               }
+
+
+
+               if (machineId == localMachineId) {
+                       // Our own messages are immediately dead.
                        if (liveness instanceof LastMessage) {
                                ((LastMessage)liveness).setDead();
                        } else if (liveness instanceof Slot) {
                        if (liveness instanceof LastMessage) {
                                ((LastMessage)liveness).setDead();
                        } else if (liveness instanceof Slot) {
@@ -1642,87 +1674,65 @@ final public class Table {
                        }
                }
 
                        }
                }
 
-               // Set dead the abort
-               for (Iterator<Map.Entry<Long, Abort>> i = abortMap.entrySet().iterator(); i.hasNext();) {
-                       Abort abort = i.next().getValue();
-
-                       if ((abort.getMachineID() == machineid) && (abort.getTransSequenceNumber() <= seqnum)) {
-                               abort.setDead();
-                               i.remove();
-                       }
+               // Get the old last message for this device
+               Pair<Long, Liveness> lastMessageEntry = lastMessageTable.put(machineId, new Pair<Long, Liveness>(seqNum, liveness));
+               if (lastMessageEntry == null) {
+                       // If no last message then there is nothing else to process
+                       return;
                }
 
                }
 
-               Pair<Long, Liveness> lastmsgentry = lastmessagetable.put(machineid, new Pair<Long, Liveness>(seqnum, liveness));
-               if (lastmsgentry == null)
-                       return;
+               long lastMessageSeqNum = lastMessageEntry.getFirst();
+               Liveness lastEntry = lastMessageEntry.getSecond();
 
 
-               long lastmsgseqnum = lastmsgentry.getFirst();
-               Liveness lastentry = lastmsgentry.getSecond();
-               if (machineid != localmachineid) {
-                       if (lastentry instanceof LastMessage) {
-                               ((LastMessage)lastentry).setDead();
-                       } else if (lastentry instanceof Slot) {
-                               ((Slot)lastentry).setDead();
+               // If it is not our machine Id since we already set ours to dead
+               if (machineId != localMachineId) {
+                       if (lastEntry instanceof LastMessage) {
+                               ((LastMessage)lastEntry).setDead();
+                       } else if (lastEntry instanceof Slot) {
+                               ((Slot)lastEntry).setDead();
                        } else {
                                throw new Error("Unrecognized type");
                        }
                }
 
                        } else {
                                throw new Error("Unrecognized type");
                        }
                }
 
-               if (machineid == localmachineid) {
-                       if (lastmsgseqnum != seqnum && !acceptupdatestolocal)
-                               throw new Error("Server Error: Mismatch on local machine sequence number, needed: " +  seqnum + " got: " + lastmsgseqnum);
+               // Make sure the server is not playing any games
+               if (machineId == localMachineId) {
+
+                       // We were not making any updates and we had a machine mismatch
+                       if (lastMessageSeqNum != seqNum && !acceptUpdatesToLocal) {
+                               throw new Error("Server Error: Mismatch on local machine sequence number, needed: " +  seqNum + " got: " + lastMessageSeqNum);
+                       }
                } else {
                } else {
-                       if (lastmsgseqnum > seqnum)
+                       if (lastMessageSeqNum > seqNum) {
                                throw new Error("Server Error: Rollback on remote machine sequence number");
                                throw new Error("Server Error: Rollback on remote machine sequence number");
+                       }
                }
        }
 
                }
        }
 
-       private void processSlot(SlotIndexer indexer, Slot slot, boolean acceptupdatestolocal, HashSet<Long> machineSet) {
-               updateLastMessage(slot.getMachineID(), slot.getSequenceNumber(), slot, acceptupdatestolocal, machineSet);
-               for (Entry entry : slot.getEntries()) {
-                       switch (entry.getType()) {
-
-                       case Entry.TypeNewKey:
-                               processEntry((NewKey)entry);
-                               break;
-
-                       case Entry.TypeCommit:
-                               processEntry((Commit)entry);
-                               break;
-
-                       case Entry.TypeAbort:
-                               processEntry((Abort)entry);
-                               break;
-
-                       case Entry.TypeTransaction:
-                               processEntry((Transaction)entry);
-                               break;
-
-                       case Entry.TypeLastMessage:
-                               processEntry((LastMessage)entry, machineSet);
-                               break;
-
-                       case Entry.TypeRejectedMessage:
-                               processEntry((RejectedMessage)entry, indexer);
-                               break;
-
-                       case Entry.TypeTableStatus:
-                               processEntry((TableStatus)entry);
-                               break;
-
-                       default:
-                               throw new Error("Unrecognized type: " + entry.getType());
-                       }
+       /**
+        * Add a rejected message entry to the watch set to keep track of which clients have seen that
+        * rejected message entry and which have not.
+        */
+       private void addWatchList(long machineId, RejectedMessage entry) {
+               HashSet<RejectedMessage> entries = rejectedMessageWatchListTable.get(machineId);
+               if (entries == null) {
+                       // There is no set for this machine ID yet so create one
+                       entries = new HashSet<RejectedMessage>();
+                       rejectedMessageWatchListTable.put(machineId, entries);
                }
                }
+               entries.add(entry);
        }
 
        }
 
-       private void checkHMACChain(SlotIndexer indexer, Slot[] newslots) {
-               for (int i = 0; i < newslots.length; i++) {
-                       Slot currslot = newslots[i];
-                       Slot prevslot = indexer.getSlot(currslot.getSequenceNumber() - 1);
-                       if (prevslot != null &&
-                               !Arrays.equals(prevslot.getHMAC(), currslot.getPrevHMAC()))
-                               throw new Error("Server Error: Invalid HMAC Chain" + currslot + " " + prevslot);
+       /**
+        * Check if the HMAC chain is not violated
+        */
+       private void checkHMACChain(SlotIndexer indexer, Slot[] newSlots) {
+               for (int i = 0; i < newSlots.length; i++) {
+                       Slot currSlot = newSlots[i];
+                       Slot prevSlot = indexer.getSlot(currSlot.getSequenceNumber() - 1);
+                       if (prevSlot != null &&
+                               !Arrays.equals(prevSlot.getHMAC(), currSlot.getPrevHMAC()))
+                               throw new Error("Server Error: Invalid HMAC Chain" + currSlot + " " + prevSlot);
                }
        }
 }
\ No newline at end of file
                }
        }
 }
\ No newline at end of file
index 0de2e5c0ae8b47d9307af527c560d4cd57139ce6..64b9a909eb470cb58361e82a7dff20a4943d4788 100644 (file)
@@ -11,1868 +11,1151 @@ import java.util.ArrayList;
 
 public class Test {
 
 
 public class Test {
 
-       public static final  int NUMBER_OF_TESTS = 100;
-
-       public static void main(String[] args)  throws ServerException, InterruptedException {
-               if (args[0].equals("2")) {
-                       test2();
-               } else if (args[0].equals("3")) {
-                       test3();
-               } else if (args[0].equals("4")) {
-                       test4();
-               } else if (args[0].equals("5")) {
-                       test5();
-               } else if (args[0].equals("6")) {
-                       test6();
-               } else if (args[0].equals("7")) {
-                       test7();
-               } else if (args[0].equals("8")) {
-                       test8();
-               } else if (args[0].equals("9")) {
-                       test9();
-               } else if (args[0].equals("10")) {
-                       test10();
-               } else if (args[0].equals("11")) {
-                       test11();
-               }
-       }
-
-
-       static void test11() throws InterruptedException {
-
-               boolean foundError = false;
-
-               // Setup the 2 clients
-               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
-               while (true) {
-                       try {
-                               t1.initTable();
-                               break;
-                       } catch (Exception e) {}
-               }
-
-               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
-               while (t2.update().getFirst() == false) {}
-
-               LocalComm lc = new LocalComm(t1, t2);
-               t1.addLocalComm(t2.getId(), lc);
-               t2.addLocalComm(t1.getId(), lc);
-
-               // Make the Keys
-               System.out.println("Setting up keys");
-               for (int i = 0; i < 4; i++) {
-                       String a = "a" + i;
-                       String b = "b" + i;
-                       String c = "c" + i;
-                       String d = "d" + i;
-                       IoTString ia = new IoTString(a);
-                       IoTString ib = new IoTString(b);
-                       IoTString ic = new IoTString(c);
-                       IoTString id = new IoTString(d);
-                       while (true) {
-                               try {
-                                       t1.createNewKey(ia, 321);
-                                       break;
-                               } catch (Exception e) {}
-                       }
-
-                       while (true) {
-                               try {
-                                       t1.createNewKey(ib, 351);
-                                       break;
-                               } catch (Exception e) {}
-                       }
-
-                       while (true) {
-                               try {
-                                       t2.createNewKey(ic, 321);
-                                       break;
-                               } catch (Exception e) {}
-                       }
-
-                       while (true) {
-                               try {
-                                       t2.createNewKey(id, 351);
-                                       break;
-                               } catch (Exception e) {}
-                       }
-               }
-
-               // Do Updates for the keys
-               System.out.println("Setting Key-Values...");
-               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
-                       for (int i = 0; i < 4; i++) {
-                               String keyA = "a" + i;
-                               String valueA = "a" + (i + t);
-
-                               IoTString iKeyA = new IoTString(keyA);
-                               IoTString iValueA = new IoTString(valueA);
-
-                               t1.startTransaction();
-                               t1.addKV(iKeyA, iValueA);
-                               t1.commitTransaction();
-                       }
-               }
-
-               t2.updateFromLocal(321);
-
-               System.out.println("Checking Key-Values...");
-               for (int i = 0; i < 4; i++) {
-
-                       String keyA = "a" + i;
-                       String valueA = "a" + (i + NUMBER_OF_TESTS - 1);
-
-                       IoTString iKeyA = new IoTString(keyA);
-                       IoTString iValueA = new IoTString(valueA);
-
-                       IoTString testValA1 = t1.getCommitted(iKeyA);
-                       IoTString testValA2 = t2.getCommitted(iKeyA);
-
-                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyA + "    " + testValA1 + "    " + iValueA);
-                               foundError = true;
-                       }
-
-                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2 + "    " + iValueA);
-                               foundError = true;
-                       }
-               }
-
-               if (foundError) {
-                       System.out.println("Found Errors...");
-               } else {
-                       System.out.println("No Errors Found...");
-               }
-       }
-
-       static void test10() throws InterruptedException {
-
-               boolean foundError = false;
-
-               // Setup the 2 clients
-               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
-               while (true) {
-                       try {
-                               t1.rebuild();
-                               break;
-                       } catch (Exception e) {}
-               }
-
-               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
-               while (true) {
-                       try {
-                               t2.rebuild();
-                               break;
-                       } catch (Exception e) {}
-               }
-
-               LocalComm lc = new LocalComm(t1, t2);
-               t1.addLocalComm(t2.getId(), lc);
-               t2.addLocalComm(t1.getId(), lc);
-
-
-               System.out.println("Checking Key-Values...");
-               for (int i = 0; i < 4; i++) {
-
-                       String keyA = "a" + i;
-                       String keyB = "b" + i;
-                       String keyC = "c" + i;
-                       String keyD = "d" + i;
-                       String valueA = "a" + (i + NUMBER_OF_TESTS - 1);
-                       String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
-                       String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
-                       String valueD = "d" + (i + NUMBER_OF_TESTS - 1);
-
-                       IoTString iKeyA = new IoTString(keyA);
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iKeyD = new IoTString(keyD);
-                       IoTString iValueA = new IoTString(valueA);
-                       IoTString iValueB = new IoTString(valueB);
-                       IoTString iValueC = new IoTString(valueC);
-                       IoTString iValueD = new IoTString(valueD);
-
-
-                       IoTString testValA1 = t1.getCommitted(iKeyA);
-                       IoTString testValB1 = t1.getCommitted(iKeyB);
-                       IoTString testValC1 = t1.getCommitted(iKeyC);
-                       IoTString testValD1 = t1.getCommitted(iKeyD);
-
-                       IoTString testValA2 = t2.getCommitted(iKeyA);
-                       IoTString testValB2 = t2.getCommitted(iKeyB);
-                       IoTString testValC2 = t2.getCommitted(iKeyC);
-                       IoTString testValD2 = t2.getCommitted(iKeyD);
-
-                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyA + "    " + testValA1 + "    " + iValueA);
-                               foundError = true;
-                       }
-
-                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1 + "    " + iValueB);
-                               foundError = true;
-                       }
-
-                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyC + "    " + testValC1 + "    " + iValueC);
-                               foundError = true;
-                       }
-
-                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyD + "    " + testValD1 + "    " + iValueD);
-                               foundError = true;
-                       }
-
-                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2 + "    " + iValueA);
-                               foundError = true;
-                       }
-
-                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2 + "    " + iValueB);
-                               foundError = true;
-                       }
-
-                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2 + "    " + iValueC);
-                               foundError = true;
-                       }
-
-                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2 + "    " + iValueD);
-                               foundError = true;
-                       }
-               }
-
-               if (foundError) {
-                       System.out.println("Found Errors...");
-               } else {
-                       System.out.println("No Errors Found...");
-               }
-       }
-
-       static void test9() throws InterruptedException {
-
-               boolean foundError = false;
-               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
-
-               // Setup the 2 clients
-               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
-               while (true) {
-                       try {
-                               t1.initTable();
-                               break;
-                       } catch (Exception e) {}
-               }
-
-               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
-               while (t2.update().getFirst() == false) {}
-
-               // LocalComm lc = new LocalComm(t1, t2);
-               // t1.addLocalComm(t2.getId(), lc);
-               // t2.addLocalComm(t1.getId(), lc);
-
-
-
-               // Make the Keys
-               System.out.println("Setting up keys");
-               for (int i = 0; i < 4; i++) {
-                       String a = "a" + i;
-                       String b = "b" + i;
-                       String c = "c" + i;
-                       String d = "d" + i;
-                       IoTString ia = new IoTString(a);
-                       IoTString ib = new IoTString(b);
-                       IoTString ic = new IoTString(c);
-                       IoTString id = new IoTString(d);
-                       while (true) {
-                               try {
-                                       t1.createNewKey(ia, 321);
-                                       break;
-                               } catch (Exception e) {}
-                       }
-
-                       while (true) {
-                               try {
-                                       t1.createNewKey(ib, 351);
-                                       break;
-                               } catch (Exception e) {}
-                       }
-
-                       while (true) {
-                               try {
-                                       t2.createNewKey(ic, 321);
-                                       break;
-                               } catch (Exception e) {}
-                       }
-
-                       while (true) {
-                               try {
-                                       t2.createNewKey(id, 351);
-                                       break;
-                               } catch (Exception e) {}
-                       }
-               }
-
-               // Do Updates for the keys
-               System.out.println("Setting Key-Values...");
-
-               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
-                       for (int i = 0; i < 4; i++) {
-                               String keyB = "b" + i;
-                               String valueB = "b" + (i + t);
-
-                               IoTString iKeyB = new IoTString(keyB);
-                               IoTString iValueB = new IoTString(valueB);
-
-
-                               t1.startTransaction();
-                               t1.getSpeculativeAtomic(iKeyB);
-                               t1.addKV(iKeyB, iValueB);
-                               transStatusList.add(t1.commitTransaction());
-                       }
-               }
-
-               while (t1.update().getFirst() == false) {}
-
-
-               for (int i = 0; i < 4; i++) {
-
-                       String keyB = "b" + i;
-                       String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iValueB = new IoTString(valueB);
-
-                       IoTString testValB1 = t1.getSpeculative(iKeyB);
-                       IoTString testValB2 = t2.getSpeculative(iKeyB);
-
-                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1);
-                               foundError = true;
-                       }
-
-                       if ((testValB2 != null)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
-                               foundError = true;
-                       }
-               }
-
-               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
-                       for (int i = 0; i < 4; i++) {
-                               String keyC = "c" + i;
-                               String valueC = "c" + (i + t);
-
-                               IoTString iKeyC = new IoTString(keyC);
-                               IoTString iValueC = new IoTString(valueC);
-
-                               t2.startTransaction();
-                               t2.getSpeculativeAtomic(iKeyC);
-                               t2.addKV(iKeyC, iValueC);
-                               transStatusList.add(t2.commitTransaction());
-                       }
-               }
-
-               while (t2.update().getFirst() == false) {}
-
-               for (int i = 0; i < 4; i++) {
-                       String keyC = "c" + i;
-                       String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iValueC = new IoTString(valueC);
-
-                       IoTString testValC1 = t1.getSpeculative(iKeyC);
-                       IoTString testValC2 = t2.getSpeculative(iKeyC);
-
-                       if ((testValC1 != null)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyC + "   " + testValC1);
-                               foundError = true;
-                       }
-
-                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyC + "   " + testValC2);
-                               foundError = true;
-                       }
-               }
-
-               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
-                       for (int i = 0; i < 4; i++) {
-                               String keyA = "a" + i;
-                               String keyD = "d" + i;
-                               String valueA = "a" + (i + t);
-                               String valueD = "d" + (i + t);
-
-                               IoTString iKeyA = new IoTString(keyA);
-                               IoTString iKeyD = new IoTString(keyD);
-                               IoTString iValueA = new IoTString(valueA);
-                               IoTString iValueD = new IoTString(valueD);
-
-
-                               t1.startTransaction();
-                               t1.addKV(iKeyA, iValueA);
-                               transStatusList.add(t1.commitTransaction());
-
-                               t2.startTransaction();
-                               t2.addKV(iKeyD, iValueD);
-                               transStatusList.add(t2.commitTransaction());
-                       }
-               }
-
-               System.out.println("Updating Clients...");
-               while (t1.update().getFirst() == false) {}
-               while (t2.update().getFirst() == false) {}
-
-               System.out.println("Checking Key-Values...");
-               for (int i = 0; i < 4; i++) {
-
-                       String keyA = "a" + i;
-                       String keyB = "b" + i;
-                       String keyC = "c" + i;
-                       String keyD = "d" + i;
-                       String valueA = "a" + (i + NUMBER_OF_TESTS - 1);
-                       String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
-                       String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
-                       String valueD = "d" + (i + NUMBER_OF_TESTS - 1);
-
-                       IoTString iKeyA = new IoTString(keyA);
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iKeyD = new IoTString(keyD);
-                       IoTString iValueA = new IoTString(valueA);
-                       IoTString iValueB = new IoTString(valueB);
-                       IoTString iValueC = new IoTString(valueC);
-                       IoTString iValueD = new IoTString(valueD);
-
-
-                       IoTString testValA1 = t1.getCommitted(iKeyA);
-                       IoTString testValB1 = t1.getCommitted(iKeyB);
-                       IoTString testValC1 = t1.getCommitted(iKeyC);
-                       IoTString testValD1 = t1.getCommitted(iKeyD);
-
-                       IoTString testValA2 = t2.getCommitted(iKeyA);
-                       IoTString testValB2 = t2.getCommitted(iKeyB);
-                       IoTString testValC2 = t2.getCommitted(iKeyC);
-                       IoTString testValD2 = t2.getCommitted(iKeyD);
-
-                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyA + "    " + testValA1 + "    " + iValueA);
-                               foundError = true;
-                       }
-
-                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1 + "    " + iValueB);
-                               foundError = true;
-                       }
-
-                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyC + "    " + testValC1 + "    " + iValueC);
-                               foundError = true;
-                       }
-
-                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyD + "    " + testValD1 + "    " + iValueD);
-                               foundError = true;
-                       }
-
-                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2 + "    " + iValueA);
-                               foundError = true;
-                       }
-
-                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2 + "    " + iValueB);
-                               foundError = true;
-                       }
-
-                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2 + "    " + iValueC);
-                               foundError = true;
-                       }
-
-                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2 + "    " + iValueD);
-                               foundError = true;
-                       }
-               }
-
-               for (TransactionStatus status : transStatusList) {
-                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
-                               foundError = true;
-                               System.out.println(status.getStatus());
-                       }
-               }
-
-               if (foundError) {
-                       System.out.println("Found Errors...");
-               } else {
-                       System.out.println("No Errors Found...");
-               }
-       }
-
-       static void test8() throws InterruptedException {
-
-               boolean foundError = false;
-               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
-
-               // Setup the 2 clients
-               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
-               while (true) {
-                       try {
-                               t1.initTable();
-                               break;
-                       } catch (Exception e) {}
-               }
-
-               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
-               while (t2.update().getFirst() == false) {}
-
-               LocalComm lc = new LocalComm(t1, t2);
-               t1.addLocalComm(t2.getId(), lc);
-               t2.addLocalComm(t1.getId(), lc);
-
-               // Make the Keys
-               System.out.println("Setting up keys");
-               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
-                       System.out.println(i);
-
-                       String a = "a" + i;
-                       String b = "b" + i;
-                       String c = "c" + i;
-                       String d = "d" + i;
-                       IoTString ia = new IoTString(a);
-                       IoTString ib = new IoTString(b);
-                       IoTString ic = new IoTString(c);
-                       IoTString id = new IoTString(d);
-
-                       while (true) {
-                               try {
-                                       t1.createNewKey(ia, 321);
-                                       break;
-                               } catch (Exception e) {}
-                       }
-
-                       while (true) {
-                               try {
-                                       t1.createNewKey(ib, 351);
-                                       break;
-                               } catch (Exception e) {}
-                       }
-
-                       while (true) {
-                               try {
-                                       t2.createNewKey(ic, 321);
-                                       break;
-                               } catch (Exception e) {}
-                       }
-
-                       while (true) {
-                               try {
-                                       t2.createNewKey(id, 351);
-                                       break;
-                               } catch (Exception e) {}
-                       }
-               }
-
-               // Do Updates for the keys
-               System.out.println("Setting Key-Values...");
-               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
-                       System.out.println(i);
-                       String keyA = "a" + i;
-                       String keyB = "b" + i;
-                       String keyC = "c" + i;
-                       String keyD = "d" + i;
-                       String valueA = "a" + i;
-                       String valueB = "b" + i;
-                       String valueC = "c" + i;
-                       String valueD = "d" + i;
-
-                       IoTString iKeyA = new IoTString(keyA);
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iKeyD = new IoTString(keyD);
-                       IoTString iValueA = new IoTString(valueA);
-                       IoTString iValueB = new IoTString(valueB);
-                       IoTString iValueC = new IoTString(valueC);
-                       IoTString iValueD = new IoTString(valueD);
-
-
-                       String keyAPrev = "a" + (i - 1);
-                       String keyBPrev = "b" + (i - 1);
-                       String keyCPrev = "c" + (i - 1);
-                       String keyDPrev = "d" + (i - 1);
-                       String valueAPrev = "a" + (i - 1);
-                       String valueBPrev = "b" + (i - 1);
-                       String valueCPrev = "c" + (i - 1);
-                       String valueDPrev = "d" + (i - 1);
-
-                       IoTString iKeyAPrev = new IoTString(keyAPrev);
-                       IoTString iKeyBPrev = new IoTString(keyBPrev);
-                       IoTString iKeyCPrev = new IoTString(keyCPrev);
-                       IoTString iKeyDPrev = new IoTString(keyDPrev);
-                       IoTString iValueAPrev = new IoTString(valueAPrev);
-                       IoTString iValueBPrev = new IoTString(valueBPrev);
-                       IoTString iValueCPrev = new IoTString(valueCPrev);
-                       IoTString iValueDPrev = new IoTString(valueDPrev);
-
-                       t1.startTransaction();
-                       if (i != 0) {
-                               IoTString tmp = t1.getSpeculative(iKeyAPrev);
-                               if ((tmp == null) || !tmp.equals(iValueAPrev)) {
-                                       System.out.println("Key a Error: " + i);
-                                       foundError = true;
-                               }
-                       }
-                       t1.addKV(iKeyA, iValueA);
-                       transStatusList.add(t1.commitTransaction());
-
-
-
-                       t1.startTransaction();
-                       if (i != 0) {
-                               IoTString tmp = t1.getSpeculative(iKeyBPrev);
-                               if ((tmp == null) || !tmp.equals(iValueBPrev)) {
-                                       System.out.println("Key b Error: " + i);
-                                       foundError = true;
-                               }
-                       }
-                       t1.addKV(iKeyB, iValueB);
-                       transStatusList.add(t1.commitTransaction());
-
-
-                       t2.startTransaction();
-                       if (i != 0) {
-                               IoTString tmp = t2.getSpeculative(iKeyCPrev);
-                               if ((tmp == null) || !tmp.equals(iValueCPrev)) {
-                                       System.out.println("Key c Error: " + i);
-                                       foundError = true;
-                               }
-                       }
-                       t2.addKV(iKeyC, iValueC);
-                       transStatusList.add(t2.commitTransaction());
-
-                       t2.startTransaction();
-                       if (i != 0) {
-                               IoTString tmp = t2.getSpeculative(iKeyDPrev);
-                               if ((tmp == null) || !tmp.equals(iValueDPrev)) {
-                                       System.out.println("Key d Error: " + i);
-                                       foundError = true;
-                               }
-                       }
-                       t2.addKV(iKeyD, iValueD);
-                       transStatusList.add(t2.commitTransaction());
-               }
-
-
-               System.out.println("Updating...");
-               while (t1.update().getFirst() == false) {}
-               while (t2.update().getFirst() == false) {}
-
-
-               System.out.println("Checking Key-Values...");
-               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
-
-                       String keyA = "a" + i;
-                       String keyB = "b" + i;
-                       String keyC = "c" + i;
-                       String keyD = "d" + i;
-                       String valueA = "a" + i;
-                       String valueB = "b" + i;
-                       String valueC = "c" + i;
-                       String valueD = "d" + i;
-
-                       IoTString iKeyA = new IoTString(keyA);
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iKeyD = new IoTString(keyD);
-                       IoTString iValueA = new IoTString(valueA);
-                       IoTString iValueB = new IoTString(valueB);
-                       IoTString iValueC = new IoTString(valueC);
-                       IoTString iValueD = new IoTString(valueD);
-
-
-                       IoTString testValA1 = t1.getCommitted(iKeyA);
-                       IoTString testValB1 = t1.getCommitted(iKeyB);
-                       IoTString testValC1 = t1.getCommitted(iKeyC);
-                       IoTString testValD1 = t1.getCommitted(iKeyD);
-
-                       IoTString testValA2 = t2.getCommitted(iKeyA);
-                       IoTString testValB2 = t2.getCommitted(iKeyB);
-                       IoTString testValC2 = t2.getCommitted(iKeyC);
-                       IoTString testValD2 = t2.getCommitted(iKeyD);
-
-                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyA);
-                               foundError = true;
-                       }
-
-                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyB);
-                               foundError = true;
-                       }
-
-                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyC);
-                               foundError = true;
-                       }
-
-                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyD);
-                               foundError = true;
-                       }
-
-
-                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
-                               foundError = true;
-                       }
-
-                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
-                               foundError = true;
-                       }
-
-                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
-                               foundError = true;
-                       }
-
-                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
-                               foundError = true;
-                       }
-               }
-
-               for (TransactionStatus status : transStatusList) {
-                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
-                               foundError = true;
-                       }
-               }
-               if (foundError) {
-                       System.out.println("Found Errors...");
-               } else {
-                       System.out.println("No Errors Found...");
-               }
-       }
-
-       static void test7() throws ServerException, InterruptedException {
-
-               boolean foundError = false;
-               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
-
-               // Setup the 2 clients
-               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
-               t1.initTable();
-               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
-               t2.update();
-
-               // Make the Keys
-               System.out.println("Setting up keys");
-               for (int i = 0; i < 4; i++) {
-                       String a = "a" + i;
-                       String b = "b" + i;
-                       String c = "c" + i;
-                       String d = "d" + i;
-                       IoTString ia = new IoTString(a);
-                       IoTString ib = new IoTString(b);
-                       IoTString ic = new IoTString(c);
-                       IoTString id = new IoTString(d);
-                       t1.createNewKey(ia, 321);
-                       t1.createNewKey(ib, 351);
-                       t2.createNewKey(ic, 321);
-                       t2.createNewKey(id, 351);
-               }
-
-               // Do Updates for the keys
-               System.out.println("Setting Key-Values...");
-
-               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
-                       for (int i = 0; i < 4; i++) {
-                               String keyB = "b" + i;
-                               String valueB = "b" + (i + t);
-
-                               IoTString iKeyB = new IoTString(keyB);
-                               IoTString iValueB = new IoTString(valueB);
-
-                               t1.startTransaction();
-                               t1.getSpeculativeAtomic(iKeyB);
-                               t1.addKV(iKeyB, iValueB);
-                               transStatusList.add(t1.commitTransaction());
-                       }
-               }
-
-               for (int i = 0; i < 4; i++) {
-
-                       String keyB = "b" + i;
-                       String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iValueB = new IoTString(valueB);
-
-                       IoTString testValB1 = t1.getSpeculative(iKeyB);
-                       IoTString testValB2 = t2.getSpeculative(iKeyB);
-
-                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1);
-                               foundError = true;
-                       }
-
-                       if ((testValB2 != null)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
-                               foundError = true;
-                       }
-               }
-
-               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
-                       for (int i = 0; i < 4; i++) {
-                               String keyC = "c" + i;
-                               String valueC = "c" + (i + t);
-
-                               IoTString iKeyC = new IoTString(keyC);
-                               IoTString iValueC = new IoTString(valueC);
-
-                               t2.startTransaction();
-                               t2.getSpeculativeAtomic(iKeyC);
-                               t2.addKV(iKeyC, iValueC);
-                               transStatusList.add(t2.commitTransaction());
-                       }
-               }
-
-               for (int i = 0; i < 4; i++) {
-                       String keyC = "c" + i;
-                       String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iValueC = new IoTString(valueC);
-
-                       IoTString testValC1 = t1.getSpeculative(iKeyC);
-                       IoTString testValC2 = t2.getSpeculative(iKeyC);
-
-                       if ((testValC1 != null)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyC + "   " + testValC1);
-                               foundError = true;
-                       }
-
-                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyC + "   " + testValC2);
-                               foundError = true;
-                       }
-               }
-
-               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
-                       for (int i = 0; i < 4; i++) {
-                               String keyA = "a" + i;
-                               String keyD = "d" + i;
-                               String valueA = "a" + (i + t);
-                               String valueD = "d" + (i + t);
-
-                               IoTString iKeyA = new IoTString(keyA);
-                               IoTString iKeyD = new IoTString(keyD);
-                               IoTString iValueA = new IoTString(valueA);
-                               IoTString iValueD = new IoTString(valueD);
-
-                               t1.startTransaction();
-                               t1.addKV(iKeyA, iValueA);
-                               transStatusList.add(t1.commitTransaction());
-
-                               t2.startTransaction();
-                               t2.addKV(iKeyD, iValueD);
-                               transStatusList.add(t2.commitTransaction());
-                       }
-               }
-
-               System.out.println("Updating Clients...");
-               t1.update();
-               t2.update();
-               t1.update();
-               t2.update();
-
-               System.out.println("Checking Key-Values...");
-               for (int i = 0; i < 4; i++) {
-
-                       String keyA = "a" + i;
-                       String keyB = "b" + i;
-                       String keyC = "c" + i;
-                       String keyD = "d" + i;
-                       String valueA = "a" + (i + NUMBER_OF_TESTS - 1);
-                       String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
-                       String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
-                       String valueD = "d" + (i + NUMBER_OF_TESTS - 1);
-
-                       IoTString iKeyA = new IoTString(keyA);
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iKeyD = new IoTString(keyD);
-                       IoTString iValueA = new IoTString(valueA);
-                       IoTString iValueB = new IoTString(valueB);
-                       IoTString iValueC = new IoTString(valueC);
-                       IoTString iValueD = new IoTString(valueD);
-
-
-                       IoTString testValA1 = t1.getCommitted(iKeyA);
-                       IoTString testValB1 = t1.getCommitted(iKeyB);
-                       IoTString testValC1 = t1.getCommitted(iKeyC);
-                       IoTString testValD1 = t1.getCommitted(iKeyD);
-
-                       IoTString testValA2 = t2.getCommitted(iKeyA);
-                       IoTString testValB2 = t2.getCommitted(iKeyB);
-                       IoTString testValC2 = t2.getCommitted(iKeyC);
-                       IoTString testValD2 = t2.getCommitted(iKeyD);
-
-                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyA + "    " + testValA1);
-                               foundError = true;
-                       }
-
-                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1);
-                               foundError = true;
-                       }
-
-                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyC + "    " + testValC1);
-                               foundError = true;
-                       }
-
-                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyD + "    " + testValD1);
-                               foundError = true;
-                       }
-
-                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
-                               foundError = true;
-                       }
-
-                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
-                               foundError = true;
-                       }
-
-                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
-                               foundError = true;
-                       }
-
-                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
-                               foundError = true;
-                       }
-               }
-
-               for (TransactionStatus status : transStatusList) {
-                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
-                               foundError = true;
-                       }
-               }
-
-               if (foundError) {
-                       System.out.println("Found Errors...");
-               } else {
-                       System.out.println("No Errors Found...");
-               }
-       }
-
-       static void test6() throws ServerException, InterruptedException {
-
-               boolean foundError = false;
-               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
-
-               // Setup the 2 clients
-               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
-               t1.initTable();
-               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
-               t2.update();
-
-               // Make the Keys
-               System.out.println("Setting up keys");
-               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
-                       String a = "a" + i;
-                       String b = "b" + i;
-                       String c = "c" + i;
-                       String d = "d" + i;
-                       IoTString ia = new IoTString(a);
-                       IoTString ib = new IoTString(b);
-                       IoTString ic = new IoTString(c);
-                       IoTString id = new IoTString(d);
-                       t1.createNewKey(ia, 321);
-                       t1.createNewKey(ib, 351);
-                       t2.createNewKey(ic, 321);
-                       t2.createNewKey(id, 351);
-               }
-
-               // Do Updates for the keys
-               System.out.println("Setting Key-Values...");
-               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
-                       String keyA = "a" + i;
-                       String keyB = "b" + i;
-                       String keyC = "c" + i;
-                       String keyD = "d" + i;
-                       String valueA = "a" + i;
-                       String valueB = "b" + i;
-                       String valueC = "c" + i;
-                       String valueD = "d" + i;
-
-                       IoTString iKeyA = new IoTString(keyA);
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iKeyD = new IoTString(keyD);
-                       IoTString iValueA = new IoTString(valueA);
-                       IoTString iValueB = new IoTString(valueB);
-                       IoTString iValueC = new IoTString(valueC);
-                       IoTString iValueD = new IoTString(valueD);
-
-                       t1.startTransaction();
-                       t1.getCommittedAtomic(iKeyA);
-                       t1.addKV(iKeyA, iValueA);
-                       transStatusList.add(t1.commitTransaction());
-
-                       t1.startTransaction();
-                       t1.getCommittedAtomic(iKeyB);
-                       t1.addKV(iKeyB, iValueB);
-                       transStatusList.add(t1.commitTransaction());
-
-                       t2.startTransaction();
-                       t2.getCommittedAtomic(iKeyC);
-                       t2.addKV(iKeyC, iValueC);
-                       transStatusList.add(t2.commitTransaction());
-
-                       t2.startTransaction();
-                       t2.getCommittedAtomic(iKeyD);
-                       t2.addKV(iKeyD, iValueD);
-                       transStatusList.add(t2.commitTransaction());
-               }
-
-               System.out.println("Updating Clients...");
-               t1.update();
-               t2.update();
-
-               System.out.println("Checking Key-Values...");
-               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
-
-                       String keyA = "a" + i;
-                       String keyB = "b" + i;
-                       String keyC = "c" + i;
-                       String keyD = "d" + i;
-                       String valueA = "a" + i;
-                       String valueB = "b" + i;
-                       String valueC = "c" + i;
-                       String valueD = "d" + i;
-
-                       IoTString iKeyA = new IoTString(keyA);
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iKeyD = new IoTString(keyD);
-                       IoTString iValueA = new IoTString(valueA);
-                       IoTString iValueB = new IoTString(valueB);
-                       IoTString iValueC = new IoTString(valueC);
-                       IoTString iValueD = new IoTString(valueD);
-
-
-                       IoTString testValA1 = t1.getCommitted(iKeyA);
-                       IoTString testValB1 = t1.getCommitted(iKeyB);
-                       IoTString testValC1 = t1.getCommitted(iKeyC);
-                       IoTString testValD1 = t1.getCommitted(iKeyD);
-
-                       IoTString testValA2 = t2.getCommitted(iKeyA);
-                       IoTString testValB2 = t2.getCommitted(iKeyB);
-                       IoTString testValC2 = t2.getCommitted(iKeyC);
-                       IoTString testValD2 = t2.getCommitted(iKeyD);
-
-                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyA);
-                               foundError = true;
-                       }
-
-                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyB);
-                               foundError = true;
-                       }
-
-                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyC);
-                               foundError = true;
-                       }
-
-                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyD);
-                               foundError = true;
-                       }
-
-
-                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
-                               foundError = true;
-                       }
-
-                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
-                               foundError = true;
-                       }
-
-                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
-                               foundError = true;
-                       }
-
-                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
-                               foundError = true;
-                       }
-               }
-
-               for (TransactionStatus status : transStatusList) {
-                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
-                               foundError = true;
-                       }
-               }
-
-               if (foundError) {
-                       System.out.println("Found Errors...");
-               } else {
-                       System.out.println("No Errors Found...");
-               }
-       }
-
-       static void test5() throws ServerException, InterruptedException {
-
-               boolean foundError = false;
-               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
-
-               // Setup the 2 clients
-               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
-               t1.initTable();
-               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
-               t2.update();
-
-
-               // Make the Keys
-               System.out.println("Setting up keys");
-               for (int i = 0; i < 4; i++) {
-                       String a = "a" + i;
-                       String b = "b" + i;
-                       String c = "c" + i;
-                       String d = "d" + i;
-                       IoTString ia = new IoTString(a);
-                       IoTString ib = new IoTString(b);
-                       IoTString ic = new IoTString(c);
-                       IoTString id = new IoTString(d);
-                       t1.createNewKey(ia, 321);
-                       t1.createNewKey(ib, 351);
-                       t2.createNewKey(ic, 321);
-                       t2.createNewKey(id, 351);
-               }
-
-               // Do Updates for the keys
-               System.out.println("Setting Key-Values...");
-
-               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
-                       for (int i = 0; i < 4; i++) {
-                               String keyB = "b" + i;
-                               String valueB = "b" + (i + t);
-
-                               IoTString iKeyB = new IoTString(keyB);
-                               IoTString iValueB = new IoTString(valueB);
-
-                               t1.startTransaction();
-                               t1.addKV(iKeyB, iValueB);
-                               transStatusList.add(t1.commitTransaction());
-                       }
-               }
-
-               for (int i = 0; i < 4; i++) {
-
-                       String keyB = "b" + i;
-                       String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iValueB = new IoTString(valueB);
-
-                       IoTString testValB1 = t1.getSpeculative(iKeyB);
-                       IoTString testValB2 = t2.getSpeculative(iKeyB);
-
-                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyB);
-                               foundError = true;
-                       }
-
-                       if ((testValB2 != null)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyB);
-                               foundError = true;
-                       }
-               }
-
-               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
-                       for (int i = 0; i < 4; i++) {
-                               String keyC = "c" + i;
-                               String valueC = "c" + (i + t);
-
-                               IoTString iKeyC = new IoTString(keyC);
-                               IoTString iValueC = new IoTString(valueC);
-
-                               t2.startTransaction();
-                               t2.addKV(iKeyC, iValueC);
-                               transStatusList.add(t2.commitTransaction());
-                       }
-               }
-
-               for (int i = 0; i < 4; i++) {
-                       String keyC = "c" + i;
-                       String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iValueC = new IoTString(valueC);
-
-                       IoTString testValC1 = t1.getSpeculative(iKeyC);
-                       IoTString testValC2 = t2.getSpeculative(iKeyC);
-
-                       if ((testValC1 != null)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyC + "   " + testValC1);
-                               foundError = true;
-                       }
-
-                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyC + "   " + testValC2);
-                               foundError = true;
-                       }
-               }
-
-               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
-                       for (int i = 0; i < 4; i++) {
-                               String keyA = "a" + i;
-                               String keyD = "d" + i;
-                               String valueA = "a" + (i + t);
-                               String valueD = "d" + (i + t);
-
-                               IoTString iKeyA = new IoTString(keyA);
-                               IoTString iKeyD = new IoTString(keyD);
-                               IoTString iValueA = new IoTString(valueA);
-                               IoTString iValueD = new IoTString(valueD);
-
-                               t1.startTransaction();
-                               t1.addKV(iKeyA, iValueA);
-                               transStatusList.add(t1.commitTransaction());
-
-                               t2.startTransaction();
-                               t2.addKV(iKeyD, iValueD);
-                               transStatusList.add(t2.commitTransaction());
-                       }
-               }
-
-               System.out.println("Updating Clients...");
-               t1.update();
-               t2.update();
-
-
-               System.out.println("Checking Key-Values...");
-               for (int i = 0; i < 4; i++) {
-
-                       String keyA = "a" + i;
-                       String keyB = "b" + i;
-                       String keyC = "c" + i;
-                       String keyD = "d" + i;
-                       String valueA = "a" + (i + NUMBER_OF_TESTS - 1);
-                       String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
-                       String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
-                       String valueD = "d" + (i + NUMBER_OF_TESTS - 1);
-
-                       IoTString iKeyA = new IoTString(keyA);
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iKeyD = new IoTString(keyD);
-                       IoTString iValueA = new IoTString(valueA);
-                       IoTString iValueB = new IoTString(valueB);
-                       IoTString iValueC = new IoTString(valueC);
-                       IoTString iValueD = new IoTString(valueD);
-
-
-                       IoTString testValA1 = t1.getCommitted(iKeyA);
-                       IoTString testValB1 = t1.getCommitted(iKeyB);
-                       IoTString testValC1 = t1.getCommitted(iKeyC);
-                       IoTString testValD1 = t1.getCommitted(iKeyD);
-
-                       IoTString testValA2 = t2.getCommitted(iKeyA);
-                       IoTString testValB2 = t2.getCommitted(iKeyB);
-                       IoTString testValC2 = t2.getCommitted(iKeyC);
-                       IoTString testValD2 = t2.getCommitted(iKeyD);
-
-                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyA + "    " + testValA1);
-                               foundError = true;
-                       }
-
-                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1);
-                               foundError = true;
-                       }
-
-                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyC + "    " + testValC1);
-                               foundError = true;
-                       }
-
-                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyD + "    " + testValD1);
-                               foundError = true;
-                       }
-
-
-                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
-                               foundError = true;
-                       }
-
-                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
-                               foundError = true;
-                       }
-
-                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
-                               foundError = true;
-                       }
-
-                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
-                               foundError = true;
-                       }
-               }
-
-               for (TransactionStatus status : transStatusList) {
-                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
-                               foundError = true;
-                       }
-               }
-
-               if (foundError) {
-                       System.out.println("Found Errors...");
-               } else {
-                       System.out.println("No Errors Found...");
-               }
-       }
-
-       static void test4() throws ServerException, InterruptedException {
-
-               boolean foundError = false;
-               long startTime = 0;
-               long endTime = 0;
-               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
-
-               // Setup the 2 clients
-               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
-               t1.initTable();
-               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
-               t2.update();
-
-               // Make the Keys
-               System.out.println("Setting up keys");
-               startTime = System.currentTimeMillis();
-               for (int i = 0; i < 4; i++) {
-                       String a = "a" + i;
-                       String b = "b" + i;
-                       String c = "c" + i;
-                       String d = "d" + i;
-                       IoTString ia = new IoTString(a);
-                       IoTString ib = new IoTString(b);
-                       IoTString ic = new IoTString(c);
-                       IoTString id = new IoTString(d);
-                       t1.createNewKey(ia, 321);
-                       t1.createNewKey(ib, 351);
-                       t2.createNewKey(ic, 321);
-                       t2.createNewKey(id, 351);
-               }
-               endTime = System.currentTimeMillis();
-               System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
-               System.out.println("Time Taken Per Key: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
-               System.out.println();
-
-
-               // Do Updates for the keys
-               System.out.println("Setting Key-Values...");
-               startTime = System.currentTimeMillis();
-               for (int t = 0; t < NUMBER_OF_TESTS; t++) {
-                       for (int i = 0; i < 4; i++) {
-                               String keyA = "a" + i;
-                               String keyB = "b" + i;
-                               String keyC = "c" + i;
-                               String keyD = "d" + i;
-                               String valueA = "a" + i;
-                               String valueB = "b" + i;
-                               String valueC = "c" + i;
-                               String valueD = "d" + i;
-
-                               IoTString iKeyA = new IoTString(keyA);
-                               IoTString iKeyB = new IoTString(keyB);
-                               IoTString iKeyC = new IoTString(keyC);
-                               IoTString iKeyD = new IoTString(keyD);
-                               IoTString iValueA = new IoTString(valueA);
-                               IoTString iValueB = new IoTString(valueB);
-                               IoTString iValueC = new IoTString(valueC);
-                               IoTString iValueD = new IoTString(valueD);
-
-                               t1.startTransaction();
-                               t1.addKV(iKeyA, iValueA);
-                               transStatusList.add(t1.commitTransaction());
-
-                               t1.startTransaction();
-                               t1.addKV(iKeyB, iValueB);
-                               transStatusList.add(t1.commitTransaction());
-
-                               t2.startTransaction();
-                               t2.addKV(iKeyC, iValueC);
-                               transStatusList.add(t2.commitTransaction());
-
-                               t2.startTransaction();
-                               t2.addKV(iKeyD, iValueD);
-                               transStatusList.add(t2.commitTransaction());
-                       }
-               }
-               endTime = System.currentTimeMillis();
-               System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
-               System.out.println("Time Taken Per Update: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 16))   );
-               System.out.println();
-
-
-               System.out.println("Updating Clients...");
-               t1.update();
-               t2.update();
-
-
-               System.out.println("Checking Key-Values...");
-               for (int i = 0; i < 4; i++) {
-
-                       String keyA = "a" + i;
-                       String keyB = "b" + i;
-                       String keyC = "c" + i;
-                       String keyD = "d" + i;
-                       String valueA = "a" + i;
-                       String valueB = "b" + i;
-                       String valueC = "c" + i;
-                       String valueD = "d" + i;
-
-                       IoTString iKeyA = new IoTString(keyA);
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iKeyD = new IoTString(keyD);
-                       IoTString iValueA = new IoTString(valueA);
-                       IoTString iValueB = new IoTString(valueB);
-                       IoTString iValueC = new IoTString(valueC);
-                       IoTString iValueD = new IoTString(valueD);
-
-
-                       IoTString testValA1 = t1.getCommitted(iKeyA);
-                       IoTString testValB1 = t1.getCommitted(iKeyB);
-                       IoTString testValC1 = t1.getCommitted(iKeyC);
-                       IoTString testValD1 = t1.getCommitted(iKeyD);
-
-                       IoTString testValA2 = t2.getCommitted(iKeyA);
-                       IoTString testValB2 = t2.getCommitted(iKeyB);
-                       IoTString testValC2 = t2.getCommitted(iKeyC);
-                       IoTString testValD2 = t2.getCommitted(iKeyD);
-
-                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyA);
-                               foundError = true;
-                       }
-
-                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyB);
-                               foundError = true;
-                       }
-
-                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyC);
-                               foundError = true;
-                       }
-
-                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyD);
-                               foundError = true;
-                       }
-
-
-                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
-                               foundError = true;
-                       }
-
-                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
-                               foundError = true;
-                       }
-
-                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
-                               foundError = true;
-                       }
-
-                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
-                               foundError = true;
-                       }
-               }
-
-               for (TransactionStatus status : transStatusList) {
-                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
-                               foundError = true;
-                       }
-               }
-
-               if (foundError) {
-                       System.out.println("Found Errors...");
-               } else {
-                       System.out.println("No Errors Found...");
-               }
-       }
-
-       static void test3() throws ServerException, InterruptedException {
-
-               long startTime = 0;
-               long endTime = 0;
-               boolean foundError = false;
-
-               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
-
-               // Setup the 2 clients
-               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
-               t1.initTable();
-               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
-               t2.update();
-
-
-               // Make the Keys
-               System.out.println("Setting up keys");
-               startTime = System.currentTimeMillis();
-               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
-                       String a = "a" + i;
-                       String b = "b" + i;
-                       String c = "c" + i;
-                       String d = "d" + i;
-                       IoTString ia = new IoTString(a);
-                       IoTString ib = new IoTString(b);
-                       IoTString ic = new IoTString(c);
-                       IoTString id = new IoTString(d);
-                       t1.createNewKey(ia, 321);
-                       t1.createNewKey(ib, 351);
-                       t2.createNewKey(ic, 321);
-                       t2.createNewKey(id, 351);
-               }
-               endTime = System.currentTimeMillis();
-               System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
-               System.out.println("Time Taken Per Key: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
-               System.out.println();
-
-
-               // Do Updates for the keys
-               System.out.println("Setting Key-Values...");
-               startTime = System.currentTimeMillis();
-               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
-                       String keyB = "b" + i;
-                       String valueB = "b" + i;
-
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iValueB = new IoTString(valueB);
-
-                       t1.startTransaction();
-                       t1.addKV(iKeyB, iValueB);
-                       transStatusList.add(t1.commitTransaction());
-               }
-
-               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
-                       String keyC = "c" + i;
-                       String valueC = "c" + i;
-
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iValueC = new IoTString(valueC);
-
-                       t2.startTransaction();
-                       t2.addKV(iKeyC, iValueC);
-                       transStatusList.add(t2.commitTransaction());
-               }
-
-               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
-                       String keyA = "a" + i;
-                       String keyD = "d" + i;
-                       String valueA = "a" + i;
-                       String valueD = "d" + i;
-
-                       IoTString iKeyA = new IoTString(keyA);
-                       IoTString iKeyD = new IoTString(keyD);
-                       IoTString iValueA = new IoTString(valueA);
-                       IoTString iValueD = new IoTString(valueD);
-
-                       t1.startTransaction();
-                       t1.addKV(iKeyA, iValueA);
-                       transStatusList.add(t1.commitTransaction());
-
-                       t2.startTransaction();
-                       t2.addKV(iKeyD, iValueD);
-                       transStatusList.add(t2.commitTransaction());
-               }
-               endTime = System.currentTimeMillis();
-               System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
-               System.out.println("Time Taken Per Update: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
-               System.out.println();
-
-
-               System.out.println("Updating Clients...");
-               t1.update();
-               t2.update();
-
-
-               System.out.println("Checking Key-Values...");
-               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
-
-                       String keyA = "a" + i;
-                       String keyB = "b" + i;
-                       String keyC = "c" + i;
-                       String keyD = "d" + i;
-                       String valueA = "a" + i;
-                       String valueB = "b" + i;
-                       String valueC = "c" + i;
-                       String valueD = "d" + i;
-
-                       IoTString iKeyA = new IoTString(keyA);
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iKeyD = new IoTString(keyD);
-                       IoTString iValueA = new IoTString(valueA);
-                       IoTString iValueB = new IoTString(valueB);
-                       IoTString iValueC = new IoTString(valueC);
-                       IoTString iValueD = new IoTString(valueD);
-
-
-                       IoTString testValA1 = t1.getCommitted(iKeyA);
-                       IoTString testValB1 = t1.getCommitted(iKeyB);
-                       IoTString testValC1 = t1.getCommitted(iKeyC);
-                       IoTString testValD1 = t1.getCommitted(iKeyD);
-
-                       IoTString testValA2 = t2.getCommitted(iKeyA);
-                       IoTString testValB2 = t2.getCommitted(iKeyB);
-                       IoTString testValC2 = t2.getCommitted(iKeyC);
-                       IoTString testValD2 = t2.getCommitted(iKeyD);
-
-                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyA);
-                               foundError = true;
-                       }
-
-                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyB);
-                               foundError = true;
-                       }
-
-                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyC);
-                               foundError = true;
-                       }
-
-                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyD);
-                               foundError = true;
-                       }
-
-
-                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
-                               foundError = true;
-                       }
-
-                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
-                               foundError = true;
-                       }
-
-                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
-                               foundError = true;
-                       }
-
-                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
-                               foundError = true;
-                       }
-               }
-
-               for (TransactionStatus status : transStatusList) {
-                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
-                               foundError = true;
-                       }
-               }
-
-               if (foundError) {
-                       System.out.println("Found Errors...");
-               } else {
-                       System.out.println("No Errors Found...");
-               }
-       }
-
-       static void test2() throws ServerException, InterruptedException {
-
-               boolean foundError = false;
-               long startTime = 0;
-               long endTime = 0;
-               List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
-
-               // Setup the 2 clients
-               Table t1 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
-               t1.initTable();
-               System.out.println("T1 Ready");
-
-               Table t2 = new Table("127.0.0.1", "http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
-               t2.update();
-               System.out.println("T2 Ready");
-
-               // Make the Keys
-               System.out.println("Setting up keys");
-               startTime = System.currentTimeMillis();
-               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
-                       String a = "a" + i;
-                       String b = "b" + i;
-                       String c = "c" + i;
-                       String d = "d" + i;
-                       IoTString ia = new IoTString(a);
-                       IoTString ib = new IoTString(b);
-                       IoTString ic = new IoTString(c);
-                       IoTString id = new IoTString(d);
-                       t1.createNewKey(ia, 321);
-                       t1.createNewKey(ib, 351);
-                       t2.createNewKey(ic, 321);
-                       t2.createNewKey(id, 351);
-               }
-               endTime = System.currentTimeMillis();
-               System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
-               System.out.println("Time Taken Per Key: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
-               System.out.println();
-
-               // Do Updates for the keys
-               System.out.println("Setting Key-Values...");
-               startTime = System.currentTimeMillis();
-               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
-                       String keyA = "a" + i;
-                       String keyB = "b" + i;
-                       String keyC = "c" + i;
-                       String keyD = "d" + i;
-                       String valueA = "a" + i;
-                       String valueB = "b" + i;
-                       String valueC = "c" + i;
-                       String valueD = "d" + i;
-
-                       IoTString iKeyA = new IoTString(keyA);
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iKeyD = new IoTString(keyD);
-                       IoTString iValueA = new IoTString(valueA);
-                       IoTString iValueB = new IoTString(valueB);
-                       IoTString iValueC = new IoTString(valueC);
-                       IoTString iValueD = new IoTString(valueD);
-
-                       t1.startTransaction();
-                       t1.addKV(iKeyA, iValueA);
-                       transStatusList.add(t1.commitTransaction());
-
-                       t1.startTransaction();
-                       t1.addKV(iKeyB, iValueB);
-                       transStatusList.add(t1.commitTransaction());
-
-                       t2.startTransaction();
-                       t2.addKV(iKeyC, iValueC);
-                       transStatusList.add(t2.commitTransaction());
-
-                       t2.startTransaction();
-                       t2.addKV(iKeyD, iValueD);
-                       transStatusList.add(t2.commitTransaction());
-               }
-               endTime = System.currentTimeMillis();
-               System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
-               System.out.println("Time Taken Per Update: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
-               System.out.println();
-
-
-               System.out.println("Updating Clients...");
-               t1.update();
-               t2.update();
-
-
-               System.out.println("Checking Key-Values...");
-               for (int i = 0; i < NUMBER_OF_TESTS; i++) {
-
-                       String keyA = "a" + i;
-                       String keyB = "b" + i;
-                       String keyC = "c" + i;
-                       String keyD = "d" + i;
-                       String valueA = "a" + i;
-                       String valueB = "b" + i;
-                       String valueC = "c" + i;
-                       String valueD = "d" + i;
-
-                       IoTString iKeyA = new IoTString(keyA);
-                       IoTString iKeyB = new IoTString(keyB);
-                       IoTString iKeyC = new IoTString(keyC);
-                       IoTString iKeyD = new IoTString(keyD);
-                       IoTString iValueA = new IoTString(valueA);
-                       IoTString iValueB = new IoTString(valueB);
-                       IoTString iValueC = new IoTString(valueC);
-                       IoTString iValueD = new IoTString(valueD);
-
-
-                       IoTString testValA1 = t1.getCommitted(iKeyA);
-                       IoTString testValB1 = t1.getCommitted(iKeyB);
-                       IoTString testValC1 = t1.getCommitted(iKeyC);
-                       IoTString testValD1 = t1.getCommitted(iKeyD);
-
-                       IoTString testValA2 = t2.getCommitted(iKeyA);
-                       IoTString testValB2 = t2.getCommitted(iKeyB);
-                       IoTString testValC2 = t2.getCommitted(iKeyC);
-                       IoTString testValD2 = t2.getCommitted(iKeyD);
-
-                       if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyA);
-                               foundError = true;
-                       }
-
-                       if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyB);
-                               foundError = true;
-                       }
-
-                       if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyC);
-                               foundError = true;
-                       }
-
-                       if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t1 incorrect: " + keyD);
-                               foundError = true;
-                       }
-
-
-                       if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
-                               foundError = true;
-                       }
-
-                       if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
-                               foundError = true;
-                       }
-
-                       if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
-                               foundError = true;
-                       }
-
-                       if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
-                               System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
-                               foundError = true;
-                       }
-               }
-
-               for (TransactionStatus status : transStatusList) {
-                       if (status.getStatus() != TransactionStatus.StatusCommitted) {
-                               foundError = true;
-                       }
-               }
-
-               if (foundError) {
-                       System.out.println("Found Errors...");
-               } else {
-                       System.out.println("No Errors Found...");
-               }
-       }
+    public static final  int NUMBER_OF_TESTS = 100;
+
+    public static void main(String[] args)  throws ServerException {
+        if (args[0].equals("2")) {
+            test2();
+        } else if (args[0].equals("3")) {
+            test3();
+        } else if (args[0].equals("4")) {
+            test4();
+        } else if (args[0].equals("5")) {
+            test5();
+        } else if (args[0].equals("6")) {
+            test6();
+        } else if (args[0].equals("7")) {
+            test7();
+        }
+    }
+
+    static void test7() throws ServerException {
+
+        boolean foundError = false;
+        List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+        // Setup the 2 clients
+        Table t1 = new Table("http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+        t1.initTable();
+        Table t2 = new Table("http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+        t2.update();
+
+        // Make the Keys
+        System.out.println("Setting up keys");
+        for (int i = 0; i < 4; i++) {
+            String a = "a" + i;
+            String b = "b" + i;
+            String c = "c" + i;
+            String d = "d" + i;
+            IoTString ia = new IoTString(a);
+            IoTString ib = new IoTString(b);
+            IoTString ic = new IoTString(c);
+            IoTString id = new IoTString(d);
+            t1.createNewKey(ia, 321);
+            t1.createNewKey(ib, 351);
+            t2.createNewKey(ic, 321);
+            t2.createNewKey(id, 351);
+        }
+
+        // Do Updates for the keys
+        System.out.println("Setting Key-Values...");
+
+        for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+            for (int i = 0; i < 4; i++) {
+                String keyB = "b" + i;
+                String valueB = "b" + (i + t);
+
+                IoTString iKeyB = new IoTString(keyB);
+                IoTString iValueB = new IoTString(valueB);
+
+                t1.startTransaction();
+                t1.getSpeculativeAtomic(iKeyB);
+                t1.addKV(iKeyB, iValueB);
+                transStatusList.add(t1.commitTransaction());
+            }
+        }
+
+        for (int i = 0; i < 4; i++) {
+
+            String keyB = "b" + i;
+            String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
+            IoTString iKeyB = new IoTString(keyB);
+            IoTString iValueB = new IoTString(valueB);
+
+            IoTString testValB1 = t1.getSpeculative(iKeyB);
+            IoTString testValB2 = t2.getSpeculative(iKeyB);
+
+            if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1);
+                foundError = true;
+            }
+
+            if ((testValB2 != null)) {
+                System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                foundError = true;
+            }
+        }
+
+        for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+            for (int i = 0; i < 4; i++) {
+                String keyC = "c" + i;
+                String valueC = "c" + (i + t);
+
+                IoTString iKeyC = new IoTString(keyC);
+                IoTString iValueC = new IoTString(valueC);
+
+                t2.startTransaction();
+                t2.getSpeculativeAtomic(iKeyC);
+                t2.addKV(iKeyC, iValueC);
+                transStatusList.add(t2.commitTransaction());
+            }
+        }
+
+        for (int i = 0; i < 4; i++) {
+            String keyC = "c" + i;
+            String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
+            IoTString iKeyC = new IoTString(keyC);
+            IoTString iValueC = new IoTString(valueC);
+
+            IoTString testValC1 = t1.getSpeculative(iKeyC);
+            IoTString testValC2 = t2.getSpeculative(iKeyC);
+
+            if ((testValC1 != null)) {
+                System.out.println("Key-Value t1 incorrect: " + keyC + "   " + testValC1);
+                foundError = true;
+            }
+
+            if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyC + "   " + testValC2);
+                foundError = true;
+            }
+        }
+
+        for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+            for (int i = 0; i < 4; i++) {
+                String keyA = "a" + i;
+                String keyD = "d" + i;
+                String valueA = "a" + (i + t);
+                String valueD = "d" + (i + t);
+
+                IoTString iKeyA = new IoTString(keyA);
+                IoTString iKeyD = new IoTString(keyD);
+                IoTString iValueA = new IoTString(valueA);
+                IoTString iValueD = new IoTString(valueD);
+
+                t1.startTransaction();
+                t1.addKV(iKeyA, iValueA);
+                transStatusList.add(t1.commitTransaction());
+
+                t2.startTransaction();
+                t2.addKV(iKeyD, iValueD);
+                transStatusList.add(t2.commitTransaction());
+            }
+        }
+
+        System.out.println("Updating Clients...");
+        t1.update();
+        t2.update();
+        t1.update();
+        t2.update();
+
+        System.out.println("Checking Key-Values...");
+        for (int i = 0; i < 4; i++) {
+
+            String keyA = "a" + i;
+            String keyB = "b" + i;
+            String keyC = "c" + i;
+            String keyD = "d" + i;
+            String valueA = "a" + (i + NUMBER_OF_TESTS - 1);
+            String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
+            String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
+            String valueD = "d" + (i + NUMBER_OF_TESTS - 1);
+
+            IoTString iKeyA = new IoTString(keyA);
+            IoTString iKeyB = new IoTString(keyB);
+            IoTString iKeyC = new IoTString(keyC);
+            IoTString iKeyD = new IoTString(keyD);
+            IoTString iValueA = new IoTString(valueA);
+            IoTString iValueB = new IoTString(valueB);
+            IoTString iValueC = new IoTString(valueC);
+            IoTString iValueD = new IoTString(valueD);
+
+
+            IoTString testValA1 = t1.getCommitted(iKeyA);
+            IoTString testValB1 = t1.getCommitted(iKeyB);
+            IoTString testValC1 = t1.getCommitted(iKeyC);
+            IoTString testValD1 = t1.getCommitted(iKeyD);
+
+            IoTString testValA2 = t2.getCommitted(iKeyA);
+            IoTString testValB2 = t2.getCommitted(iKeyB);
+            IoTString testValC2 = t2.getCommitted(iKeyC);
+            IoTString testValD2 = t2.getCommitted(iKeyD);
+
+            if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyA + "    " + testValA1);
+                foundError = true;
+            }
+
+            if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1);
+                foundError = true;
+            }
+
+            if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyC + "    " + testValC1);
+                foundError = true;
+            }
+
+            if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyD + "    " + testValD1);
+                foundError = true;
+            }
+
+            if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
+                foundError = true;
+            }
+
+            if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                foundError = true;
+            }
+
+            if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
+                foundError = true;
+            }
+
+            if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
+                foundError = true;
+            }
+        }
+
+        for (TransactionStatus status : transStatusList) {
+            if (status.getStatus() != TransactionStatus.StatusCommitted) {
+                foundError = true;
+            }
+        }
+
+        if (foundError) {
+            System.out.println("Found Errors...");
+        } else {
+            System.out.println("No Errors Found...");
+        }
+    }
+
+    static void test6() throws ServerException {
+
+        boolean foundError = false;
+        List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+        // Setup the 2 clients
+        Table t1 = new Table("http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+        t1.initTable();
+        Table t2 = new Table("http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+        t2.update();
+
+        // Make the Keys
+        System.out.println("Setting up keys");
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+            String a = "a" + i;
+            String b = "b" + i;
+            String c = "c" + i;
+            String d = "d" + i;
+            IoTString ia = new IoTString(a);
+            IoTString ib = new IoTString(b);
+            IoTString ic = new IoTString(c);
+            IoTString id = new IoTString(d);
+            t1.createNewKey(ia, 321);
+            t1.createNewKey(ib, 351);
+            t2.createNewKey(ic, 321);
+            t2.createNewKey(id, 351);
+        }
+
+        // Do Updates for the keys
+        System.out.println("Setting Key-Values...");
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+            String keyA = "a" + i;
+            String keyB = "b" + i;
+            String keyC = "c" + i;
+            String keyD = "d" + i;
+            String valueA = "a" + i;
+            String valueB = "b" + i;
+            String valueC = "c" + i;
+            String valueD = "d" + i;
+
+            IoTString iKeyA = new IoTString(keyA);
+            IoTString iKeyB = new IoTString(keyB);
+            IoTString iKeyC = new IoTString(keyC);
+            IoTString iKeyD = new IoTString(keyD);
+            IoTString iValueA = new IoTString(valueA);
+            IoTString iValueB = new IoTString(valueB);
+            IoTString iValueC = new IoTString(valueC);
+            IoTString iValueD = new IoTString(valueD);
+
+            t1.startTransaction();
+            t1.getCommittedAtomic(iKeyA);
+            t1.addKV(iKeyA, iValueA);
+            transStatusList.add(t1.commitTransaction());
+
+            t1.startTransaction();
+            t1.getCommittedAtomic(iKeyB);
+            t1.addKV(iKeyB, iValueB);
+            transStatusList.add(t1.commitTransaction());
+
+            t2.startTransaction();
+            t2.getCommittedAtomic(iKeyC);
+            t2.addKV(iKeyC, iValueC);
+            transStatusList.add(t2.commitTransaction());
+
+            t2.startTransaction();
+            t2.getCommittedAtomic(iKeyD);
+            t2.addKV(iKeyD, iValueD);
+            transStatusList.add(t2.commitTransaction());
+        }
+
+        System.out.println("Updating Clients...");
+        t1.update();
+        t2.update();
+
+        System.out.println("Checking Key-Values...");
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+
+            String keyA = "a" + i;
+            String keyB = "b" + i;
+            String keyC = "c" + i;
+            String keyD = "d" + i;
+            String valueA = "a" + i;
+            String valueB = "b" + i;
+            String valueC = "c" + i;
+            String valueD = "d" + i;
+
+            IoTString iKeyA = new IoTString(keyA);
+            IoTString iKeyB = new IoTString(keyB);
+            IoTString iKeyC = new IoTString(keyC);
+            IoTString iKeyD = new IoTString(keyD);
+            IoTString iValueA = new IoTString(valueA);
+            IoTString iValueB = new IoTString(valueB);
+            IoTString iValueC = new IoTString(valueC);
+            IoTString iValueD = new IoTString(valueD);
+
+
+            IoTString testValA1 = t1.getCommitted(iKeyA);
+            IoTString testValB1 = t1.getCommitted(iKeyB);
+            IoTString testValC1 = t1.getCommitted(iKeyC);
+            IoTString testValD1 = t1.getCommitted(iKeyD);
+
+            IoTString testValA2 = t2.getCommitted(iKeyA);
+            IoTString testValB2 = t2.getCommitted(iKeyB);
+            IoTString testValC2 = t2.getCommitted(iKeyC);
+            IoTString testValD2 = t2.getCommitted(iKeyD);
+
+            if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyA);
+                foundError = true;
+            }
+
+            if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyB);
+                foundError = true;
+            }
+
+            if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyC);
+                foundError = true;
+            }
+
+            if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyD);
+                foundError = true;
+            }
+
+
+            if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
+                foundError = true;
+            }
+
+            if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                foundError = true;
+            }
+
+            if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
+                foundError = true;
+            }
+
+            if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
+                foundError = true;
+            }
+        }
+
+        for (TransactionStatus status : transStatusList) {
+            if (status.getStatus() != TransactionStatus.StatusCommitted) {
+                foundError = true;
+            }
+        }
+
+        if (foundError) {
+            System.out.println("Found Errors...");
+        } else {
+            System.out.println("No Errors Found...");
+        }
+    }
+
+    static void test5() throws ServerException {
+
+        boolean foundError = false;
+        List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+        // Setup the 2 clients
+        Table t1 = new Table("http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+        t1.initTable();
+        Table t2 = new Table("http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+        t2.update();
+
+
+        // Make the Keys
+        System.out.println("Setting up keys");
+        for (int i = 0; i < 4; i++) {
+            String a = "a" + i;
+            String b = "b" + i;
+            String c = "c" + i;
+            String d = "d" + i;
+            IoTString ia = new IoTString(a);
+            IoTString ib = new IoTString(b);
+            IoTString ic = new IoTString(c);
+            IoTString id = new IoTString(d);
+            t1.createNewKey(ia, 321);
+            t1.createNewKey(ib, 351);
+            t2.createNewKey(ic, 321);
+            t2.createNewKey(id, 351);
+        }
+
+        // Do Updates for the keys
+        System.out.println("Setting Key-Values...");
+
+        for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+            for (int i = 0; i < 4; i++) {
+                String keyB = "b" + i;
+                String valueB = "b" + (i + t);
+
+                IoTString iKeyB = new IoTString(keyB);
+                IoTString iValueB = new IoTString(valueB);
+
+                t1.startTransaction();
+                t1.addKV(iKeyB, iValueB);
+                transStatusList.add(t1.commitTransaction());
+            }
+        }
+
+        for (int i = 0; i < 4; i++) {
+
+            String keyB = "b" + i;
+            String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
+            IoTString iKeyB = new IoTString(keyB);
+            IoTString iValueB = new IoTString(valueB);
+
+            IoTString testValB1 = t1.getSpeculative(iKeyB);
+            IoTString testValB2 = t2.getSpeculative(iKeyB);
+
+            if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyB);
+                foundError = true;
+            }
+
+            if ((testValB2 != null)) {
+                System.out.println("Key-Value t2 incorrect: " + keyB);
+                foundError = true;
+            }
+        }
+
+        for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+            for (int i = 0; i < 4; i++) {
+                String keyC = "c" + i;
+                String valueC = "c" + (i + t);
+
+                IoTString iKeyC = new IoTString(keyC);
+                IoTString iValueC = new IoTString(valueC);
+
+                t2.startTransaction();
+                t2.addKV(iKeyC, iValueC);
+                transStatusList.add(t2.commitTransaction());
+            }
+        }
+
+        for (int i = 0; i < 4; i++) {
+            String keyC = "c" + i;
+            String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
+            IoTString iKeyC = new IoTString(keyC);
+            IoTString iValueC = new IoTString(valueC);
+
+            IoTString testValC1 = t1.getSpeculative(iKeyC);
+            IoTString testValC2 = t2.getSpeculative(iKeyC);
+
+            if ((testValC1 != null)) {
+                System.out.println("Key-Value t1 incorrect: " + keyC + "   " + testValC1);
+                foundError = true;
+            }
+
+            if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyC + "   " + testValC2);
+                foundError = true;
+            }
+        }
+
+        for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+            for (int i = 0; i < 4; i++) {
+                String keyA = "a" + i;
+                String keyD = "d" + i;
+                String valueA = "a" + (i + t);
+                String valueD = "d" + (i + t);
+
+                IoTString iKeyA = new IoTString(keyA);
+                IoTString iKeyD = new IoTString(keyD);
+                IoTString iValueA = new IoTString(valueA);
+                IoTString iValueD = new IoTString(valueD);
+
+                t1.startTransaction();
+                t1.addKV(iKeyA, iValueA);
+                transStatusList.add(t1.commitTransaction());
+
+                t2.startTransaction();
+                t2.addKV(iKeyD, iValueD);
+                transStatusList.add(t2.commitTransaction());
+            }
+        }
+
+        System.out.println("Updating Clients...");
+        t1.update();
+        t2.update();
+
+
+        System.out.println("Checking Key-Values...");
+        for (int i = 0; i < 4; i++) {
+
+            String keyA = "a" + i;
+            String keyB = "b" + i;
+            String keyC = "c" + i;
+            String keyD = "d" + i;
+            String valueA = "a" + (i + NUMBER_OF_TESTS - 1);
+            String valueB = "b" + (i + NUMBER_OF_TESTS - 1);
+            String valueC = "c" + (i + NUMBER_OF_TESTS - 1);
+            String valueD = "d" + (i + NUMBER_OF_TESTS - 1);
+
+            IoTString iKeyA = new IoTString(keyA);
+            IoTString iKeyB = new IoTString(keyB);
+            IoTString iKeyC = new IoTString(keyC);
+            IoTString iKeyD = new IoTString(keyD);
+            IoTString iValueA = new IoTString(valueA);
+            IoTString iValueB = new IoTString(valueB);
+            IoTString iValueC = new IoTString(valueC);
+            IoTString iValueD = new IoTString(valueD);
+
+
+            IoTString testValA1 = t1.getCommitted(iKeyA);
+            IoTString testValB1 = t1.getCommitted(iKeyB);
+            IoTString testValC1 = t1.getCommitted(iKeyC);
+            IoTString testValD1 = t1.getCommitted(iKeyD);
+
+            IoTString testValA2 = t2.getCommitted(iKeyA);
+            IoTString testValB2 = t2.getCommitted(iKeyB);
+            IoTString testValC2 = t2.getCommitted(iKeyC);
+            IoTString testValD2 = t2.getCommitted(iKeyD);
+
+            if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyA + "    " + testValA1);
+                foundError = true;
+            }
+
+            if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1);
+                foundError = true;
+            }
+
+            if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyC + "    " + testValC1);
+                foundError = true;
+            }
+
+            if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyD + "    " + testValD1);
+                foundError = true;
+            }
+
+
+            if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
+                foundError = true;
+            }
+
+            if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                foundError = true;
+            }
+
+            if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
+                foundError = true;
+            }
+
+            if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
+                foundError = true;
+            }
+        }
+
+        for (TransactionStatus status : transStatusList) {
+            if (status.getStatus() != TransactionStatus.StatusCommitted) {
+                foundError = true;
+            }
+        }
+
+        if (foundError) {
+            System.out.println("Found Errors...");
+        } else {
+            System.out.println("No Errors Found...");
+        }
+    }
+
+    static void test4() throws ServerException {
+
+        boolean foundError = false;
+        long startTime = 0;
+        long endTime = 0;
+        List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+        // Setup the 2 clients
+        Table t1 = new Table("http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+        t1.initTable();
+        Table t2 = new Table("http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+        t2.update();
+
+        // Make the Keys
+        System.out.println("Setting up keys");
+        startTime = System.currentTimeMillis();
+        for (int i = 0; i < 4; i++) {
+            String a = "a" + i;
+            String b = "b" + i;
+            String c = "c" + i;
+            String d = "d" + i;
+            IoTString ia = new IoTString(a);
+            IoTString ib = new IoTString(b);
+            IoTString ic = new IoTString(c);
+            IoTString id = new IoTString(d);
+            t1.createNewKey(ia, 321);
+            t1.createNewKey(ib, 351);
+            t2.createNewKey(ic, 321);
+            t2.createNewKey(id, 351);
+        }
+        endTime = System.currentTimeMillis();
+        System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
+        System.out.println("Time Taken Per Key: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
+        System.out.println();
+
+
+        // Do Updates for the keys
+        System.out.println("Setting Key-Values...");
+        startTime = System.currentTimeMillis();
+        for (int t = 0; t < NUMBER_OF_TESTS; t++) {
+            for (int i = 0; i < 4; i++) {
+                String keyA = "a" + i;
+                String keyB = "b" + i;
+                String keyC = "c" + i;
+                String keyD = "d" + i;
+                String valueA = "a" + i;
+                String valueB = "b" + i;
+                String valueC = "c" + i;
+                String valueD = "d" + i;
+
+                IoTString iKeyA = new IoTString(keyA);
+                IoTString iKeyB = new IoTString(keyB);
+                IoTString iKeyC = new IoTString(keyC);
+                IoTString iKeyD = new IoTString(keyD);
+                IoTString iValueA = new IoTString(valueA);
+                IoTString iValueB = new IoTString(valueB);
+                IoTString iValueC = new IoTString(valueC);
+                IoTString iValueD = new IoTString(valueD);
+
+                t1.startTransaction();
+                t1.addKV(iKeyA, iValueA);
+                transStatusList.add(t1.commitTransaction());
+
+                t1.startTransaction();
+                t1.addKV(iKeyB, iValueB);
+                transStatusList.add(t1.commitTransaction());
+
+                t2.startTransaction();
+                t2.addKV(iKeyC, iValueC);
+                transStatusList.add(t2.commitTransaction());
+
+                t2.startTransaction();
+                t2.addKV(iKeyD, iValueD);
+                transStatusList.add(t2.commitTransaction());
+            }
+        }
+        endTime = System.currentTimeMillis();
+        System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
+        System.out.println("Time Taken Per Update: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 16))   );
+        System.out.println();
+
+
+        System.out.println("Updating Clients...");
+        t1.update();
+        t2.update();
+
+
+        System.out.println("Checking Key-Values...");
+        for (int i = 0; i < 4; i++) {
+
+            String keyA = "a" + i;
+            String keyB = "b" + i;
+            String keyC = "c" + i;
+            String keyD = "d" + i;
+            String valueA = "a" + i;
+            String valueB = "b" + i;
+            String valueC = "c" + i;
+            String valueD = "d" + i;
+
+            IoTString iKeyA = new IoTString(keyA);
+            IoTString iKeyB = new IoTString(keyB);
+            IoTString iKeyC = new IoTString(keyC);
+            IoTString iKeyD = new IoTString(keyD);
+            IoTString iValueA = new IoTString(valueA);
+            IoTString iValueB = new IoTString(valueB);
+            IoTString iValueC = new IoTString(valueC);
+            IoTString iValueD = new IoTString(valueD);
+
+
+            IoTString testValA1 = t1.getCommitted(iKeyA);
+            IoTString testValB1 = t1.getCommitted(iKeyB);
+            IoTString testValC1 = t1.getCommitted(iKeyC);
+            IoTString testValD1 = t1.getCommitted(iKeyD);
+
+            IoTString testValA2 = t2.getCommitted(iKeyA);
+            IoTString testValB2 = t2.getCommitted(iKeyB);
+            IoTString testValC2 = t2.getCommitted(iKeyC);
+            IoTString testValD2 = t2.getCommitted(iKeyD);
+
+            if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyA);
+                foundError = true;
+            }
+
+            if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyB);
+                foundError = true;
+            }
+
+            if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyC);
+                foundError = true;
+            }
+
+            if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyD);
+                foundError = true;
+            }
+
+
+            if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
+                foundError = true;
+            }
+
+            if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                foundError = true;
+            }
+
+            if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
+                foundError = true;
+            }
+
+            if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
+                foundError = true;
+            }
+        }
+
+        for (TransactionStatus status : transStatusList) {
+            if (status.getStatus() != TransactionStatus.StatusCommitted) {
+                foundError = true;
+            }
+        }
+
+        if (foundError) {
+            System.out.println("Found Errors...");
+        } else {
+            System.out.println("No Errors Found...");
+        }
+    }
+
+    static void test3() throws ServerException {
+
+        long startTime = 0;
+        long endTime = 0;
+        boolean foundError = false;
+
+        List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+        // Setup the 2 clients
+        Table t1 = new Table("http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+        t1.initTable();
+        Table t2 = new Table("http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+        t2.update();
+
+
+        // Make the Keys
+        System.out.println("Setting up keys");
+        startTime = System.currentTimeMillis();
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+            String a = "a" + i;
+            String b = "b" + i;
+            String c = "c" + i;
+            String d = "d" + i;
+            IoTString ia = new IoTString(a);
+            IoTString ib = new IoTString(b);
+            IoTString ic = new IoTString(c);
+            IoTString id = new IoTString(d);
+            t1.createNewKey(ia, 321);
+            t1.createNewKey(ib, 351);
+            t2.createNewKey(ic, 321);
+            t2.createNewKey(id, 351);
+        }
+        endTime = System.currentTimeMillis();
+        System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
+        System.out.println("Time Taken Per Key: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
+        System.out.println();
+
+
+        // Do Updates for the keys
+        System.out.println("Setting Key-Values...");
+        startTime = System.currentTimeMillis();
+
+        System.out.println("B...");
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+            String keyB = "b" + i;
+            String valueB = "b" + i;
+
+            IoTString iKeyB = new IoTString(keyB);
+            IoTString iValueB = new IoTString(valueB);
+
+            t1.startTransaction();
+            t1.addKV(iKeyB, iValueB);
+            transStatusList.add(t1.commitTransaction());
+        }
+
+        System.out.println("C...");
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+            String keyC = "c" + i;
+            String valueC = "c" + i;
+
+            IoTString iKeyC = new IoTString(keyC);
+            IoTString iValueC = new IoTString(valueC);
+
+            t2.startTransaction();
+            t2.addKV(iKeyC, iValueC);
+            transStatusList.add(t2.commitTransaction());
+        }
+
+        System.out.println("A, D...");
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+            String keyA = "a" + i;
+            String keyD = "d" + i;
+            String valueA = "a" + i;
+            String valueD = "d" + i;
+
+            IoTString iKeyA = new IoTString(keyA);
+            IoTString iKeyD = new IoTString(keyD);
+            IoTString iValueA = new IoTString(valueA);
+            IoTString iValueD = new IoTString(valueD);
+
+            t1.startTransaction();
+            t1.addKV(iKeyA, iValueA);
+            transStatusList.add(t1.commitTransaction());
+
+            t2.startTransaction();
+            t2.addKV(iKeyD, iValueD);
+            transStatusList.add(t2.commitTransaction());
+        }
+        endTime = System.currentTimeMillis();
+        System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
+        System.out.println("Time Taken Per Update: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
+        System.out.println();
+
+
+        System.out.println("Updating Clients...");
+        t1.update();
+        t2.update();
+
+
+        System.out.println("Checking Key-Values...");
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+
+            String keyA = "a" + i;
+            String keyB = "b" + i;
+            String keyC = "c" + i;
+            String keyD = "d" + i;
+            String valueA = "a" + i;
+            String valueB = "b" + i;
+            String valueC = "c" + i;
+            String valueD = "d" + i;
+
+            IoTString iKeyA = new IoTString(keyA);
+            IoTString iKeyB = new IoTString(keyB);
+            IoTString iKeyC = new IoTString(keyC);
+            IoTString iKeyD = new IoTString(keyD);
+            IoTString iValueA = new IoTString(valueA);
+            IoTString iValueB = new IoTString(valueB);
+            IoTString iValueC = new IoTString(valueC);
+            IoTString iValueD = new IoTString(valueD);
+
+
+            IoTString testValA1 = t1.getCommitted(iKeyA);
+            IoTString testValB1 = t1.getCommitted(iKeyB);
+            IoTString testValC1 = t1.getCommitted(iKeyC);
+            IoTString testValD1 = t1.getCommitted(iKeyD);
+
+            IoTString testValA2 = t2.getCommitted(iKeyA);
+            IoTString testValB2 = t2.getCommitted(iKeyB);
+            IoTString testValC2 = t2.getCommitted(iKeyC);
+            IoTString testValD2 = t2.getCommitted(iKeyD);
+
+            if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyA);
+                foundError = true;
+            }
+
+            if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyB);
+                foundError = true;
+            }
+
+            if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyC);
+                foundError = true;
+            }
+
+            if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyD);
+                foundError = true;
+            }
+
+
+            if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
+                foundError = true;
+            }
+
+            if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                foundError = true;
+            }
+
+            if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
+                foundError = true;
+            }
+
+            if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
+                foundError = true;
+            }
+        }
+
+        for (TransactionStatus status : transStatusList) {
+            if (status.getStatus() != TransactionStatus.StatusCommitted) {
+                foundError = true;
+            }
+        }
+
+        if (foundError) {
+            System.out.println("Found Errors...");
+        } else {
+            System.out.println("No Errors Found...");
+        }
+    }
+
+    static void test2() throws ServerException {
+
+        boolean foundError = false;
+        long startTime = 0;
+        long endTime = 0;
+        List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+        // Setup the 2 clients
+        Table t1 = new Table("http://127.0.0.1/test.iotcloud/", "reallysecret", 321);
+        t1.initTable();
+        System.out.println("T1 Ready");
+
+        Table t2 = new Table("http://127.0.0.1/test.iotcloud/", "reallysecret", 351);
+        t2.update();
+        System.out.println("T2 Ready");
+
+        // Make the Keys
+        System.out.println("Setting up keys");
+        startTime = System.currentTimeMillis();
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+            String a = "a" + i;
+            String b = "b" + i;
+            String c = "c" + i;
+            String d = "d" + i;
+            IoTString ia = new IoTString(a);
+            IoTString ib = new IoTString(b);
+            IoTString ic = new IoTString(c);
+            IoTString id = new IoTString(d);
+            t1.createNewKey(ia, 321);
+            t1.createNewKey(ib, 351);
+            t2.createNewKey(ic, 321);
+            t2.createNewKey(id, 351);
+        }
+        endTime = System.currentTimeMillis();
+        System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
+        System.out.println("Time Taken Per Key: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
+        System.out.println();
+
+        // Do Updates for the keys
+        System.out.println("Setting Key-Values...");
+        startTime = System.currentTimeMillis();
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+            String keyA = "a" + i;
+            String keyB = "b" + i;
+            String keyC = "c" + i;
+            String keyD = "d" + i;
+            String valueA = "a" + i;
+            String valueB = "b" + i;
+            String valueC = "c" + i;
+            String valueD = "d" + i;
+
+            IoTString iKeyA = new IoTString(keyA);
+            IoTString iKeyB = new IoTString(keyB);
+            IoTString iKeyC = new IoTString(keyC);
+            IoTString iKeyD = new IoTString(keyD);
+            IoTString iValueA = new IoTString(valueA);
+            IoTString iValueB = new IoTString(valueB);
+            IoTString iValueC = new IoTString(valueC);
+            IoTString iValueD = new IoTString(valueD);
+
+            t1.startTransaction();
+            t1.addKV(iKeyA, iValueA);
+            transStatusList.add(t1.commitTransaction());
+
+
+            t1.startTransaction();
+            t1.addKV(iKeyB, iValueB);
+            transStatusList.add(t1.commitTransaction());
+
+
+            t2.startTransaction();
+            t2.addKV(iKeyC, iValueC);
+            transStatusList.add(t2.commitTransaction());
+
+
+            t2.startTransaction();
+            t2.addKV(iKeyD, iValueD);
+            transStatusList.add(t2.commitTransaction());
+        }
+        endTime = System.currentTimeMillis();
+        System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
+        System.out.println("Time Taken Per Update: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
+        System.out.println();
+
+
+        System.out.println("Updating Clients...");
+        t1.update();
+        t2.update();
+
+
+        System.out.println("Checking Key-Values...");
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+
+            String keyA = "a" + i;
+            String keyB = "b" + i;
+            String keyC = "c" + i;
+            String keyD = "d" + i;
+            String valueA = "a" + i;
+            String valueB = "b" + i;
+            String valueC = "c" + i;
+            String valueD = "d" + i;
+
+            IoTString iKeyA = new IoTString(keyA);
+            IoTString iKeyB = new IoTString(keyB);
+            IoTString iKeyC = new IoTString(keyC);
+            IoTString iKeyD = new IoTString(keyD);
+            IoTString iValueA = new IoTString(valueA);
+            IoTString iValueB = new IoTString(valueB);
+            IoTString iValueC = new IoTString(valueC);
+            IoTString iValueD = new IoTString(valueD);
+
+
+            IoTString testValA1 = t1.getCommitted(iKeyA);
+            IoTString testValB1 = t1.getCommitted(iKeyB);
+            IoTString testValC1 = t1.getCommitted(iKeyC);
+            IoTString testValD1 = t1.getCommitted(iKeyD);
+
+            IoTString testValA2 = t2.getCommitted(iKeyA);
+            IoTString testValB2 = t2.getCommitted(iKeyB);
+            IoTString testValC2 = t2.getCommitted(iKeyC);
+            IoTString testValD2 = t2.getCommitted(iKeyD);
+
+            if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyA);
+                foundError = true;
+            }
+
+            if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyB);
+                foundError = true;
+            }
+
+            if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyC);
+                foundError = true;
+            }
+
+            if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+                System.out.println("Key-Value t1 incorrect: " + keyD);
+                foundError = true;
+            }
+
+
+            if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
+                foundError = true;
+            }
+
+            if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+                foundError = true;
+            }
+
+            if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
+                foundError = true;
+            }
+
+            if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+                System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
+                foundError = true;
+            }
+        }
+
+        for (TransactionStatus status : transStatusList) {
+            if (status.getStatus() != TransactionStatus.StatusCommitted) {
+                foundError = true;
+                System.out.println(status.getStatus());
+            }
+        }
+
+        if (foundError) {
+            System.out.println("Found Errors...");
+        } else {
+            System.out.println("No Errors Found...");
+        }
+    }
 }
 }
index 90ef4d4fc385b269308cbc6d0716da9ece60ad96..82280c0fb38daab2c7340fb9bcb392ff62ed5879 100644 (file)
 package iotcloud;
 
 package iotcloud;
 
-import java.nio.ByteBuffer;
+import java.util.Map;
 import java.util.Set;
 import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.HashSet;
-import java.util.Map;
+import java.nio.ByteBuffer;
 
 
-class Transaction extends Entry {
+class Transaction {
 
 
-    private long seqnum;
-    private long machineid;
-    private Set<KeyValue> keyValueUpdateSet = null;
+    private Map<Integer, TransactionPart> parts = null;
+    private Set<Integer> missingParts = null;
+    private List<Integer> partsPendingSend = null;
+    private boolean isComplete = false;
     private Set<KeyValue> keyValueGuardSet = null;
     private Set<KeyValue> keyValueGuardSet = null;
-    private Long arbitrator;
+    private Set<KeyValue> keyValueUpdateSet = null;
+    private boolean isDead = false;
+    private long sequenceNumber = -1;
+    private long clientLocalSequenceNumber = -1;
+    private long arbitratorId = -1;
+    private long machineId = -1;
+    private Pair<Long, Long> transactionId = null;
+
+    private int nextPartToSend = 0;
+    private boolean didSendAPartToServer = false;
+
+    private TransactionStatus transactionStatus = null;
+
+    public Transaction() {
+        parts = new HashMap<Integer, TransactionPart>();
+        keyValueGuardSet = new HashSet<KeyValue>();
+        keyValueUpdateSet = new HashSet<KeyValue>();
+        partsPendingSend = new ArrayList<Integer>();
+    }
+
+    public void addPartEncode(TransactionPart newPart) {
+        parts.put(newPart.getPartNumber(), newPart);
+        partsPendingSend.add(newPart.getPartNumber());
+
+        // Get the sequence number and other important information
+        sequenceNumber = newPart.getSequenceNumber();
+        arbitratorId = newPart.getArbitratorId();
+        transactionId = newPart.getTransactionId();
+        clientLocalSequenceNumber = newPart.getClientLocalSequenceNumber();
+        machineId = newPart.getMachineId();
+
+        isComplete = true;
+    }
+
+    public void addPartDecode(TransactionPart newPart) {
+
+        if (isDead) {
+            // If dead then just kill this part and move on
+            newPart.setDead();
+            return;
+        }
+
+        // Get the sequence number and other important information
+        sequenceNumber = newPart.getSequenceNumber();
+        arbitratorId = newPart.getArbitratorId();
+        transactionId = newPart.getTransactionId();
+        clientLocalSequenceNumber = newPart.getClientLocalSequenceNumber();
+        machineId = newPart.getMachineId();
+
+        TransactionPart previoslySeenPart = parts.put(newPart.getPartNumber(), newPart);
+
+        if (previoslySeenPart != null) {
+            // Set dead the old one since the new one is a rescued version of this part
+            previoslySeenPart.setDead();
+        } else if (newPart.isLastPart()) {
+            missingParts = new HashSet<Integer>();
 
 
-    public Transaction(Slot slot, long _seqnum, long _machineid, Long _arbitrator, Set<KeyValue> _keyValueUpdateSet, Set<KeyValue> _keyValueGuardSet) {
-        super(slot);
-        seqnum = _seqnum;
-        machineid = _machineid;
-        arbitrator = _arbitrator;
-        // keyValueUpdateSet = new HashSet<KeyValue>();
-        // keyValueGuardSet = new HashSet<KeyValue>();
+            for (int i = 0; i < newPart.getPartNumber(); i++) {
+                if (parts.get(i) == null) {
+                    missingParts.add(i);
+                }
+            }
+        }
 
 
-        // for (KeyValue kv : _keyValueUpdateSet) {
-        //     KeyValue kvCopy = kv.getCopy();
-        //     keyValueUpdateSet.add(kvCopy);
-        // }
+        if (!isComplete) {
 
 
-        // for (KeyValue kv : _keyValueGuardSet) {
-        //     KeyValue kvCopy = kv.getCopy();
-        //     keyValueGuardSet.add(kvCopy);
-        // }
+            // We have seen this part so remove it from the set of missing parts
+            missingParts.remove(newPart.getPartNumber());
 
 
-        keyValueUpdateSet = _keyValueUpdateSet;
-        keyValueGuardSet = _keyValueGuardSet;
+            // Check if all the parts have been seen
+            if (missingParts.size() == 0) {
+
+                // We have all the parts
+                isComplete = true;
+
+                // Decode all the parts and create the key value guard and update sets
+                decodeTransactionData();
+            }
+        }
     }
 
     }
 
-    public long getMachineID() {
-        return machineid;
+    public void addUpdateKV(KeyValue kv) {
+        keyValueUpdateSet.add(kv);
     }
 
     }
 
-    public long getArbitrator() {
-        return arbitrator;
+    public void addGuardKV(KeyValue kv) {
+        keyValueGuardSet.add(kv);
     }
 
     }
 
+
     public long getSequenceNumber() {
     public long getSequenceNumber() {
-        return seqnum;
+        return sequenceNumber;
     }
 
     }
 
+    public void setSequenceNumber(long _sequenceNumber) {
+        sequenceNumber = _sequenceNumber;
 
 
-    public Set<KeyValue> getkeyValueUpdateSet() {
-        return keyValueUpdateSet;
+        for (Integer i : parts.keySet()) {
+            parts.get(i).setSequenceNumber(sequenceNumber);
+        }
     }
 
     }
 
-    public Set<KeyValue> getkeyValueGuardSet() {
-        return keyValueGuardSet;
+    public long getClientLocalSequenceNumber() {
+        return clientLocalSequenceNumber;
     }
 
     }
 
-    public boolean evaluateGuard(Map<IoTString, KeyValue> keyValTableCommitted, Map<IoTString, KeyValue> keyValTableSpeculative) {
-        for (KeyValue kvGuard : keyValueGuardSet) {
+    public Map<Integer, TransactionPart> getParts() {
+        return parts;
+    }
 
 
-            // First check if the key is in the speculative table, this is the value of the latest assumption
-            KeyValue kv = null;
 
 
-            // If we have a speculation table then use it first
-            if (keyValTableSpeculative != null) {
-                kv = keyValTableSpeculative.get(kvGuard.getKey());
-            }
-
-            if (kv == null) {
+    public boolean didSendAPartToServer() {
+        return didSendAPartToServer;
+    }
 
 
-                // if it is not in the speculative table then check the committed table and use that
-                // value as our latest assumption
-                kv = keyValTableCommitted.get(kvGuard.getKey());
-            }
+    public void resetNextPartToSend() {
+        nextPartToSend = 0;
+    }
 
 
-            if (kvGuard.getValue() != null) {
-                if ((kv == null) || (!kvGuard.getValue().equals(kv.getValue()))) {
-                    return false;
-                }
-            } else {
-                if (kv != null) {
-                    return false;
-                }
-            }
+    public TransactionPart getNextPartToSend() {
+        if ((partsPendingSend.size() == 0) || (partsPendingSend.size() == nextPartToSend)) {
+            return null;
         }
         }
-        return true;
+        TransactionPart part = parts.get(partsPendingSend.get(nextPartToSend));
+        nextPartToSend++;
+        return part;
+    }
+
+    public void setTransactionStatus(TransactionStatus _transactionStatus) {
+        transactionStatus = _transactionStatus;
     }
 
     }
 
-    public byte getType() {
-        return Entry.TypeTransaction;
+    public TransactionStatus getTransactionStatus() {
+        return transactionStatus;
     }
 
     }
 
-    public int getSize() {
-        int size = 3 * Long.BYTES + Byte.BYTES; // seq, machine id, entry type
-        size += Integer.BYTES; // number of KV's
-        size += Integer.BYTES; // number of Guard KV's
+    public void removeSentParts(List<Integer> sentParts) {
+        nextPartToSend = 0;
+        partsPendingSend.removeAll(sentParts);
+        didSendAPartToServer = true;
+        transactionStatus.setTransactionSequenceNumber(sequenceNumber);
+    }
 
 
-        // Size of each KV
-        for (KeyValue kv : keyValueUpdateSet) {
-            size += kv.getSize();
-        }
+    public boolean didSendAllParts() {
+        return partsPendingSend.isEmpty();
+    }
 
 
-        // Size of each Guard KV
-        for (KeyValue kv : keyValueGuardSet) {
-            size += kv.getSize();
-        }
 
 
-        return size;
+    public Set<KeyValue> getKeyValueUpdateSet() {
+        return keyValueUpdateSet;
+    }
+
+    public int getNumberOfParts() {
+        return parts.size();
+    }
+
+    public long getMachineId() {
+        return machineId;
+    }
+
+    public long getArbitrator() {
+        return arbitratorId;
+    }
+
+    public boolean isComplete() {
+        return isComplete;
     }
 
     }
 
-    public void encode(ByteBuffer bb) {
-        bb.put(Entry.TypeTransaction);
-        bb.putLong(seqnum);
-        bb.putLong(machineid);
-        bb.putLong(arbitrator);
+    public Pair<Long, Long> getId() {
+        return transactionId;
+    }
 
 
-        bb.putInt(keyValueUpdateSet.size());
-        for (KeyValue kv : keyValueUpdateSet) {
-            kv.encode(bb);
+    public void setDead() {
+        if (isDead) {
+            // Already dead
+            return;
         }
 
         }
 
-        bb.putInt(keyValueGuardSet.size());
-        for (KeyValue kv : keyValueGuardSet) {
-            kv.encode(bb);
+        // Set dead
+        isDead = true;
+
+        // Make all the parts of this transaction dead
+        for (Integer partNumber : parts.keySet()) {
+            TransactionPart part = parts.get(partNumber);
+            part.setDead();
         }
     }
 
         }
     }
 
-    static Entry decode(Slot slot, ByteBuffer bb) {
-        long seqnum = bb.getLong();
-        long machineid = bb.getLong();
-        long arbitrator = bb.getLong();
-        int numberOfKeys = bb.getInt();
+    public TransactionPart getPart(int index) {
+        return parts.get(index);
+    }
+
+    private void decodeTransactionData() {
 
 
-        Set<KeyValue> kvSetUpdates = new HashSet<KeyValue>();
-        for (int i = 0; i < numberOfKeys; i++) {
-            KeyValue kv = KeyValue.decode(bb);
-            kvSetUpdates.add(kv);
+        // Calculate the size of the data section
+        int dataSize = 0;
+        for (int i = 0; i < parts.keySet().size(); i++) {
+            TransactionPart tp = parts.get(i);
+            dataSize += tp.getDataSize();
         }
 
         }
 
-        int numberOfGuards = bb.getInt();
-        Set<KeyValue> kvSetGuards = new HashSet<KeyValue>();
-        for (int i = 0; i < numberOfGuards; i++) {
-            KeyValue kv = KeyValue.decode(bb);
-            kvSetGuards.add(kv);
+        byte[] combinedData = new byte[dataSize];
+        int currentPosition = 0;
+
+        // Stitch all the data sections together
+        for (int i = 0; i < parts.keySet().size(); i++) {
+            TransactionPart tp = parts.get(i);
+            System.arraycopy(tp.getData(), 0, combinedData, currentPosition, tp.getDataSize());
+            currentPosition += tp.getDataSize();
         }
 
         }
 
-        return new Transaction(slot, seqnum, machineid, arbitrator, kvSetUpdates, kvSetGuards);
+        // Decoder Object
+        ByteBuffer bbDecode = ByteBuffer.wrap(combinedData);
+
+        // Decode how many key value pairs need to be decoded
+        int numberOfKVGuards = bbDecode.getInt();
+        int numberOfKVUpdates = bbDecode.getInt();
+
+        // Decode all the guard key values
+        for (int i = 0; i < numberOfKVGuards; i++) {
+            KeyValue kv = (KeyValue)KeyValue.decode(bbDecode);
+            keyValueGuardSet.add(kv);
+        }
+
+        // Decode all the updates key values
+        for (int i = 0; i < numberOfKVUpdates; i++) {
+            KeyValue kv = (KeyValue)KeyValue.decode(bbDecode);
+            keyValueUpdateSet.add(kv);
+        }
     }
 
     }
 
-    public Entry getCopy(Slot s) {
-        return new Transaction(s, seqnum, machineid, arbitrator, keyValueUpdateSet, keyValueGuardSet);
+    public boolean evaluateGuard(Map<IoTString, KeyValue> committedKeyValueTable, Map<IoTString, KeyValue> speculatedKeyValueTable, Map<IoTString, KeyValue> pendingTransactionSpeculatedKeyValueTable) {
+        for (KeyValue kvGuard : keyValueGuardSet) {
+
+            // First check if the key is in the speculative table, this is the value of the latest assumption
+            KeyValue kv = null;
+
+            // If we have a speculation table then use it first
+            if (pendingTransactionSpeculatedKeyValueTable != null) {
+                kv = pendingTransactionSpeculatedKeyValueTable.get(kvGuard.getKey());
+            }
+
+            // If we have a speculation table then use it first
+            if ((kv == null) && (speculatedKeyValueTable != null)) {
+                kv = speculatedKeyValueTable.get(kvGuard.getKey());
+            }
+
+            if (kv == null) {
+                // if it is not in the speculative table then check the committed table and use that
+                // value as our latest assumption
+                kv = committedKeyValueTable.get(kvGuard.getKey());
+            }
+
+            if (kvGuard.getValue() != null) {
+                if ((kv == null) || (!kvGuard.getValue().equals(kv.getValue()))) {
+                    return false;
+                }
+            } else {
+                if (kv != null) {
+                    return false;
+                }
+            }
+        }
+        return true;
     }
 }
\ No newline at end of file
     }
 }
\ No newline at end of file
diff --git a/version2/src/java/iotcloud/TransactionPart.java b/version2/src/java/iotcloud/TransactionPart.java
new file mode 100644 (file)
index 0000000..17d8e44
--- /dev/null
@@ -0,0 +1,140 @@
+package iotcloud;
+
+import java.nio.ByteBuffer;
+
+class TransactionPart extends Entry {
+
+    // Max size of the part excluding the fixed size header
+    public static final int MAX_NON_HEADER_SIZE = 512;
+
+    private long sequenceNumber = -1;
+    private long machineId = -1;
+    private long arbitratorId = -1;
+    private long clientLocalSequenceNumber = -1; // Sequence number of the transaction that this is a part of
+    private int partNumber = -1; // Parts position in the
+    private Boolean isLastPart = false;
+
+    private Pair<Long, Long> transactionId = null;
+    private Pair<Long, Integer> partId = null;
+
+    private byte[] data = null;
+
+    public TransactionPart(Slot s, long _machineId, long _arbitratorId, long _clientLocalSequenceNumber, int _partNumber, byte[] _data, Boolean _isLastPart) {
+        super(s);
+        machineId = _machineId;
+        arbitratorId = _arbitratorId;
+        clientLocalSequenceNumber = _clientLocalSequenceNumber;
+        partNumber = _partNumber;
+        data = _data;
+        isLastPart = _isLastPart;
+
+        transactionId = new Pair<Long, Long>(machineId, clientLocalSequenceNumber);
+        partId = new Pair<Long, Integer>(clientLocalSequenceNumber, partNumber);
+
+    }
+
+    public int getSize() {
+        if (data == null) {
+            return (4 * Long.BYTES) + (2 * Integer.BYTES) + (2 * Byte.BYTES);
+        }
+        return (4 * Long.BYTES) + (2 * Integer.BYTES) + (2 * Byte.BYTES) + data.length;
+    }
+
+    public void setSlot(Slot s) {
+        parentslot = s;
+    }
+
+    public Pair<Long, Long> getTransactionId() {
+        return transactionId;
+    }
+
+    public long getArbitratorId() {
+        return arbitratorId;
+    }
+
+    public Pair<Long, Integer> getPartId() {
+        return partId;
+    }
+
+    public int getPartNumber() {
+        return partNumber;
+    }
+
+    public int getDataSize() {
+        return data.length;
+    }
+
+    public byte[] getData() {
+        return data;
+    }
+
+    public Boolean isLastPart() {
+        return isLastPart;
+    }
+
+    public long getMachineId() {
+        return machineId;
+    }
+
+    public long getClientLocalSequenceNumber() {
+        return clientLocalSequenceNumber;
+    }
+
+
+    public long getSequenceNumber() {
+        return sequenceNumber;
+    }
+
+    public void setSequenceNumber(long _sequenceNumber) {
+        sequenceNumber = _sequenceNumber;
+    }
+
+    static Entry decode(Slot s, ByteBuffer bb) {
+        long sequenceNumber = bb.getLong();
+        long machineId = bb.getLong();
+        long arbitratorId = bb.getLong();
+        long clientLocalSequenceNumber = bb.getLong();
+        int partNumber = bb.getInt();
+        int dataSize = bb.getInt();
+        Boolean isLastPart = bb.get() == 1;
+
+        // Get the data
+        byte[] data = new byte[dataSize];
+        bb.get(data);
+
+        TransactionPart returnTransactionPart = new TransactionPart(s, machineId, arbitratorId, clientLocalSequenceNumber, partNumber, data, isLastPart);
+        returnTransactionPart.setSequenceNumber(sequenceNumber);
+
+        return returnTransactionPart;
+    }
+
+    public void encode(ByteBuffer bb) {
+        bb.put(Entry.TypeTransactionPart);
+        bb.putLong(sequenceNumber);
+        bb.putLong(machineId);
+        bb.putLong(arbitratorId);
+        bb.putLong(clientLocalSequenceNumber);
+        bb.putInt(partNumber);
+        bb.putInt(data.length);
+
+        if (isLastPart) {
+            bb.put((byte)1);
+        } else {
+            bb.put((byte)0);
+        }
+
+        bb.put(data);
+    }
+
+    public byte getType() {
+        return Entry.TypeTransactionPart;
+    }
+
+    public Entry getCopy(Slot s) {
+
+        TransactionPart copyTransaction = new TransactionPart(s, machineId, arbitratorId, clientLocalSequenceNumber, partNumber, data, isLastPart);
+        copyTransaction.setSequenceNumber(sequenceNumber);
+
+        return copyTransaction;
+    }
+}
\ No newline at end of file
index a42f5703dde1d88ae9b8f4180907a1933a55459f..e397d6ce88651a63579a5cb471b446c52811729c 100644 (file)
@@ -5,13 +5,16 @@ class TransactionStatus {
     static final byte StatusPending = 2;
     static final byte StatusCommitted = 3;
     // static final byte StatusRetrying = 4;
     static final byte StatusPending = 2;
     static final byte StatusCommitted = 3;
     // static final byte StatusRetrying = 4;
-    static final byte StatusSent = 5;
-    static final byte StatusNoEffect = 6;
+    static final byte StatusSentPartial = 5;
+    static final byte StatusSentFully = 6;
+    static final byte StatusNoEffect = 10;
 
     private byte status = 0;
     private boolean applicationReleased = false;
 
     private byte status = 0;
     private boolean applicationReleased = false;
-    private long arbitrator = 0;
     private boolean wasSentInChain = false;
     private boolean wasSentInChain = false;
+    private long transactionSequenceNumber = 0;
+    private long arbitrator = -1;
+
 
     public TransactionStatus(byte _status, long _arbitrator) {
         status = _status;
 
     public TransactionStatus(byte _status, long _arbitrator) {
         status = _status;
@@ -26,20 +29,15 @@ class TransactionStatus {
         status = _status;
     }
 
         status = _status;
     }
 
-    public void setSentTransaction() {
-        wasSentInChain = true;
+    public long getTransactionSequenceNumber() {
+        return transactionSequenceNumber;
     }
 
     }
 
-    public boolean getSentTransaction() {
-        return wasSentInChain;
+    public void setTransactionSequenceNumber(long _transactionSequenceNumber) {
+        transactionSequenceNumber = _transactionSequenceNumber;
     }
 
     }
 
-
-    // public void setArbitrator(long _arbitrator) {
-    //     arbitrator = _arbitrator;
-    // }
-
-    public long getArbitrator() {
+    public long getTransactionArbitrator() {
         return arbitrator;
     }
 
         return arbitrator;
     }
 
diff --git a/version2/src/java/iotcloud/issues.txt b/version2/src/java/iotcloud/issues.txt
deleted file mode 100644 (file)
index 4c246b6..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-1) add better resizing support...gets stuck when it is full now...
-2) Transaction does not check arbitrator is the same for all keys and guards
\ No newline at end of file
diff --git a/version2/src/script/C.cfg b/version2/src/script/C.cfg
deleted file mode 100644 (file)
index 6165d83..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-indent_with_tabs = 2
-indent_cmt_with_tabs = True
-indent_columns = 2
-indent_class = True
-output_tab_size = 2
-nl_if_brace = Remove
-nl_brace_else = Remove
-nl_elseif_brace = Remove
-nl_struct_brace = Remove
-nl_union_brace = Remove
-nl_fcall_brace = Remove
-nl_for_brace = Remove
-nl_fdef_brace = Remove
-nl_while_brace = Remove
-nl_do_brace = Remove
-nl_brace_while = Remove
-nl_switch_brace = Remove
-nl_before_case = True
-nl_try_brace = Remove
-nl_catch_brace = Remove
-nl_brace_catch = Remove
-sp_func_proto_paren = Remove
-sp_func_def_paren = Remove
-sp_inside_fparens = remove
-sp_inside_fparen = remove
-sp_func_call_paren = Remove
-sp_fparen_brace = Add
-sp_sparen_brace = Add
-sp_paren_brace = Add
-sp_else_brace = Add
-sp_brace_else = Add
-sp_catch_brace = Add
-sp_brace_catch = Add
-sp_try_brace = Add
-sp_after_sparen = Add
-sp_cond_colon = remove
-sp_cond_question = remove
diff --git a/version2/src/script/java.cfg b/version2/src/script/java.cfg
deleted file mode 100644 (file)
index 6165d83..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-indent_with_tabs = 2
-indent_cmt_with_tabs = True
-indent_columns = 2
-indent_class = True
-output_tab_size = 2
-nl_if_brace = Remove
-nl_brace_else = Remove
-nl_elseif_brace = Remove
-nl_struct_brace = Remove
-nl_union_brace = Remove
-nl_fcall_brace = Remove
-nl_for_brace = Remove
-nl_fdef_brace = Remove
-nl_while_brace = Remove
-nl_do_brace = Remove
-nl_brace_while = Remove
-nl_switch_brace = Remove
-nl_before_case = True
-nl_try_brace = Remove
-nl_catch_brace = Remove
-nl_brace_catch = Remove
-sp_func_proto_paren = Remove
-sp_func_def_paren = Remove
-sp_inside_fparens = remove
-sp_inside_fparen = remove
-sp_func_call_paren = Remove
-sp_fparen_brace = Add
-sp_sparen_brace = Add
-sp_paren_brace = Add
-sp_else_brace = Add
-sp_brace_else = Add
-sp_catch_brace = Add
-sp_brace_catch = Add
-sp_try_brace = Add
-sp_after_sparen = Add
-sp_cond_colon = remove
-sp_cond_question = remove
diff --git a/version2/src/script/makefile b/version2/src/script/makefile
deleted file mode 100644 (file)
index ac2da6e..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-tabbing:
-       uncrustify -c java.cfg --no-backup $$(find .. -name "*.java")
-       uncrustify -c C.cfg --no-backup $$(find .. -name "*.cpp")
-       uncrustify -c C.cfg --no-backup $$(find .. -name "*.h")