16
16
package de .jetsli .graph .storage ;
17
17
18
18
import de .jetsli .graph .coll .MyBitSet ;
19
+ import de .jetsli .graph .coll .MyBitSetImpl ;
19
20
import de .jetsli .graph .coll .MyOpenBitSet ;
21
+ import de .jetsli .graph .coll .MyTBitSet ;
20
22
import de .jetsli .graph .util .EdgeIdIterator ;
21
23
import de .jetsli .graph .util .Helper ;
22
24
import gnu .trove .list .array .TIntArrayList ;
25
27
import java .io .IOException ;
26
28
import java .util .Arrays ;
27
29
import java .util .Date ;
30
+ import javax .management .RuntimeErrorException ;
28
31
import org .slf4j .Logger ;
29
32
import org .slf4j .LoggerFactory ;
30
33
@@ -375,88 +378,104 @@ public void optimize() {
375
378
return ;
376
379
377
380
378
- if (deleted < size / 5 )
379
- optimizeIfFewDeletes (deleted );
380
- else
381
- optimizeIfLotsOfDeletes (deleted );
381
+ // if (deleted < size / 5) {
382
+ inPlaceDelete (deleted );
383
+ // } else
384
+ // optimizeIfLotsOfDeletes(deleted);
382
385
}
383
386
384
387
/**
385
388
* This methods moves the last nodes into the deleted nodes, which is much more memory friendly
386
- * but probably slower than optimizeIfLotsOfDeletes for many deletes.
389
+ * for only a few deletes but probably not for many deletes.
387
390
*/
388
- void optimizeIfFewDeletes (int deleted ) {
391
+ void inPlaceDelete (int deleted ) {
389
392
// Alternative to this method: use smaller segments for nodes and not one big fat java array?
390
393
//
391
- // Prepare edge-update of nodes which are connected to deleted nodes and
392
- // create old- to new-index map.
393
- int index = getNodes ();
394
- int counter = 0 ;
395
- int newIndices [] = new int [deleted ];
396
- int oldIndices [] = new int [deleted ];
397
- TIntIntHashMap markedMap = new TIntIntHashMap (deleted , 1.5f , -1 , -1 );
398
- for (int del = deletedNodes .next (0 ); del >= 0 ; del = deletedNodes .next (del + 1 )) {
399
- EdgeIdIterator delEdgesIter = getEdges (del );
394
+ // Prepare edge-update of nodes which are connected to deleted nodes
395
+ int toMoveNode = getNodes ();
396
+ int itemsToMove = 0 ;
397
+ int maxMoves = Math .min (deleted , Math .max (0 , toMoveNode - deleted ));
398
+ int newIndices [] = new int [maxMoves ];
399
+ int oldIndices [] = new int [maxMoves ];
400
+
401
+ TIntIntHashMap oldToNewIndexMap = new TIntIntHashMap (deleted , 1.5f , -1 , -1 );
402
+ MyBitSetImpl toUpdate = new MyBitSetImpl (deleted * 3 );
403
+ for (int delNode = deletedNodes .next (0 ); delNode >= 0 ; delNode = deletedNodes .next (delNode + 1 )) {
404
+ EdgeIdIterator delEdgesIter = getEdges (delNode );
400
405
while (delEdgesIter .next ()) {
401
406
int currNode = delEdgesIter .nodeId ();
402
407
if (deletedNodes .contains (currNode ))
403
408
continue ;
404
409
405
- // remove all edges to the deleted nodes
406
- EdgeIdIterator nodesConnectedToDelIter = getEdges (currNode );
407
- boolean firstNext = nodesConnectedToDelIter .next ();
408
- if (firstNext ) {
409
- // this forces new edges to be created => TODO only update the edges. do not create new entries
410
- refToEdges [currNode ] = -1 ;
411
- do {
412
- if (!deletedNodes .contains (nodesConnectedToDelIter .nodeId ()))
413
- internalAdd (currNode , nodesConnectedToDelIter .nodeId (),
414
- nodesConnectedToDelIter .distance (), nodesConnectedToDelIter .flags ());
415
- } while (nodesConnectedToDelIter .next ());
416
- }
410
+ toUpdate .add (currNode );
417
411
}
418
412
419
- index --;
420
- for (; index >= 0 ; index --) {
421
- if (!deletedNodes .contains (index ))
413
+ toMoveNode --;
414
+ for (; toMoveNode >= 0 ; toMoveNode --) {
415
+ if (!deletedNodes .contains (toMoveNode ))
422
416
break ;
423
417
}
424
418
425
- newIndices [counter ] = del ;
426
- oldIndices [counter ] = index ;
427
- markedMap .put (index , del );
428
- counter ++;
419
+ if (toMoveNode < delNode )
420
+ break ;
421
+
422
+ // create sorted old- to new-index map
423
+ newIndices [itemsToMove ] = delNode ;
424
+ oldIndices [itemsToMove ] = toMoveNode ;
425
+ oldToNewIndexMap .put (toMoveNode , delNode );
426
+ itemsToMove ++;
429
427
}
430
428
431
- // now move marked nodes into deleted nodes
432
- for (int i = 0 ; i < oldIndices .length ; i ++) {
429
+ // all deleted nodes could be connected to existing. remove the connections
430
+ for (int toUpdateNode = toUpdate .next (0 ); toUpdateNode >= 0 ; toUpdateNode = toUpdate .next (toUpdateNode + 1 )) {
431
+ // remove all edges to the deleted nodes
432
+ EdgeIdIterator nodesConnectedToDelIter = getEdges (toUpdateNode );
433
+ // hack to remove edges ref afterwards
434
+ boolean firstNext = nodesConnectedToDelIter .next ();
435
+ if (firstNext ) {
436
+ // this forces new edges to be created => TODO only update the edges. do not create new entries
437
+ refToEdges [toUpdateNode ] = EMPTY_LINK ;
438
+ do {
439
+ if (!deletedNodes .contains (nodesConnectedToDelIter .nodeId ()))
440
+ internalAdd (toUpdateNode , nodesConnectedToDelIter .nodeId (),
441
+ nodesConnectedToDelIter .distance (), nodesConnectedToDelIter .flags ());
442
+ } while (nodesConnectedToDelIter .next ());
443
+ }
444
+ }
445
+ toUpdate .clear ();
446
+
447
+ // marks connected nodes to rewrite the edges
448
+ for (int i = 0 ; i < itemsToMove ; i ++) {
433
449
int oldI = oldIndices [i ];
434
- int newI = newIndices [i ];
450
+ EdgeIdIterator movedEdgeIter = getEdges (oldI );
451
+ while (movedEdgeIter .next ()) {
452
+ if (deletedNodes .contains (movedEdgeIter .nodeId ()))
453
+ throw new IllegalStateException ("shouldn't happen the edge to the node " + movedEdgeIter .nodeId () + " should be already deleted. " + oldI );
435
454
436
- EdgeIdIterator toMoveEdgeIter = getEdges (oldI );
437
- while (toMoveEdgeIter .next ()) {
438
- int movedNewIndex = markedMap .get (toMoveEdgeIter .nodeId ());
439
- // if node not moved at all (<0) or node is not yet moved use the old index
440
- if (movedNewIndex < 0 || movedNewIndex >= newI ) {
441
- movedNewIndex = toMoveEdgeIter .nodeId ();
442
- }
443
-
444
- // update edges of r to use newI instead of oldI
445
- EdgeIdIterator updateIter = getEdges (movedNewIndex );
446
- boolean firstNext = updateIter .next ();
447
- if (firstNext ) {
448
- // this forces new edges to be created => TODO only update the edges. do not create new entries
449
- refToEdges [movedNewIndex ] = -1 ;
450
- do {
451
- int connNode ;
452
- if (updateIter .nodeId () == oldI )
453
- connNode = newI ;
454
- else
455
- connNode = updateIter .nodeId ();
456
- internalAdd (movedNewIndex , connNode , updateIter .distance (), updateIter .flags ());
457
- } while (updateIter .next ());
458
- }
455
+ toUpdate .add (movedEdgeIter .nodeId ());
459
456
}
457
+ }
458
+
459
+ // rewrite the edges of nodes connected to moved nodes
460
+ for (int toUpdateNode = toUpdate .next (0 ); toUpdateNode >= 0 ; toUpdateNode = toUpdate .next (toUpdateNode + 1 )) {
461
+ EdgeIdIterator connectedToMovedIter = getEdges (toUpdateNode );
462
+ boolean firstNext = connectedToMovedIter .next ();
463
+ if (firstNext ) {
464
+ refToEdges [toUpdateNode ] = EMPTY_LINK ;
465
+ do {
466
+ int currNode = connectedToMovedIter .nodeId ();
467
+ int other = oldToNewIndexMap .get (currNode );
468
+ if (other < 0 )
469
+ other = currNode ;
470
+ internalAdd (toUpdateNode , other , connectedToMovedIter .distance (), connectedToMovedIter .flags ());
471
+ } while (connectedToMovedIter .next ());
472
+ }
473
+ }
474
+
475
+ // move nodes into deleted nodes
476
+ for (int i = 0 ; i < itemsToMove ; i ++) {
477
+ int oldI = oldIndices [i ];
478
+ int newI = newIndices [i ];
460
479
refToEdges [newI ] = refToEdges [oldI ];
461
480
lats [newI ] = lats [oldI ];
462
481
lons [newI ] = lons [oldI ];
@@ -469,7 +488,7 @@ void optimizeIfFewDeletes(int deleted) {
469
488
/**
470
489
* This methods creates a new in-memory graph without the specified deleted nodes.
471
490
*/
472
- void optimizeIfLotsOfDeletes (int deleted ) {
491
+ void replacingDelete (int deleted ) {
473
492
MemoryGraphSafe inMemGraph = new MemoryGraphSafe (null , getNodes () - deleted , getMaxEdges ());
474
493
475
494
// see MMapGraph for a near duplicate
0 commit comments