2020import static org .lwjgl .system .MemoryUtil .NULL ;
2121import static org .lwjgl .util .lmdb .LMDB .MDB_CREATE ;
2222import static org .lwjgl .util .lmdb .LMDB .MDB_FIRST ;
23+ import static org .lwjgl .util .lmdb .LMDB .MDB_KEYEXIST ;
2324import static org .lwjgl .util .lmdb .LMDB .MDB_LAST ;
2425import static org .lwjgl .util .lmdb .LMDB .MDB_NEXT ;
2526import static org .lwjgl .util .lmdb .LMDB .MDB_NOMETASYNC ;
27+ import static org .lwjgl .util .lmdb .LMDB .MDB_NOOVERWRITE ;
2628import static org .lwjgl .util .lmdb .LMDB .MDB_NOSYNC ;
2729import static org .lwjgl .util .lmdb .LMDB .MDB_NOTFOUND ;
2830import static org .lwjgl .util .lmdb .LMDB .MDB_NOTLS ;
2931import static org .lwjgl .util .lmdb .LMDB .MDB_PREV ;
3032import static org .lwjgl .util .lmdb .LMDB .MDB_SET_RANGE ;
33+ import static org .lwjgl .util .lmdb .LMDB .MDB_SUCCESS ;
3134import static org .lwjgl .util .lmdb .LMDB .mdb_cmp ;
3235import static org .lwjgl .util .lmdb .LMDB .mdb_cursor_close ;
3336import static org .lwjgl .util .lmdb .LMDB .mdb_cursor_get ;
4750import static org .lwjgl .util .lmdb .LMDB .mdb_put ;
4851import static org .lwjgl .util .lmdb .LMDB .mdb_set_compare ;
4952import static org .lwjgl .util .lmdb .LMDB .mdb_stat ;
53+ import static org .lwjgl .util .lmdb .LMDB .mdb_strerror ;
5054import static org .lwjgl .util .lmdb .LMDB .mdb_txn_abort ;
5155import static org .lwjgl .util .lmdb .LMDB .mdb_txn_begin ;
5256import static org .lwjgl .util .lmdb .LMDB .mdb_txn_commit ;
9296import org .slf4j .LoggerFactory ;
9397
9498/**
95- * LMDB-based indexed storage and retrieval of RDF statements. TripleStore stores statements in the form of four integer
99+ * LMDB-based indexed storage and retrieval of RDF statements. TripleStore stores statements in the form of four long
96100 * IDs. Each ID represent an RDF value that is stored in a {@link ValueStore}. The four IDs refer to the statement's
97101 * subject, predicate, object and context. The ID <tt>0</tt> is used to represent the "null" context and doesn't map to
98102 * an actual RDF value.
@@ -539,7 +543,7 @@ protected void bucketStart(double fraction, long[] lowerValues, long[] upperValu
539543 * @throws IOException
540544 */
541545 protected void filterUsedIds (Collection <Long > ids ) throws IOException {
542- try ( MemoryStack stack = stackPush ()) {
546+ readTransaction ( env , ( stack , txn ) -> {
543547 MDBVal maxKey = MDBVal .malloc (stack );
544548 ByteBuffer maxKeyBuf = stack .malloc (TripleStore .MAX_KEY_LENGTH );
545549 MDBVal keyData = MDBVal .malloc (stack );
@@ -559,7 +563,7 @@ protected void filterUsedIds(Collection<Long> ids) throws IOException {
559563 keyBuf .clear ();
560564 Varint .writeUnsigned (keyBuf , id );
561565 keyData .mv_data (keyBuf .flip ());
562- if (mdb_get (writeTxn , contextsDbi , keyData , valueData ) == 0 ) {
566+ if (mdb_get (txn , contextsDbi , keyData , valueData ) == 0 ) {
563567 it .remove ();
564568 }
565569 }
@@ -580,7 +584,7 @@ protected void filterUsedIds(Collection<Long> ids) throws IOException {
580584
581585 long cursor = 0 ;
582586 try {
583- E (mdb_cursor_open (writeTxn , dbi , pp ));
587+ E (mdb_cursor_open (txn , dbi , pp ));
584588 cursor = pp .get (0 );
585589
586590 if (fullScan ) {
@@ -626,7 +630,7 @@ protected void filterUsedIds(Collection<Long> ids) throws IOException {
626630 int rc = mdb_cursor_get (cursor , keyData , valueData , MDB_SET_RANGE );
627631 boolean exists = false ;
628632 while (!exists && rc == 0 ) {
629- if (mdb_cmp (writeTxn , dbi , keyData , maxKey ) > 0 ) {
633+ if (mdb_cmp (txn , dbi , keyData , maxKey ) > 0 ) {
630634 // id was not found
631635 break ;
632636 } else if (!matcher .matches (keyData .mv_data ())) {
@@ -649,7 +653,8 @@ protected void filterUsedIds(Collection<Long> ids) throws IOException {
649653 }
650654 }
651655 }
652- }
656+ return null ;
657+ });
653658 }
654659
655660 protected double cardinality (long subj , long pred , long obj , long context ) throws IOException {
@@ -842,6 +847,7 @@ private boolean requiresResize() {
842847
843848 public boolean storeTriple (long subj , long pred , long obj , long context , boolean explicit ) throws IOException {
844849 TripleIndex mainIndex = indexes .get (0 );
850+ boolean stAdded ;
845851 try (MemoryStack stack = MemoryStack .stackPush ()) {
846852 MDBVal keyVal = MDBVal .malloc (stack );
847853 // use calloc to get an empty data value
@@ -851,33 +857,34 @@ public boolean storeTriple(long subj, long pred, long obj, long context, boolean
851857 keyBuf .flip ();
852858 keyVal .mv_data (keyBuf );
853859
854- boolean foundExplicit = mdb_get (writeTxn , mainIndex .getDB (true ), keyVal , dataVal ) == 0 ;
855- boolean foundImplicit = !foundExplicit && mdb_get (writeTxn , mainIndex .getDB (false ), keyVal , dataVal ) == 0 ;
856-
857- boolean stAdded = !(foundExplicit || foundImplicit );
858- if (stAdded || explicit && foundImplicit ) {
859- if (recordCache == null ) {
860- if (requiresResize ()) {
861- // map is full, resize required
862- recordCache = new TxnRecordCache (dir );
863- logger .debug ("resize of map size {} required while adding - initialize record cache" , mapSize );
864- }
860+ if (recordCache == null ) {
861+ if (requiresResize ()) {
862+ // map is full, resize required
863+ recordCache = new TxnRecordCache (dir );
864+ logger .debug ("resize of map size {} required while adding - initialize record cache" , mapSize );
865865 }
866- if (recordCache != null ) {
867- long quad [] = new long [] { subj , pred , obj , context };
868- if (explicit && foundImplicit ) {
869- // remove implicit statement
870- recordCache .removeRecord (quad , false );
871- }
872- // put record in cache and return immediately
873- return recordCache .storeRecord (quad , explicit );
866+ }
867+ if (recordCache != null ) {
868+ long quad [] = new long [] { subj , pred , obj , context };
869+ if (explicit ) {
870+ // remove implicit statement
871+ recordCache .removeRecord (quad , false );
874872 }
873+ // put record in cache and return immediately
874+ return recordCache .storeRecord (quad , explicit );
875+ }
875876
876- if (explicit && foundImplicit ) {
877- E (mdb_del (writeTxn , mainIndex .getDB (false ), keyVal , dataVal ));
878- }
879- E (mdb_put (writeTxn , mainIndex .getDB (explicit ), keyVal , dataVal , 0 ));
877+ int rc = mdb_put (writeTxn , mainIndex .getDB (explicit ), keyVal , dataVal , MDB_NOOVERWRITE );
878+ if (rc != MDB_SUCCESS && rc != MDB_KEYEXIST ) {
879+ throw new IOException (mdb_strerror (rc ));
880+ }
881+ stAdded = rc == MDB_SUCCESS ;
882+ boolean foundImplicit = false ;
883+ if (explicit && stAdded ) {
884+ foundImplicit = E (mdb_del (writeTxn , mainIndex .getDB (false ), keyVal , dataVal )) == MDB_SUCCESS ;
885+ }
880886
887+ if (stAdded ) {
881888 for (int i = 1 ; i < indexes .size (); i ++) {
882889 TripleIndex index = indexes .get (i );
883890 keyBuf .clear ();
@@ -887,7 +894,7 @@ public boolean storeTriple(long subj, long pred, long obj, long context, boolean
887894 // update buffer positions in MDBVal
888895 keyVal .mv_data (keyBuf );
889896
890- if (explicit && foundImplicit ) {
897+ if (foundImplicit ) {
891898 E (mdb_del (writeTxn , mainIndex .getDB (false ), keyVal , dataVal ));
892899 }
893900 E (mdb_put (writeTxn , index .getDB (explicit ), keyVal , dataVal , 0 ));
@@ -897,9 +904,9 @@ public boolean storeTriple(long subj, long pred, long obj, long context, boolean
897904 incrementContext (stack , context );
898905 }
899906 }
900-
901- return stAdded ;
902907 }
908+
909+ return stAdded ;
903910 }
904911
905912 private void incrementContext (MemoryStack stack , long context ) throws IOException {
@@ -991,6 +998,7 @@ public void removeTriples(RecordIterator it, boolean explicit, Consumer<long[]>
991998 }
992999 if (recordCache != null ) {
9931000 recordCache .removeRecord (quad , explicit );
1001+ handler .accept (quad );
9941002 continue ;
9951003 }
9961004
@@ -1005,6 +1013,7 @@ public void removeTriples(RecordIterator it, boolean explicit, Consumer<long[]>
10051013 }
10061014
10071015 decrementContext (stack , quad [CONTEXT_IDX ]);
1016+ handler .accept (quad );
10081017 }
10091018 } finally {
10101019 it .close ();
0 commit comments