lance-sp opened a new issue, #3877:
URL: https://github.com/apache/jena/issues/3877

   ### Version
   
   5.6.0 
   
   ### What happened?
   
   - Module: `jena-dboe-base` 
(`org.apache.jena.dboe.base.file.BinaryDataFileRandomAccess`).
   `BinaryDataFileRandomAccess.truncate(length)` in `jena-dboe-base` calls 
`RandomAccessFile.setLength(length)` but does not reset the class's own 
`writePosition` field. A later `switchToWriteMode()` (triggered by any 
read→write transition, e.g. a write after a read inside the same 
`BinaryDataFileRandomAccess` lifecycle) seeks the underlying `RandomAccessFile` 
to the stale `writePosition` past the just-truncated EOF. The next 
`file.write(...)` extends the file at that position; the filesystem zero-fills 
the range between the truncated length and the stale seek, leaving a contiguous 
zero gap inside the file.
   
   What I expected: after `truncate(length)` followed by `read(...)` then 
`write(buf)`, the write should land at offset `length`, and the file should 
contain the written bytes only (no zero padding).
   
   What actually happens: the write lands at the stale `writePosition` (the 
file length *before* `truncate`), and the filesystem zero-fills the intervening 
bytes.
   
   Minimal reproducer, no framework:
   
       var file = new BinaryDataFileRandomAccess("/tmp/bdf-bug.bin");
       file.open();
       byte[] ab = new byte[1024]; java.util.Arrays.fill(ab, (byte) 0xAB);
       for (int i = 0; i < 300; i++) file.write(ab, 0, 1024); // 300 KB of 0xAB
       file.truncate(100 * 1024);                             // file truncated 
to 100 KB
       file.read(0, new byte[16], 0, 16);                     // flips internal 
readMode
       byte[] cd = new byte[100]; java.util.Arrays.fill(cd, (byte) 0xCD);
       long pos = file.write(cd, 0, 100);
       file.sync();
       file.close();
       // Expect: pos == 102400, file is 102500 bytes, no zero bytes.
       // Actual: pos == 307200, file is 307300 bytes, 204800 bytes of 0x00 
between
       //         the 100 KB of 0xAB and the 100 bytes of 0xCD.
   
   Under TDB2 this surfaces as zero regions inside `nodes-data.obj` after an 
aborted write transaction (`TransBinaryDataFile._abort()` calls `truncate()`) 
followed by a transaction whose first access to that file is a read (typical 
for SPARQL UPDATE — node lookups before allocation). `NodeTable` reads that 
later resolve a NodeId into a zero region throw `TDBException: 
NodeTableTRDF/Read → TProtocolException: Unrecognized type 0`. The store is 
persistently corrupt until the affected range is overwritten; a Fuseki restart 
does not recover it.
   
   I have a one-line fix and a JUnit 5 regression test ready as a PR against 
`jena-db/jena-dboe-base` — will open it once this issue has a number to 
reference.
   
   ### Relevant output and stacktrace
   
   ```shell
   # Output of the minimal reproducer above, on Jena 5.6.0:
   
   after 300 KB writes:   writePosition=307200, file on disk=307200 bytes
   after truncate(100K):  writePosition=307200 (stale), file on disk=102400 
bytes
   after read of 16 B:    readMode=true
   after write of 100 B:  returned pos=307200 (should be 102400), file on 
disk=307300 bytes
   byte-content audit:    102400 × 0xAB, 204800 × 0x00, 100 × 0xCD
   
   
   # The TDB2-level exception this produces when a later NodeTable read 
resolves a
   # NodeId whose offset falls inside one of the zero regions in nodes-data.obj:
   
   org.apache.jena.tdb2.TDBException: NodeTableTRDF/Read
       at 
org.apache.jena.tdb2.store.nodetable.NodeTableTRDF.readNodeFromTable(NodeTableTRDF.java:87)
       at 
org.apache.jena.tdb2.store.nodetable.NodeTableNative._retrieveNodeByNodeId(NodeTableNative.java:102)
       at 
org.apache.jena.tdb2.store.nodetable.NodeTableNative.getNodeForNodeId(NodeTableNative.java:52)
       at 
org.apache.jena.tdb2.store.nodetable.NodeTableCache._retrieveNodeByNodeId(NodeTableCache.java:212)
       at 
org.apache.jena.tdb2.store.nodetable.NodeTableCache.getNodeForNodeId(NodeTableCache.java:137)
       at 
org.apache.jena.tdb2.store.nodetable.NodeTableWrapper.getNodeForNodeId(NodeTableWrapper.java:52)
       ...
   Caused by: org.apache.thrift.protocol.TProtocolException: Unrecognized type 0
       at org.apache.thrift.protocol.TCompactProtocol.getTType(...)
       ...
   ```
   
   ### Are you interested in making a pull request?
   
   Yes


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to