Skip to content

Commit a8bfdb7

Browse files
committed
[Core] Fix concurrency issues when reading from DataBlocks with internal
block indexing
1 parent 1729671 commit a8bfdb7

File tree

3 files changed

+225
-203
lines changed

3 files changed

+225
-203
lines changed

lib-ogc/swe-common-core/src/main/java/org/vast/data/DataBlockList.java

Lines changed: 69 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,15 @@ public class DataBlockList extends AbstractDataBlock
3939
private static final long serialVersionUID = -413032909256132305L;
4040
protected List<DataBlock> blockList; // either ArrayList or LinkedList so it's serializable
4141
protected int blockAtomCount = -1;
42-
protected boolean equalBlockSize;
43-
transient protected int blockIndex;
44-
transient protected int localIndex;
42+
protected boolean equalBlockSize;
4543
transient ThreadLocal<CachedIndex> cachedIndex = new ThreadLocal<>();
4644

4745
static class CachedIndex
4846
{
4947
int lastIndex; // last requested index
5048
int cumulIndex;
51-
int blockIndex;
49+
int blockIndex;
50+
int localIndex;
5251
}
5352

5453

@@ -154,8 +153,8 @@ public DataType getDataType()
154153
@Override
155154
public DataType getDataType(int index)
156155
{
157-
selectBlock(index);
158-
return blockList.get(blockIndex).getDataType();
156+
var cachedIndex = selectBlock(index);
157+
return blockList.get(cachedIndex.blockIndex).getDataType();
159158
}
160159

161160

@@ -190,30 +189,38 @@ public void updateAtomCount()
190189
}
191190

192191

193-
protected final void selectBlock(int index)
192+
protected final CachedIndex selectBlock(int index)
194193
{
195-
int desiredIndex = index + startIndex;
194+
int desiredIndex = index + startIndex;
196195

196+
// use thread local index so we can read concurrently from multiple threads
197+
CachedIndex cachedIdx = cachedIndex.get();
198+
if (cachedIdx == null) {
199+
cachedIdx = new CachedIndex();
200+
cachedIndex.set(cachedIdx);
201+
}
202+
197203
if (equalBlockSize)
198204
{
199-
blockIndex = desiredIndex / blockAtomCount;
200-
localIndex = desiredIndex % blockAtomCount;
205+
cachedIdx.blockIndex = desiredIndex / blockAtomCount;
206+
cachedIdx.localIndex = desiredIndex % blockAtomCount;
201207
}
202208
else
203209
{
204-
// use thread local cached index to speed up sequential scans
205-
CachedIndex cachedIdx = cachedIndex.get();
206-
if (cachedIdx == null || index <= cachedIdx.lastIndex)
207-
{
208-
cachedIdx = new CachedIndex();
209-
cachedIndex.set(cachedIdx);
210+
// speed up sequential scans by restarting from previous index
211+
// but reset if desired index is going back down
212+
if (index <= cachedIdx.lastIndex) {
213+
cachedIdx.lastIndex = 0;
214+
cachedIdx.cumulIndex = 0;
215+
cachedIdx.blockIndex = 0;
216+
cachedIdx.localIndex = 0;
210217
}
211218

212219
int size = 0;
213220
int cumul = cachedIdx.cumulIndex;
214221
int i = cachedIdx.blockIndex;
215222

216-
while (desiredIndex >= cumul)
223+
while (desiredIndex >= cumul)
217224
{
218225
size = blockList.get(i).getAtomCount();
219226
cumul += size;
@@ -222,14 +229,15 @@ protected final void selectBlock(int index)
222229

223230
// actually use previous block because we went one block too far
224231
cumul -= size;
225-
blockIndex = i - 1;
226-
localIndex = desiredIndex - cumul;
232+
cachedIdx.blockIndex = i - 1;
233+
cachedIdx.localIndex = desiredIndex - cumul;
227234

228235
// save indexing variables in cache for next call
229236
cachedIdx.lastIndex = index;
230237
cachedIdx.cumulIndex = cumul;
231-
cachedIdx.blockIndex = blockIndex;
232-
}
238+
}
239+
240+
return cachedIdx;
233241
}
234242

235243

@@ -313,159 +321,159 @@ public String toString()
313321
@Override
314322
public boolean getBooleanValue(int index)
315323
{
316-
selectBlock(index);
317-
return blockList.get(blockIndex).getBooleanValue(localIndex);
324+
var idx = selectBlock(index);
325+
return blockList.get(idx.blockIndex).getBooleanValue(idx.localIndex);
318326
}
319327

320328

321329
@Override
322330
public byte getByteValue(int index)
323331
{
324-
selectBlock(index);
325-
return blockList.get(blockIndex).getByteValue(localIndex);
332+
var idx = selectBlock(index);
333+
return blockList.get(idx.blockIndex).getByteValue(idx.localIndex);
326334
}
327335

328336

329337
@Override
330338
public short getShortValue(int index)
331339
{
332-
selectBlock(index);
333-
return blockList.get(blockIndex).getShortValue(localIndex);
340+
var idx = selectBlock(index);
341+
return blockList.get(idx.blockIndex).getShortValue(idx.localIndex);
334342
}
335343

336344

337345
@Override
338346
public int getIntValue(int index)
339347
{
340-
selectBlock(index);
341-
return blockList.get(blockIndex).getIntValue(localIndex);
348+
var idx = selectBlock(index);
349+
return blockList.get(idx.blockIndex).getIntValue(idx.localIndex);
342350
}
343351

344352

345353
@Override
346354
public long getLongValue(int index)
347355
{
348-
selectBlock(index);
349-
return blockList.get(blockIndex).getLongValue(localIndex);
356+
var idx = selectBlock(index);
357+
return blockList.get(idx.blockIndex).getLongValue(idx.localIndex);
350358
}
351359

352360

353361
@Override
354362
public float getFloatValue(int index)
355363
{
356-
selectBlock(index);
357-
return blockList.get(blockIndex).getFloatValue(localIndex);
364+
var idx = selectBlock(index);
365+
return blockList.get(idx.blockIndex).getFloatValue(idx.localIndex);
358366
}
359367

360368

361369
@Override
362370
public double getDoubleValue(int index)
363371
{
364-
selectBlock(index);
365-
return blockList.get(blockIndex).getDoubleValue(localIndex);
372+
var idx = selectBlock(index);
373+
return blockList.get(idx.blockIndex).getDoubleValue(idx.localIndex);
366374
}
367375

368376

369377
@Override
370378
public String getStringValue(int index)
371379
{
372-
selectBlock(index);
373-
return blockList.get(blockIndex).getStringValue(localIndex);
380+
var idx = selectBlock(index);
381+
return blockList.get(idx.blockIndex).getStringValue(idx.localIndex);
374382
}
375383

376384

377385
@Override
378386
public Instant getTimeStamp(int index)
379387
{
380-
selectBlock(index);
381-
return blockList.get(blockIndex).getTimeStamp(localIndex);
388+
var idx = selectBlock(index);
389+
return blockList.get(idx.blockIndex).getTimeStamp(idx.localIndex);
382390
}
383391

384392

385393
@Override
386394
public OffsetDateTime getDateTime(int index)
387395
{
388-
selectBlock(index);
389-
return blockList.get(blockIndex).getDateTime(localIndex);
396+
var idx = selectBlock(index);
397+
return blockList.get(idx.blockIndex).getDateTime(idx.localIndex);
390398
}
391399

392400

393401
@Override
394402
public void setBooleanValue(int index, boolean value)
395403
{
396-
selectBlock(index);
397-
blockList.get(blockIndex).setBooleanValue(localIndex, value);
404+
var idx = selectBlock(index);
405+
blockList.get(idx.blockIndex).setBooleanValue(idx.localIndex, value);
398406
}
399407

400408

401409
@Override
402410
public void setByteValue(int index, byte value)
403411
{
404-
selectBlock(index);
405-
blockList.get(blockIndex).setByteValue(localIndex, value);
412+
var idx = selectBlock(index);
413+
blockList.get(idx.blockIndex).setByteValue(idx.localIndex, value);
406414
}
407415

408416

409417
@Override
410418
public void setShortValue(int index, short value)
411419
{
412-
selectBlock(index);
413-
blockList.get(blockIndex).setShortValue(localIndex, value);
420+
var idx = selectBlock(index);
421+
blockList.get(idx.blockIndex).setShortValue(idx.localIndex, value);
414422
}
415423

416424

417425
@Override
418426
public void setIntValue(int index, int value)
419427
{
420-
selectBlock(index);
421-
blockList.get(blockIndex).setIntValue(localIndex, value);
428+
var idx = selectBlock(index);
429+
blockList.get(idx.blockIndex).setIntValue(idx.localIndex, value);
422430
}
423431

424432

425433
@Override
426434
public void setLongValue(int index, long value)
427435
{
428-
selectBlock(index);
429-
blockList.get(blockIndex).setLongValue(localIndex, value);
436+
var idx = selectBlock(index);
437+
blockList.get(idx.blockIndex).setLongValue(idx.localIndex, value);
430438
}
431439

432440

433441
@Override
434442
public void setFloatValue(int index, float value)
435443
{
436-
selectBlock(index);
437-
blockList.get(blockIndex).setFloatValue(localIndex, value);
444+
var idx = selectBlock(index);
445+
blockList.get(idx.blockIndex).setFloatValue(idx.localIndex, value);
438446
}
439447

440448

441449
@Override
442450
public void setDoubleValue(int index, double value)
443451
{
444-
selectBlock(index);
445-
blockList.get(blockIndex).setDoubleValue(localIndex, value);
452+
var idx = selectBlock(index);
453+
blockList.get(idx.blockIndex).setDoubleValue(idx.localIndex, value);
446454
}
447455

448456

449457
@Override
450458
public void setStringValue(int index, String value)
451459
{
452-
selectBlock(index);
453-
blockList.get(blockIndex).setStringValue(localIndex, value);
460+
var idx = selectBlock(index);
461+
blockList.get(idx.blockIndex).setStringValue(idx.localIndex, value);
454462
}
455463

456464

457465
@Override
458466
public void setTimeStamp(int index, Instant value)
459467
{
460-
selectBlock(index);
461-
blockList.get(blockIndex).setTimeStamp(localIndex, value);
468+
var idx = selectBlock(index);
469+
blockList.get(idx.blockIndex).setTimeStamp(idx.localIndex, value);
462470
}
463471

464472

465473
@Override
466474
public void setDateTime(int index, OffsetDateTime value)
467475
{
468-
selectBlock(index);
469-
blockList.get(blockIndex).setDateTime(localIndex, value);
476+
var idx = selectBlock(index);
477+
blockList.get(idx.blockIndex).setDateTime(idx.localIndex, value);
470478
}
471479
}

0 commit comments

Comments
 (0)