edits
[iotcloud.git] / version2 / src / C / PendingTransaction.h
1
2
3
4
5 class PendingTransaction {
6
7     private Set<KeyValue> keyValueUpdateSet = NULL;
8     private Set<KeyValue> keyValueGuardSet = NULL;
9     private int64_t arbitrator = -1;
10     private int64_t clientLocalSequenceNumber = -1;
11     private int64_t machineId = -1;
12
13     private int currentDataSize = 0;
14
15     public PendingTransaction(int64_t _machineId) {
16         machineId = _machineId;
17         keyValueUpdateSet = new HashSet<KeyValue>();
18         keyValueGuardSet = new HashSet<KeyValue>();
19     }
20
21     /**
22      * Add a new key value to the updates
23      *
24      */
25     public void addKV(KeyValue newKV) {
26
27         KeyValue rmKV = NULL;
28
29         // Make sure there are no duplicates
30         for (KeyValue kv : keyValueUpdateSet) {
31             if (kv.getKey().equals(newKV.getKey())) {
32
33                 // Remove key if we are adding a newer version of the same key
34                 rmKV = kv;
35                 break;
36             }
37         }
38
39         // Remove key if we are adding a newer version of the same key
40         if (rmKV != NULL) {
41             keyValueUpdateSet.remove(rmKV);
42             currentDataSize -= rmKV.getSize();
43         }
44
45         // Add the key to the hash set
46         keyValueUpdateSet.add(newKV);
47         currentDataSize += newKV.getSize();
48     }
49
50     /**
51      * Add a new key value to the guard set
52      *
53      */
54     public void addKVGuard(KeyValue newKV) {
55         // Add the key to the hash set
56         keyValueGuardSet.add(newKV);
57         currentDataSize += newKV.getSize();
58     }
59
60     /**
61      * Checks if the arbitrator is the same
62      */
63     public bool checkArbitrator(int64_t arb) {
64         if (arbitrator == -1) {
65             arbitrator = arb;
66             return true;
67         }
68
69         return arb == arbitrator;
70     }
71
72     /**
73      * Get the transaction arbitrator
74      */
75     public int64_t getArbitrator() {
76         return arbitrator;
77     }
78
79     /**
80      * Get the key value update set
81      */
82     public Set<KeyValue> getKVUpdates() {
83         return keyValueUpdateSet;
84     }
85
86     /**
87      * Get the key value update set
88      */
89     public Set<KeyValue> getKVGuard() {
90         return keyValueGuardSet;
91     }
92
93     public void setClientLocalSequenceNumber(int64_t _clientLocalSequenceNumber) {
94         clientLocalSequenceNumber = _clientLocalSequenceNumber;
95     }
96
97     public int64_t getClientLocalSequenceNumber() {
98         return clientLocalSequenceNumber;
99     }
100
101     public int64_t getMachineId() {
102         return machineId;
103     }
104
105     public bool evaluateGuard(Map<IoTString, KeyValue> keyValTableCommitted, Map<IoTString, KeyValue> keyValTableSpeculative, Map<IoTString, KeyValue> keyValTablePendingTransSpeculative) {
106         for (KeyValue kvGuard : keyValueGuardSet) {
107
108             // First check if the key is in the speculative table, this is the value of the latest assumption
109             KeyValue kv = keyValTablePendingTransSpeculative.get(kvGuard.getKey());
110
111
112             if (kv == NULL) {
113                 // if it is not in the pending trans table then check the speculative table and use that
114                 // value as our latest assumption
115                 kv = keyValTableSpeculative.get(kvGuard.getKey());
116             }
117
118
119             if (kv == NULL) {
120                 // if it is not in the speculative table then check the committed table and use that
121                 // value as our latest assumption
122                 kv = keyValTableCommitted.get(kvGuard.getKey());
123             }
124
125             if (kvGuard.getValue() != NULL) {
126                 if ((kv == NULL) || (!kvGuard.getValue().equals(kv.getValue()))) {
127                     return false;
128                 }
129             } else {
130                 if (kv != NULL) {
131                     return false;
132                 }
133             }
134         }
135         return true;
136     }
137
138     public Transaction createTransaction() {
139
140         Transaction newTransaction = new Transaction();
141         int transactionPartCount = 0;
142
143         // Convert all the data into a char array so we can start partitioning
144         char[] charData = convertDataToBytes();
145
146         int currentPosition = 0;
147         int remaining = charData.length;
148
149         while (remaining > 0) {
150
151             Boolean isLastPart = false;
152             // determine how much to copy
153             int copySize = TransactionPart.MAX_NON_HEADER_SIZE;
154             if (remaining <= TransactionPart.MAX_NON_HEADER_SIZE) {
155                 copySize = remaining;
156                 isLastPart = true; // last bit of data so last part
157             }
158
159             // Copy to a smaller version
160             char[] partData = new char[copySize];
161             System.arraycopy(charData, currentPosition, partData, 0, copySize);
162
163             TransactionPart part = new TransactionPart(NULL, machineId, arbitrator, clientLocalSequenceNumber, transactionPartCount, partData, isLastPart);
164             newTransaction.addPartEncode(part);
165
166             // Update position, count and remaining
167             currentPosition += copySize;
168             transactionPartCount++;
169             remaining -= copySize;
170         }
171
172         // Add the Guard Conditions
173         for (KeyValue kv : keyValueGuardSet) {
174             newTransaction.addGuardKV(kv);
175         }
176
177         //  Add the updates
178         for (KeyValue kv : keyValueUpdateSet) {
179             newTransaction.addUpdateKV(kv);
180         }
181
182         return newTransaction;
183     }
184
185     private char[] convertDataToBytes() {
186
187         // Calculate the size of the data
188         int sizeOfData = 2 * sizeof(int32_t); // Number of Update KV's and Guard KV's
189         sizeOfData += currentDataSize;
190
191         // Data handlers and storage
192         char[] dataArray = new char[sizeOfData];
193         ByteBuffer bbEncode = ByteBuffer.wrap(dataArray);
194
195         // Encode the size of the updates and guard sets
196         bbEncode.putInt(keyValueGuardSet.size());
197         bbEncode.putInt(keyValueUpdateSet.size());
198
199         // Encode all the guard conditions
200         for (KeyValue kv : keyValueGuardSet) {
201             kv.encode(bbEncode);
202         }
203
204         // Encode all the updates
205         for (KeyValue kv : keyValueUpdateSet) {
206             kv.encode(bbEncode);
207         }
208
209         return bbEncode.array();
210     }
211 }