This project has retired. For details please refer to its
Attic page.
OakRepositoryFactory xref
1 package org.apache.archiva.metadata.repository.jcr;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import com.google.common.collect.ImmutableList;
23 import com.google.common.collect.ImmutableSet;
24 import org.apache.commons.lang3.time.StopWatch;
25 import org.apache.jackrabbit.oak.api.Type;
26 import org.apache.jackrabbit.oak.jcr.Jcr;
27 import org.apache.jackrabbit.oak.plugins.index.AsyncIndexInfoService;
28 import org.apache.jackrabbit.oak.plugins.index.AsyncIndexInfoServiceImpl;
29 import org.apache.jackrabbit.oak.plugins.index.IndexInfoProvider;
30 import org.apache.jackrabbit.oak.plugins.index.IndexPathService;
31 import org.apache.jackrabbit.oak.plugins.index.IndexPathServiceImpl;
32 import org.apache.jackrabbit.oak.plugins.index.IndexUtils;
33 import org.apache.jackrabbit.oak.plugins.index.aggregate.SimpleNodeAggregator;
34 import org.apache.jackrabbit.oak.plugins.index.lucene.IndexAugmentorFactory;
35 import org.apache.jackrabbit.oak.plugins.index.lucene.IndexCopier;
36 import org.apache.jackrabbit.oak.plugins.index.lucene.IndexTracker;
37 import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexEditorProvider;
38 import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexInfoProvider;
39 import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexProvider;
40 import org.apache.jackrabbit.oak.plugins.index.lucene.directory.ActiveDeletedBlobCollectorFactory;
41 import org.apache.jackrabbit.oak.plugins.index.lucene.directory.BufferedOakDirectory;
42 import org.apache.jackrabbit.oak.plugins.index.lucene.directory.LuceneIndexImporter;
43 import org.apache.jackrabbit.oak.plugins.index.lucene.hybrid.DocumentQueue;
44 import org.apache.jackrabbit.oak.plugins.index.lucene.hybrid.ExternalObserverBuilder;
45 import org.apache.jackrabbit.oak.plugins.index.lucene.hybrid.LocalIndexObserver;
46 import org.apache.jackrabbit.oak.plugins.index.lucene.hybrid.NRTIndexFactory;
47 import org.apache.jackrabbit.oak.plugins.index.lucene.property.PropertyIndexCleaner;
48 import org.apache.jackrabbit.oak.plugins.index.lucene.reader.DefaultIndexReaderFactory;
49 import org.apache.jackrabbit.oak.plugins.index.lucene.score.ScorerProviderFactory;
50 import org.apache.jackrabbit.oak.plugins.index.lucene.score.impl.ScorerProviderFactoryImpl;
51 import org.apache.jackrabbit.oak.plugins.index.lucene.util.IndexDefinitionBuilder;
52 import org.apache.jackrabbit.oak.plugins.index.search.ExtractedTextCache;
53 import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants;
54 import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
55 import org.apache.jackrabbit.oak.plugins.name.Namespaces;
56 import org.apache.jackrabbit.oak.segment.SegmentNodeStoreBuilders;
57 import org.apache.jackrabbit.oak.segment.file.FileStore;
58 import org.apache.jackrabbit.oak.segment.file.FileStoreBuilder;
59 import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
60 import org.apache.jackrabbit.oak.spi.blob.FileBlobStore;
61 import org.apache.jackrabbit.oak.spi.blob.GarbageCollectableBlobStore;
62 import org.apache.jackrabbit.oak.spi.commit.BackgroundObserver;
63 import org.apache.jackrabbit.oak.spi.commit.Observer;
64 import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
65 import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
66 import org.apache.jackrabbit.oak.spi.mount.Mounts;
67 import org.apache.jackrabbit.oak.spi.namespace.NamespaceConstants;
68 import org.apache.jackrabbit.oak.spi.query.QueryIndex;
69 import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
70 import org.apache.jackrabbit.oak.spi.state.Clusterable;
71 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
72 import org.apache.jackrabbit.oak.spi.state.NodeStore;
73 import org.apache.jackrabbit.oak.stats.StatisticsProvider;
74 import org.jetbrains.annotations.NotNull;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
77
78 import javax.jcr.Repository;
79 import java.io.Closeable;
80 import java.io.IOException;
81 import java.nio.file.Files;
82 import java.nio.file.Path;
83 import java.nio.file.Paths;
84 import java.util.concurrent.ExecutorService;
85 import java.util.concurrent.LinkedBlockingQueue;
86 import java.util.concurrent.ThreadFactory;
87 import java.util.concurrent.ThreadPoolExecutor;
88 import java.util.concurrent.TimeUnit;
89 import java.util.concurrent.atomic.AtomicInteger;
90
91 import static com.google.common.base.Preconditions.checkNotNull;
92 import static org.apache.archiva.metadata.repository.jcr.JcrConstants.*;
93 import static org.apache.archiva.metadata.repository.jcr.OakRepositoryFactory.StoreType.IN_MEMORY_TYPE;
94 import static org.apache.archiva.metadata.repository.jcr.OakRepositoryFactory.StoreType.SEGMENT_FILE_TYPE;
95 import static org.apache.commons.io.FileUtils.ONE_MB;
96 import static org.apache.jackrabbit.JcrConstants.*;
97 import static org.apache.jackrabbit.oak.api.Type.NAME;
98
99
100
101
102
103
104
105 public class OakRepositoryFactory
106 {
107
108 private Logger log = LoggerFactory.getLogger( OakRepositoryFactory.class );
109
110 private FileStore fileStore;
111
112 private NodeStore nodeStore;
113
114 private IndexTracker tracker;
115
116 private DocumentQueue documentQueue;
117
118 private NRTIndexFactory nrtIndexFactory;
119
120 private IndexCopier indexCopier;
121
122 private ExecutorService executorService;
123 private ExtractedTextCache extractedTextCache;
124
125 private boolean hybridIndex = true;
126 private boolean prefetchEnabled = true;
127 private boolean enableAsyncIndexOpen = true;
128 int queueSize = 10000;
129 int cleanerInterval = 10*60;
130 boolean enableCopyOnWrite = true;
131 boolean enableCopyOnRead = true;
132 int cacheSizeInMB = 20;
133 int cacheExpiryInSecs = 300;
134 int threadPoolSize = 5;
135
136 private StatisticsProvider statisticsProvider;
137
138 private MountInfoProvider mountInfoProvider = Mounts.defaultMountInfoProvider();
139
140 private AsyncIndexInfoService asyncIndexInfoService = null;
141
142 private LuceneIndexProvider indexProvider;
143
144 private ScorerProviderFactory scorerFactory = new ScorerProviderFactoryImpl( );
145 private IndexAugmentorFactory augmentorFactory = new IndexAugmentorFactory( );
146
147 private ActiveDeletedBlobCollectorFactory.ActiveDeletedBlobCollector activeDeletedBlobCollector = ActiveDeletedBlobCollectorFactory.NOOP;
148
149 private QueryIndex.NodeAggregator nodeAggregator = new SimpleNodeAggregator( );
150
151 private BackgroundObserver backgroundObserver;
152
153 private BackgroundObserver externalIndexObserver;
154
155 private GarbageCollectableBlobStore blobStore;
156
157 private PropertyIndexCleaner cleaner;
158
159 private IndexPathService indexPathService;
160
161 private LuceneIndexEditorProvider editorProvider;
162
163 private Path indexDir;
164
165 public enum StoreType
166 {
167 SEGMENT_FILE_TYPE,
168 IN_MEMORY_TYPE;
169 }
170
171 private StoreType storeType = SEGMENT_FILE_TYPE;
172
173 private Path repositoryPath = Paths.get( "repository" );
174
175 public OakRepositoryFactory() {
176 final OakRepositoryFactory repositoryFactory = this;
177 Runtime.getRuntime().addShutdownHook( new Thread( ( ) -> {
178 if (repositoryFactory!=null)
179 {
180 repositoryFactory.close( );
181 }
182 } ) );
183 }
184
185 private void initializeExtractedTextCache( StatisticsProvider statisticsProvider) {
186 boolean alwaysUsePreExtractedCache = false;
187
188 extractedTextCache = new ExtractedTextCache(
189 cacheSizeInMB * ONE_MB,
190 cacheExpiryInSecs,
191 alwaysUsePreExtractedCache,
192 indexDir.toFile(), statisticsProvider);
193 }
194
195 private IndexTracker createTracker() throws IOException {
196 IndexTracker tracker;
197 if (enableCopyOnRead){
198 initializeIndexCopier();
199 log.info("Enabling CopyOnRead support. Index files would be copied under {}", indexDir.toAbsolutePath());
200 if (hybridIndex) {
201 nrtIndexFactory = new NRTIndexFactory(indexCopier, statisticsProvider);
202 }
203 tracker = new IndexTracker(new DefaultIndexReaderFactory(mountInfoProvider, indexCopier), nrtIndexFactory);
204 } else {
205 tracker = new IndexTracker(new DefaultIndexReaderFactory(mountInfoProvider, null));
206 }
207
208 tracker.setAsyncIndexInfoService(asyncIndexInfoService);
209 tracker.refresh();
210 return tracker;
211 }
212
213 private void initializeIndexCopier() throws IOException {
214 if(indexCopier != null){
215 return;
216 }
217
218 if (prefetchEnabled){
219 log.info("Prefetching of index files enabled. Index would be opened after copying all new files locally");
220 }
221
222 indexCopier = new IndexCopier(getExecutorService(), indexDir.toFile(), prefetchEnabled);
223
224 }
225
226 ExecutorService getExecutorService(){
227 if (executorService == null){
228 executorService = createExecutor();
229 }
230 return executorService;
231 }
232
233 private ExecutorService createExecutor() {
234 ThreadPoolExecutor executor = new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 60L, TimeUnit.SECONDS,
235 new LinkedBlockingQueue<Runnable>(), new ThreadFactory() {
236 private final AtomicInteger counter = new AtomicInteger();
237 private final Thread.UncaughtExceptionHandler handler = new Thread.UncaughtExceptionHandler() {
238 @Override
239 public void uncaughtException(Thread t, Throwable e) {
240 log.warn("Error occurred in asynchronous processing ", e);
241 }
242 };
243 @Override
244 public Thread newThread(@NotNull Runnable r) {
245 Thread thread = new Thread(r, createName());
246 thread.setDaemon(true);
247 thread.setPriority(Thread.MIN_PRIORITY);
248 thread.setUncaughtExceptionHandler(handler);
249 return thread;
250 }
251
252 private String createName() {
253 return "oak-lucene-" + counter.getAndIncrement();
254 }
255 });
256 executor.setKeepAliveTime(1, TimeUnit.MINUTES);
257 executor.allowCoreThreadTimeOut(true);
258 return executor;
259 }
260
261 private void initialize(){
262 if(indexProvider == null){
263 return;
264 }
265
266 if(nodeAggregator != null){
267 log.debug("Using NodeAggregator {}", nodeAggregator.getClass());
268 }
269
270 indexProvider.setAggregator(nodeAggregator);
271 }
272
273 private void registerObserver() {
274 Observer observer = indexProvider;
275 if (enableAsyncIndexOpen) {
276 backgroundObserver = new BackgroundObserver(indexProvider, getExecutorService(), 5);
277 log.info("Registering the LuceneIndexProvider as a BackgroundObserver");
278 }
279 }
280
281 private void registerLocalIndexObserver(IndexTracker tracker) {
282 if (!hybridIndex){
283 log.info("Hybrid indexing feature disabled");
284 return;
285 }
286 documentQueue = new DocumentQueue( queueSize, tracker, getExecutorService(), statisticsProvider);
287 LocalIndexObserver localIndexObserver = new LocalIndexObserver(documentQueue, statisticsProvider);
288
289 int observerQueueSize = 1000;
290 int builderMaxSize = 5000;
291
292
293 ExternalObserverBuilder builder = new ExternalObserverBuilder(documentQueue, tracker, statisticsProvider,
294 getExecutorService(), observerQueueSize);
295 log.info("Configured JournalPropertyBuilder with max size {} and backed by BackgroundObserver " +
296 "with queue size {}", builderMaxSize, observerQueueSize);
297
298 Observer observer = builder.build();
299 externalIndexObserver = builder.getBackgroundObserver();
300 log.info("Hybrid indexing enabled for configured indexes with queue size of {}", queueSize );
301 }
302
303 private IndexInfoProvider registerIndexInfoProvider() {
304 return new LuceneIndexInfoProvider(nodeStore, asyncIndexInfoService, getIndexCheckDir().toFile());
305 }
306
307 private Path getIndexCheckDir() {
308 return checkNotNull(indexDir).resolve("indexCheckDir");
309 }
310
311 private LuceneIndexImporter registerIndexImporterProvider() {
312 return new LuceneIndexImporter(blobStore);
313 }
314
315 private void registerPropertyIndexCleaner( ) {
316
317 if (cleanerInterval <= 0) {
318 log.info("Property index cleaner would not be registered");
319 return;
320 }
321
322 cleaner = new PropertyIndexCleaner(nodeStore, indexPathService, asyncIndexInfoService, statisticsProvider);
323
324
325 if (nodeStore instanceof Clusterable ) {
326 cleaner.setRecursiveDelete(true);
327 log.info("PropertyIndexCleaner configured to perform recursive delete");
328 }
329 log.info("Property index cleaner configured to run every [{}] seconds", cleanerInterval);
330 }
331
332 private void registerIndexEditor( IndexTracker tracker) throws IOException {
333 boolean enableCopyOnWrite = true;
334 if (enableCopyOnWrite){
335 initializeIndexCopier();
336 editorProvider = new LuceneIndexEditorProvider(indexCopier, tracker, extractedTextCache,
337 augmentorFactory, mountInfoProvider, activeDeletedBlobCollector, null, statisticsProvider);
338 log.info("Enabling CopyOnWrite support. Index files would be copied under {}", indexDir.toAbsolutePath());
339 } else {
340 editorProvider = new LuceneIndexEditorProvider(null, tracker, extractedTextCache, augmentorFactory,
341 mountInfoProvider, activeDeletedBlobCollector, null, statisticsProvider);
342 }
343 editorProvider.setBlobStore(blobStore);
344
345 if (hybridIndex){
346 editorProvider.setIndexingQueue(checkNotNull(documentQueue));
347 }
348
349
350 }
351
352 public Repository createRepository()
353 throws IOException, InvalidFileStoreVersionException
354 {
355
356 indexDir = repositoryPath.resolve( ".index-lucene" );
357 if (!Files.exists( indexDir )) {
358 Files.createDirectories( indexDir );
359 }
360 blobStore = new FileBlobStore( indexDir.resolve( "blobs" ).toAbsolutePath().toString() );
361
362 statisticsProvider = StatisticsProvider.NOOP;
363
364 if ( SEGMENT_FILE_TYPE == storeType )
365 {
366 fileStore = FileStoreBuilder.fileStoreBuilder( repositoryPath.toFile() )
367 .withStatisticsProvider( statisticsProvider )
368 .build();
369 nodeStore = SegmentNodeStoreBuilders.builder( fileStore )
370 .withStatisticsProvider( statisticsProvider )
371 .build();
372 }
373 else if ( IN_MEMORY_TYPE == storeType )
374 {
375 nodeStore = new MemoryNodeStore( );
376 }
377 else
378 {
379 throw new IllegalArgumentException( "Store type " + storeType + " not recognized" );
380 }
381
382 asyncIndexInfoService = new AsyncIndexInfoServiceImpl( nodeStore );
383
384 indexPathService = new IndexPathServiceImpl( nodeStore, mountInfoProvider );
385
386 BufferedOakDirectory.setEnableWritingSingleBlobIndexFile( true );
387
388 initializeExtractedTextCache( statisticsProvider );
389
390 tracker = createTracker();
391
392 indexProvider = new LuceneIndexProvider(tracker, scorerFactory, augmentorFactory);
393
394 initialize();
395 registerObserver();
396 registerLocalIndexObserver(tracker);
397 registerIndexInfoProvider();
398 registerIndexImporterProvider();
399 registerPropertyIndexCleaner();
400
401 registerIndexEditor(tracker);
402
403
404
405 RepositoryInitializer repoInitializer = new RepositoryInitializer( )
406 {
407 private IndexDefinitionBuilder.PropertyRule initRegexAll( IndexDefinitionBuilder.IndexRule rule ) {
408 return rule
409 .indexNodeName( )
410 .property(JCR_LASTMODIFIED ).propertyIndex().type( "Date" ).ordered()
411 .property(JCR_PRIMARYTYPE).propertyIndex()
412 .property(JCR_MIXINTYPES).propertyIndex()
413 .property(JCR_PATH).propertyIndex().ordered()
414 .property( FulltextIndexConstants.REGEX_ALL_PROPS, true )
415 .propertyIndex().analyzed( ).nodeScopeIndex();
416 }
417
418 private IndexDefinitionBuilder.PropertyRule initBaseRule( IndexDefinitionBuilder.IndexRule rule ) {
419 return rule
420 .indexNodeName( )
421 .property(JCR_CREATED).propertyIndex().type("Date").ordered()
422 .property(JCR_LASTMODIFIED ).propertyIndex().type( "Date" ).ordered()
423 .property(JCR_PRIMARYTYPE).propertyIndex()
424 .property(JCR_MIXINTYPES).propertyIndex()
425 .property(JCR_PATH).propertyIndex().ordered()
426 .property( "id" ).propertyIndex().analyzed( );
427 }
428
429 @Override
430 public void initialize( NodeBuilder root )
431 {
432 NodeBuilder namespaces;
433 if ( !root.hasChildNode( NamespaceConstants.REP_NAMESPACES ) )
434 {
435 namespaces = Namespaces.createStandardMappings( root );
436 Namespaces.buildIndexNode( namespaces );
437 }
438 else
439 {
440 namespaces = root.getChildNode( NamespaceConstants.REP_NAMESPACES );
441 }
442 Namespaces.addCustomMapping( namespaces, "http://archiva.apache.org/jcr/", "archiva" );
443
444 log.info( "Creating index " );
445
446 NodeBuilder oakIdx = IndexUtils.getOrCreateOakIndex( root );
447 if (!oakIdx.hasChildNode( "repo-lucene" ))
448 {
449 NodeBuilder lucene = oakIdx.child( "repo-lucene" );
450 lucene.setProperty( JCR_PRIMARYTYPE, "oak:QueryIndexDefinition", NAME );
451
452 lucene.setProperty( "compatVersion", 2 );
453 lucene.setProperty( "type", "lucene" );
454
455
456
457 NodeBuilder rules = lucene.child( "indexRules" ).
458 setProperty( JCR_PRIMARYTYPE, NT_UNSTRUCTURED, NAME );
459 rules.setProperty( ":childOrder", ImmutableSet.of(
460 REPOSITORY_NODE_TYPE,
461 NAMESPACE_MIXIN_TYPE,
462 PROJECT_MIXIN_TYPE,
463 PROJECT_VERSION_NODE_TYPE,
464 ARTIFACT_NODE_TYPE,
465 FACET_NODE_TYPE
466 ), Type.STRINGS );
467 IndexDefinitionBuilder idxBuilder = new IndexDefinitionBuilder( lucene );
468 idxBuilder.async( "async", "nrt", "sync" ).includedPaths( "/repositories" ).evaluatePathRestrictions();
469
470 initBaseRule(idxBuilder.indexRule( REPOSITORY_NODE_TYPE ));
471 initBaseRule(idxBuilder.indexRule(NAMESPACE_MIXIN_TYPE))
472 .property( "namespace" ).propertyIndex().analyzed();
473 initBaseRule(idxBuilder.indexRule(PROJECT_MIXIN_TYPE))
474 .property( "name" ).propertyIndex().analyzed().notNullCheckEnabled().nullCheckEnabled();
475 initBaseRule( idxBuilder.indexRule( PROJECT_VERSION_NODE_TYPE ) )
476 .property("name").propertyIndex().analyzed().notNullCheckEnabled().nullCheckEnabled()
477 .property("description").propertyIndex().analyzed().notNullCheckEnabled().nullCheckEnabled()
478 .property("url").propertyIndex().analyzed( ).notNullCheckEnabled().nullCheckEnabled()
479 .property("incomplete").type("Boolean").propertyIndex()
480 .property("mailinglist/name").propertyIndex().analyzed()
481 .property("license/license.name").propertyIndex().analyzed();
482 initBaseRule(idxBuilder.indexRule( ARTIFACT_NODE_TYPE ))
483 .property( "whenGathered" ).type("Date").propertyIndex().analyzed().ordered()
484 .property("size").type("Long").propertyIndex().analyzed().ordered()
485 .property("version").propertyIndex().analyzed().ordered()
486 .property("checksums/*/value").propertyIndex();
487
488 initBaseRule( idxBuilder.indexRule( CHECKSUM_NODE_TYPE ) )
489 .property("type").propertyIndex()
490 .property("value").propertyIndex();
491
492 initRegexAll( idxBuilder.indexRule( FACET_NODE_TYPE ) )
493 .property("archiva:facetId").propertyIndex().analyzed().ordered()
494 .property("archiva:name").propertyIndex().analyzed().ordered().nullCheckEnabled().notNullCheckEnabled();
495
496 idxBuilder.indexRule( MIXIN_META_SCM )
497 .property( "scm.connection" ).propertyIndex()
498 .property( "scm.developerConnection" ).propertyIndex()
499 .property( "scm.url").type("URI").propertyIndex().analyzed();
500 idxBuilder.indexRule( MIXIN_META_CI )
501 .property( "ci.system" ).propertyIndex( )
502 .property( "ci.ur" ).propertyIndex( ).analyzed( );
503 idxBuilder.indexRule( MIXIN_META_ISSUE )
504 .property( "issue.system").propertyIndex()
505 .property("issue.url").propertyIndex().analyzed();
506 idxBuilder.indexRule( MIXIN_META_ORGANIZATION )
507 .property( "org.name" ).propertyIndex( ).analyzed( )
508 .property( "org.url" ).propertyIndex( ).analyzed( );
509 idxBuilder.indexRule( LICENSE_NODE_TYPE )
510 .property( "license.name" ).propertyIndex( ).analyzed( )
511 .property( "license.url" ).propertyIndex( ).analyzed( );
512 idxBuilder.indexRule( MAILINGLIST_NODE_TYPE )
513 .property( "name" ).propertyIndex().analyzed();
514 initBaseRule(idxBuilder.indexRule( DEPENDENCY_NODE_TYPE ))
515 .property( "groupId" ).propertyIndex().analyzed().ordered()
516 .property( "artifactId").propertyIndex().analyzed().ordered()
517 .property("version").propertyIndex().analyzed().ordered()
518 .property("type").propertyIndex().analyzed().ordered()
519 .property( "classifier" ).propertyIndex().ordered()
520 .property("scope").propertyIndex()
521 .property("systemPath").propertyIndex().analyzed()
522 .property("optional").type("Boolean").propertyIndex();
523
524 idxBuilder.aggregateRule( PROJECT_VERSION_NODE_TYPE ).include( "dependencies")
525 .path("dependencies/*" ).relativeNode();
526
527 idxBuilder.build( );
528
529 IndexUtils.createIndexDefinition( oakIdx, "baseIndexes", true, false, ImmutableList.of( "jcr:uuid", "rep:principalName" ), null );
530
531 log.info( "Index: {} repo-lucene: {}", lucene, lucene.getChildNode( "repo-lucene" ) );
532 log.info( "repo-lucene Properties: {}", lucene.getChildNode( "repo-lucene" ).getProperties( ) );
533 } else {
534 log.info( "No Index update" );
535 }
536
537
538 }
539 };
540
541
542
543
544
545
546
547
548 log.info( "Starting Jcr repo with nodeStore {}", nodeStore );
549 Jcr jcr = new Jcr( nodeStore ).with( editorProvider )
550 .with( backgroundObserver )
551 .with( externalIndexObserver )
552
553 .with( (QueryIndexProvider) indexProvider )
554 .with (repoInitializer)
555 .withAsyncIndexing( "async", 5 );
556
557
558 StopWatch stopWatch = new StopWatch();
559 stopWatch.start();
560 Repository r = jcr.createRepository();
561 stopWatch.stop();
562 log.info( "time to create jcr repository: {} ms", stopWatch.getTime() );
563
564 return r;
565
566
567 }
568
569 private void closeSilently( Closeable service) {
570 if (service!=null) {
571 try
572 {
573 service.close();
574 }
575 catch ( Throwable e )
576 {
577
578 }
579 }
580 }
581
582 public void close()
583 {
584 log.info( "Closing JCR RepositoryFactory" );
585 closeSilently( fileStore );
586 closeSilently( backgroundObserver );
587 closeSilently( externalIndexObserver );
588 closeSilently( indexProvider );
589 indexProvider = null;
590 closeSilently( documentQueue );
591 closeSilently( nrtIndexFactory );
592 closeSilently( indexCopier );
593
594 if (executorService != null){
595 executorService.shutdown();
596 try
597 {
598 executorService.awaitTermination(1, TimeUnit.MINUTES);
599 }
600 catch ( InterruptedException e )
601 {
602 e.printStackTrace( );
603 }
604 }
605
606 if (extractedTextCache != null) {
607 extractedTextCache.close();
608 }
609
610 }
611
612 public StoreType getStoreType()
613 {
614 return storeType;
615 }
616
617 public void setStoreType( StoreType storeType )
618 {
619 this.storeType = storeType;
620 }
621
622 public Path getRepositoryPath()
623 {
624 return repositoryPath;
625 }
626
627 public void setRepositoryPath( Path repositoryPath )
628 {
629 this.repositoryPath = repositoryPath;
630 }
631
632 public void setRepositoryPath( String repositoryPath )
633 {
634 this.repositoryPath = Paths.get( repositoryPath );
635 if ( !Files.exists( this.repositoryPath ) )
636 {
637 try
638 {
639 Files.createDirectories( this.repositoryPath );
640 }
641 catch ( IOException e )
642 {
643 log.error( e.getMessage(), e );
644 throw new IllegalArgumentException( "cannot create directory:" + repositoryPath, e );
645 }
646 }
647 }
648
649
650 }