-
Notifications
You must be signed in to change notification settings - Fork 47
/
Neo4jModule.java
executable file
·182 lines (156 loc) · 6.61 KB
/
Neo4jModule.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/**
* Copyright (C) 2014 The SciGraph authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.scigraph.neo4j;
import static com.google.common.collect.Collections2.transform;
import static com.google.common.collect.Sets.newHashSet;
import static java.lang.String.format;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import javax.inject.Singleton;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.factory.GraphDatabaseBuilder;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.graphdb.index.AutoIndexer;
import org.neo4j.graphdb.index.IndexManager;
import org.neo4j.graphdb.schema.IndexDefinition;
import org.neo4j.graphdb.schema.Schema;
import org.neo4j.helpers.collection.MapUtil;
import org.neo4j.kernel.configuration.Settings;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import io.scigraph.frames.CommonProperties;
import io.scigraph.lucene.LuceneUtils;
import io.scigraph.lucene.VocabularyIndexAnalyzer;
import io.scigraph.neo4j.bindings.IndicatesCurieMapping;
import io.scigraph.neo4j.bindings.IndicatesNeo4jGraphLocation;
import io.scigraph.vocabulary.Vocabulary;
import io.scigraph.vocabulary.VocabularyNeo4jImpl;
import org.prefixcommons.CurieUtil;
public class Neo4jModule extends AbstractModule {
private final Neo4jConfiguration configuration;
private boolean readOnly = false;
public Neo4jModule(Neo4jConfiguration configuration) {
this.configuration = configuration;
}
public Neo4jModule(Neo4jConfiguration configuration, boolean readOnly) {
this.configuration = configuration;
this.readOnly = readOnly;
}
@Override
protected void configure() {
bind(String.class).annotatedWith(IndicatesNeo4jGraphLocation.class)
.toInstance(configuration.getLocation());
bind(CurieUtil.class).toInstance(new CurieUtil(configuration.getCuries()));
bind(new TypeLiteral<Map<String, String>>() {}).annotatedWith(IndicatesCurieMapping.class)
.toInstance(configuration.getCuries());
bind(Vocabulary.class).to(VocabularyNeo4jImpl.class).in(Singleton.class);
bind(new TypeLiteral<ConcurrentMap<String, Long>>() {}).to(IdMap.class).in(Singleton.class);
}
private static final Map<String, String> INDEX_CONFIG = MapUtil.stringMap(IndexManager.PROVIDER,
"lucene", "analyzer", VocabularyIndexAnalyzer.class.getName());
private static void setupIndex(AutoIndexer<?> index, Collection<String> properties) {
for (String property : properties) {
index.startAutoIndexingProperty(property);
}
index.setEnabled(true);
}
public static void setupAutoIndexing(GraphDatabaseService graphDb, Neo4jConfiguration config) {
try (Transaction tx = graphDb.beginTx()) {
graphDb.index().forNodes("node_auto_index", INDEX_CONFIG);
Set<String> indexProperties = newHashSet(CommonProperties.IRI);
indexProperties.addAll(config.getIndexedNodeProperties());
indexProperties
.addAll(transform(config.getExactNodeProperties(), new Function<String, String>() {
@Override
public String apply(String index) {
return index + LuceneUtils.EXACT_SUFFIX;
}
}));
setupIndex(graphDb.index().getNodeAutoIndexer(), indexProperties);
tx.success();
}
}
public static void setupSchemaIndexes(GraphDatabaseService graphDb, Neo4jConfiguration config) {
Map<String, Set<String>> schemaIndexes = config.getSchemaIndexes();
for (Map.Entry<String, Set<String>> entry : schemaIndexes.entrySet()) {
Label label = Label.label(entry.getKey());
for (String property : entry.getValue()) {
try (Transaction tx = graphDb.beginTx()) {
Schema schema = graphDb.schema();
IndexDefinition indexDefinition = schema.indexFor(label).on(property).create();
tx.success();
tx.close();
Transaction tx2 = graphDb.beginTx();
schema.awaitIndexOnline(indexDefinition, 2, TimeUnit.MINUTES);
tx2.success();
tx2.close();
}
}
}
}
@Provides
@Singleton
DB getMaker() {
File dbLocation = new File(configuration.getLocation(), "SciGraphIdMap");
return DBMaker.newFileDB(dbLocation).closeOnJvmShutdown().transactionDisable().mmapFileEnable()
.make();
}
@Provides
@Singleton
GraphDatabaseService getGraphDatabaseService() throws IOException {
try {
GraphDatabaseBuilder graphDatabaseBuilder = new GraphDatabaseFactory()
.newEmbeddedDatabaseBuilder(new File(configuration.getLocation()))
.setConfig(configuration.getNeo4jConfig());
if (readOnly) {
graphDatabaseBuilder.setConfig(GraphDatabaseSettings.read_only, Settings.TRUE);
}
// #198 - do not keep transaction logs
graphDatabaseBuilder.setConfig(GraphDatabaseSettings.keep_logical_logs, Settings.FALSE);
final GraphDatabaseService graphDb = graphDatabaseBuilder.newGraphDatabase();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
graphDb.shutdown();
}
});
if (!readOnly) { // No need of auto-indexing in read-only mode
setupAutoIndexing(graphDb, configuration);
}
setupSchemaIndexes(graphDb, configuration);
return graphDb;
} catch (Exception e) {
if (Throwables.getRootCause(e).getMessage().contains("lock file")) {
throw new IOException(format("The graph at \"%s\" is locked by another process",
configuration.getLocation()));
}
throw e;
}
}
}