22
33import com .hp .hpl .jena .query .Dataset ;
44import com .hp .hpl .jena .tdb .TDBFactory ;
5+ import org .apache .commons .io .file .PathUtils ;
56import ubic .basecode .ontology .model .OntologyModel ;
67
78import javax .annotation .Nullable ;
9+ import java .io .IOException ;
810import java .io .InputStream ;
11+ import java .nio .file .Files ;
912import java .nio .file .Path ;
13+ import java .util .Set ;
14+ import java .util .stream .Collectors ;
15+ import java .util .stream .Stream ;
1016
1117/**
1218 * An implementation based on Jena TDB.
@@ -16,22 +22,48 @@ public class TdbOntologyService extends AbstractOntologyService {
1622
1723 private final Path tdbDir ;
1824 private final String modelName ;
25+ private final boolean readOnly ;
1926
2027 @ Nullable
2128 private Dataset dataset ;
2229
23- public TdbOntologyService ( String ontologyName , Path tdbDir , @ Nullable String modelName , boolean ontologyEnabled , @ Nullable String cacheName ) {
30+ /**
31+ * Temporary d
32+ */
33+ private Path tempDir ;
34+
35+ /**
36+ * @param readOnly open the TDB database in read-only mode, allowing multiple JVMs to share a common TDB. For this
37+ * to work safely, all the TDB files must not be writable. Additionally, a temporary directory with
38+ * symbolic links will be created since Jena will still be using a lock file.
39+ */
40+ public TdbOntologyService ( String ontologyName , Path tdbDir , @ Nullable String modelName , boolean ontologyEnabled , @ Nullable String cacheName , boolean readOnly ) {
2441 super ( ontologyName , tdbDir .toUri ().toString (), ontologyEnabled , cacheName );
2542 this .tdbDir = tdbDir ;
2643 this .modelName = modelName ;
44+ this .readOnly = readOnly ;
2745 }
2846
2947 @ Override
30- protected OntologyModel loadModel ( boolean processImports , LanguageLevel languageLevel , InferenceMode inferenceMode ) {
48+ protected OntologyModel loadModel ( boolean processImports , LanguageLevel languageLevel , InferenceMode inferenceMode ) throws IOException {
3149 if ( dataset == null ) {
32- dataset = TDBFactory .createDataset ( tdbDir .toString () );
50+ if ( readOnly ) {
51+ Set <Path > filesToLink ;
52+ try ( Stream <Path > z = Files .list ( tdbDir ) ) {
53+ filesToLink = z .collect ( Collectors .toSet () );
54+ }
55+ tempDir = Files .createTempDirectory ( getOntologyName () + ".tdb" );
56+ for ( Path p : filesToLink ) {
57+ Files .createSymbolicLink ( tempDir .resolve ( p .getFileName () ), p );
58+ }
59+ log .info ( "Reading read-only TDB model from {}." , tempDir );
60+ dataset = TDBFactory .createDataset ( tempDir .toString () );
61+
62+ } else {
63+ dataset = TDBFactory .createDataset ( tdbDir .toString () );
64+ }
3365 }
34- return new OntologyModelImpl ( OntologyLoader .createTdbModel ( dataset , modelName , processImports , getSpec ( languageLevel , inferenceMode ) ) );
66+ return new OntologyModelImpl ( OntologyLoader .createTdbModel ( dataset , modelName , processImports , getSpec ( languageLevel , inferenceMode ), readOnly ) );
3567 }
3668
3769 @ Override
@@ -47,6 +79,9 @@ public void close() throws Exception {
4779 if ( dataset != null ) {
4880 TDBFactory .release ( dataset );
4981 }
82+ if ( tempDir != null ) {
83+ PathUtils .delete ( tempDir );
84+ }
5085 }
5186 }
5287}
0 commit comments