1616import static org .eclipse .rdf4j .sail .lmdb .LmdbUtil .transaction ;
1717import static org .eclipse .rdf4j .sail .lmdb .Varint .readListUnsigned ;
1818import static org .eclipse .rdf4j .sail .lmdb .Varint .writeListUnsigned ;
19+ import static org .eclipse .rdf4j .sail .lmdb .Varint .writeUnsigned ;
1920import static org .lwjgl .system .MemoryStack .stackPush ;
2021import static org .lwjgl .system .MemoryUtil .NULL ;
2122import static org .lwjgl .util .lmdb .LMDB .MDB_CREATE ;
2223import static org .lwjgl .util .lmdb .LMDB .MDB_FIRST ;
24+ import static org .lwjgl .util .lmdb .LMDB .MDB_KEYEXIST ;
2325import static org .lwjgl .util .lmdb .LMDB .MDB_LAST ;
2426import static org .lwjgl .util .lmdb .LMDB .MDB_NEXT ;
2527import static org .lwjgl .util .lmdb .LMDB .MDB_NOMETASYNC ;
28+ import static org .lwjgl .util .lmdb .LMDB .MDB_NOOVERWRITE ;
2629import static org .lwjgl .util .lmdb .LMDB .MDB_NOSYNC ;
2730import static org .lwjgl .util .lmdb .LMDB .MDB_NOTFOUND ;
2831import static org .lwjgl .util .lmdb .LMDB .MDB_NOTLS ;
2932import static org .lwjgl .util .lmdb .LMDB .MDB_PREV ;
3033import static org .lwjgl .util .lmdb .LMDB .MDB_SET_RANGE ;
34+ import static org .lwjgl .util .lmdb .LMDB .MDB_SUCCESS ;
3135import static org .lwjgl .util .lmdb .LMDB .mdb_cmp ;
3236import static org .lwjgl .util .lmdb .LMDB .mdb_cursor_close ;
3337import static org .lwjgl .util .lmdb .LMDB .mdb_cursor_get ;
4751import static org .lwjgl .util .lmdb .LMDB .mdb_put ;
4852import static org .lwjgl .util .lmdb .LMDB .mdb_set_compare ;
4953import static org .lwjgl .util .lmdb .LMDB .mdb_stat ;
54+ import static org .lwjgl .util .lmdb .LMDB .mdb_strerror ;
5055import static org .lwjgl .util .lmdb .LMDB .mdb_txn_abort ;
5156import static org .lwjgl .util .lmdb .LMDB .mdb_txn_begin ;
5257import static org .lwjgl .util .lmdb .LMDB .mdb_txn_commit ;
9297import org .slf4j .LoggerFactory ;
9398
9499/**
95- * LMDB-based indexed storage and retrieval of RDF statements. TripleStore stores statements in the form of four integer
100+ * LMDB-based indexed storage and retrieval of RDF statements. TripleStore stores statements in the form of four long
96101 * IDs. Each ID represent an RDF value that is stored in a {@link ValueStore}. The four IDs refer to the statement's
97102 * subject, predicate, object and context. The ID <tt>0</tt> is used to represent the "null" context and doesn't map to
98103 * an actual RDF value.
@@ -539,7 +544,7 @@ protected void bucketStart(double fraction, long[] lowerValues, long[] upperValu
539544 * @throws IOException
540545 */
541546 protected void filterUsedIds (Collection <Long > ids ) throws IOException {
542- try ( MemoryStack stack = stackPush ()) {
547+ readTransaction ( env , ( stack , txn ) -> {
543548 MDBVal maxKey = MDBVal .malloc (stack );
544549 ByteBuffer maxKeyBuf = stack .malloc (TripleStore .MAX_KEY_LENGTH );
545550 MDBVal keyData = MDBVal .malloc (stack );
@@ -559,7 +564,7 @@ protected void filterUsedIds(Collection<Long> ids) throws IOException {
559564 keyBuf .clear ();
560565 Varint .writeUnsigned (keyBuf , id );
561566 keyData .mv_data (keyBuf .flip ());
562- if (mdb_get (writeTxn , contextsDbi , keyData , valueData ) == 0 ) {
567+ if (mdb_get (txn , contextsDbi , keyData , valueData ) == 0 ) {
563568 it .remove ();
564569 }
565570 }
@@ -580,7 +585,7 @@ protected void filterUsedIds(Collection<Long> ids) throws IOException {
580585
581586 long cursor = 0 ;
582587 try {
583- E (mdb_cursor_open (writeTxn , dbi , pp ));
588+ E (mdb_cursor_open (txn , dbi , pp ));
584589 cursor = pp .get (0 );
585590
586591 if (fullScan ) {
@@ -626,7 +631,7 @@ protected void filterUsedIds(Collection<Long> ids) throws IOException {
626631 int rc = mdb_cursor_get (cursor , keyData , valueData , MDB_SET_RANGE );
627632 boolean exists = false ;
628633 while (!exists && rc == 0 ) {
629- if (mdb_cmp (writeTxn , dbi , keyData , maxKey ) > 0 ) {
634+ if (mdb_cmp (txn , dbi , keyData , maxKey ) > 0 ) {
630635 // id was not found
631636 break ;
632637 } else if (!matcher .matches (keyData .mv_data ())) {
@@ -649,7 +654,8 @@ protected void filterUsedIds(Collection<Long> ids) throws IOException {
649654 }
650655 }
651656 }
652- }
657+ return null ;
658+ });
653659 }
654660
655661 protected double cardinality (long subj , long pred , long obj , long context ) throws IOException {
@@ -842,6 +848,7 @@ private boolean requiresResize() {
842848
843849 public boolean storeTriple (long subj , long pred , long obj , long context , boolean explicit ) throws IOException {
844850 TripleIndex mainIndex = indexes .get (0 );
851+ boolean stAdded ;
845852 try (MemoryStack stack = MemoryStack .stackPush ()) {
846853 MDBVal keyVal = MDBVal .malloc (stack );
847854 // use calloc to get an empty data value
@@ -851,33 +858,34 @@ public boolean storeTriple(long subj, long pred, long obj, long context, boolean
851858 keyBuf .flip ();
852859 keyVal .mv_data (keyBuf );
853860
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- }
861+ if (recordCache == null ) {
862+ if (requiresResize ()) {
863+ // map is full, resize required
864+ recordCache = new TxnRecordCache (dir );
865+ logger .debug ("resize of map size {} required while adding - initialize record cache" , mapSize );
865866 }
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 );
867+ }
868+ if (recordCache != null ) {
869+ long quad [] = new long [] { subj , pred , obj , context };
870+ if (explicit ) {
871+ // remove implicit statement
872+ recordCache .removeRecord (quad , false );
874873 }
874+ // put record in cache and return immediately
875+ return recordCache .storeRecord (quad , explicit );
876+ }
875877
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 ));
878+ int rc = mdb_put (writeTxn , mainIndex .getDB (explicit ), keyVal , dataVal , MDB_NOOVERWRITE );
879+ if (rc != MDB_SUCCESS && rc != MDB_KEYEXIST ) {
880+ throw new IOException (mdb_strerror (rc ));
881+ }
882+ stAdded = rc == MDB_SUCCESS ;
883+ boolean foundImplicit = false ;
884+ if (explicit && stAdded ) {
885+ foundImplicit = E (mdb_del (writeTxn , mainIndex .getDB (false ), keyVal , dataVal )) == MDB_SUCCESS ;
886+ }
880887
888+ if (stAdded ) {
881889 for (int i = 1 ; i < indexes .size (); i ++) {
882890 TripleIndex index = indexes .get (i );
883891 keyBuf .clear ();
@@ -887,7 +895,7 @@ public boolean storeTriple(long subj, long pred, long obj, long context, boolean
887895 // update buffer positions in MDBVal
888896 keyVal .mv_data (keyBuf );
889897
890- if (explicit && foundImplicit ) {
898+ if (foundImplicit ) {
891899 E (mdb_del (writeTxn , mainIndex .getDB (false ), keyVal , dataVal ));
892900 }
893901 E (mdb_put (writeTxn , index .getDB (explicit ), keyVal , dataVal , 0 ));
@@ -897,9 +905,9 @@ public boolean storeTriple(long subj, long pred, long obj, long context, boolean
897905 incrementContext (stack , context );
898906 }
899907 }
900-
901- return stAdded ;
902908 }
909+
910+ return stAdded ;
903911 }
904912
905913 private void incrementContext (MemoryStack stack , long context ) throws IOException {
@@ -991,6 +999,7 @@ public void removeTriples(RecordIterator it, boolean explicit, Consumer<long[]>
991999 }
9921000 if (recordCache != null ) {
9931001 recordCache .removeRecord (quad , explicit );
1002+ handler .accept (quad );
9941003 continue ;
9951004 }
9961005
@@ -1005,6 +1014,7 @@ public void removeTriples(RecordIterator it, boolean explicit, Consumer<long[]>
10051014 }
10061015
10071016 decrementContext (stack , quad [CONTEXT_IDX ]);
1017+ handler .accept (quad );
10081018 }
10091019 } finally {
10101020 it .close ();
@@ -1284,24 +1294,22 @@ GroupMatcher createMatcher(long subj, long pred, long obj, long context) {
12841294 }
12851295
12861296 void toKey (ByteBuffer bb , long subj , long pred , long obj , long context ) {
1287- long [] values = new long [4 ];
12881297 for (int i = 0 ; i < fieldSeq .length ; i ++) {
12891298 switch (fieldSeq [i ]) {
12901299 case 's' :
1291- values [ i ] = subj ;
1300+ writeUnsigned ( bb , subj ) ;
12921301 break ;
12931302 case 'p' :
1294- values [ i ] = pred ;
1303+ writeUnsigned ( bb , pred ) ;
12951304 break ;
12961305 case 'o' :
1297- values [ i ] = obj ;
1306+ writeUnsigned ( bb , obj ) ;
12981307 break ;
12991308 case 'c' :
1300- values [ i ] = context ;
1309+ writeUnsigned ( bb , context ) ;
13011310 break ;
13021311 }
13031312 }
1304- writeListUnsigned (bb , values );
13051313 }
13061314
13071315 void keyToQuad (ByteBuffer key , long [] quad ) {
0 commit comments