📄 storagecorecontroller.java
字号:
/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.lucene.gdata.storage.lucenestorage;import java.io.File;import java.io.IOException;import java.util.concurrent.atomic.AtomicBoolean;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.ReentrantLock;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.gdata.data.GDataAccount;import org.apache.lucene.gdata.server.registry.Component;import org.apache.lucene.gdata.server.registry.ComponentType;import org.apache.lucene.gdata.server.registry.configuration.Requiered;import org.apache.lucene.gdata.storage.IDGenerator;import org.apache.lucene.gdata.storage.Storage;import org.apache.lucene.gdata.storage.StorageController;import org.apache.lucene.gdata.storage.StorageException;import org.apache.lucene.gdata.storage.lucenestorage.recover.RecoverController;import org.apache.lucene.gdata.storage.lucenestorage.recover.RecoverException;import org.apache.lucene.gdata.utils.ReferenceCounter;import org.apache.lucene.index.IndexModifier;import org.apache.lucene.search.IndexSearcher;import org.apache.lucene.store.Directory;import org.apache.lucene.store.FSDirectory;/** * * * @author Simon Willnauer * */@Component(componentType = ComponentType.STORAGECONTROLLER)public class StorageCoreController implements StorageController { protected static final Log LOG = LogFactory .getLog(StorageCoreController.class); private IndexSearcher searcher; private Directory storageDir; private StorageModifier modifier; private ReferenceCounter<StorageQuery> storageQuery; private StorageBuffer currentBuffer; private final AtomicBoolean isClosed = new AtomicBoolean(false); private final ReentrantLock storageControllerLock = new ReentrantLock(); private final Condition closeCondition; private static final int DEFAULT_STORAGE_BUFFER_SIZE = 3; private static final int DEFAULT_STORAGE_PERSIST_FACTOR = 3; private static final String RECOVERDIRECTORY = "recover"; private static final String STORAGELOG = ".lucenestorage"; private IDGenerator idGenerator; private final ConcurrentStorageLock storageLock; /* *properties set by configuration file e.g. Registry */ private int indexOptimizeInterval; private String storageDirectory; private boolean keepRecoveredFiles; private boolean recover; private int storageBufferSize; private int storagePersistFactor; private RecoverController recoverController; /** * @see org.apache.lucene.gdata.server.registry.ServerComponent#initialize() */ public void initialize() { synchronized (StorageCoreController.class) { try { this.idGenerator = new IDGenerator(10); } catch (Exception e) { throw new StorageException("Can't create ID Generator", e); } boolean createNewStorage = false; if (this.storageDir == null) { File storeDir = new File(this.storageDirectory); File storageLog = new File(storeDir.getAbsolutePath() + System.getProperty("file.separator") + STORAGELOG); try { if (storeDir.isDirectory() && !storageLog.exists()) { if (createLuceneStorageLog(storeDir)) { this.storageDir = FSDirectory.getDirectory( storeDir, true); createNewStorage = true; } else throw new StorageException( "could not create storage lock file in " + this.storageDirectory); } else this.storageDir = FSDirectory.getDirectory(storeDir, false); } catch (IOException e) { storageLog.delete(); throw new StorageException(e); } this.storageBufferSize = this.storageBufferSize < DEFAULT_STORAGE_BUFFER_SIZE ? DEFAULT_STORAGE_BUFFER_SIZE : this.storageBufferSize; this.storagePersistFactor = this.storagePersistFactor < DEFAULT_STORAGE_PERSIST_FACTOR ? DEFAULT_STORAGE_PERSIST_FACTOR : this.storagePersistFactor; }else createNewStorage = true; this.currentBuffer = new StorageBuffer(this.storageBufferSize); try{ this.modifier = createStorageModifier(createNewStorage); this.searcher = new IndexSearcher(this.storageDir); }catch (Exception e) { throw new StorageException("Can not create Searcher/Modifier -- "+e.getMessage(),e); } if(createNewStorage) createAdminAccount(); if(!this.recover) return; try{ tryRecover(); }catch (Exception e) { LOG.fatal("Recovering failed",e); throw new StorageException("Recovering failed -- "+e.getMessage(),e); } this.recoverController = createRecoverController(false,false); try{ this.recoverController.initialize(); }catch (Exception e) { LOG.fatal("Can not initialize recover controller",e); throw new StorageException("Can not initialize recover controller -- "+e.getMessage(),e); } } } /* * reads the remaining recover files to store the failed entries */ private void tryRecover() throws IOException, RecoverException{ if(!this.recover) return; LOG.info("try to recover files if there are any"); this.recoverController = createRecoverController(true,false); this.recoverController.initialize(); this.recoverController.recoverEntries(this.modifier); this.recoverController.destroy(); } private RecoverController createRecoverController(boolean doRecover, boolean keepfiles){ String recoverDirectory = null; if(this.storageDirectory.endsWith("/") || this.storageDirectory.endsWith("\\")) recoverDirectory = this.storageDirectory.substring(0,this.storageDirectory.length()-1)+System.getProperty("file.separator")+RECOVERDIRECTORY; else recoverDirectory = this.storageDirectory+System.getProperty("file.separator")+RECOVERDIRECTORY; File recoverDirectoryFile = new File(recoverDirectory); return new RecoverController(recoverDirectoryFile,doRecover,keepfiles); } /** * Creates a new <tt>StoragCoreController</tt> */ public StorageCoreController() { this.closeCondition = this.storageControllerLock.newCondition(); this.storageLock = SingleHostConcurrentStorageLock.getConcurrentStorageLock(); } private StorageModifier createStorageModifier(boolean create) throws IOException { IndexModifier indexModifier = new IndexModifier(this.storageDir, new StandardAnalyzer(), create); return new StorageModifier(this, indexModifier, this.currentBuffer, this.storagePersistFactor, this.indexOptimizeInterval); } /** * returns the current storage modifier * * @return - the current storage modifier */ protected StorageModifier getStorageModifier() { return this.modifier; } /** * returns a <tt>StorageQuery</tt> to query the storage index. The * returned object is a reference counter to keep track of the references to * the <tt>StorageQuery</tt>. The reference is already incremented before * returned from this method. * <p> * if the reference counter has no remaining references the resource e.g. * the <tt>StorageQuery</tt> will be closed. This ensures that a * <tt>StorageQuery</tt> instance will be around as long as needed and * the resources will be released. The reference counter should be * decremented by clients after finished using the query instance. * </p> * * @return a {@link ReferenceCounter} instance holding the StorageQuery as a * resource. * */ protected ReferenceCounter<StorageQuery> getStorageQuery() { if(this.isClosed.get()) throw new IllegalStateException("StorageController is already closed -- server is shutting down"); this.storageControllerLock.lock(); try{ if(this.isClosed.get()) throw new IllegalStateException("StorageController is already closed -- server is shutting down"); if (this.storageQuery == null) { this.storageQuery = getNewStorageQueryHolder(new StorageQuery( this.currentBuffer, this.searcher)); if (LOG.isInfoEnabled()) LOG.info("Release new StorageQuery"); } this.storageQuery.increamentReference(); return this.storageQuery; }finally{ try{ this.closeCondition.signalAll(); }catch (Throwable e) {/**/} this.storageControllerLock.unlock(); } } private ReferenceCounter<StorageQuery> getNewStorageQueryHolder( final StorageQuery query) { ReferenceCounter<StorageQuery> holder = new ReferenceCounter<StorageQuery>( query) { @Override public void close() { try { if (LOG.isInfoEnabled()) LOG .info("close StorageQuery -- zero references remaining"); this.resource.close(); } catch (IOException e) { LOG.warn("Error during close call on StorageQuery" + e.getMessage(), e); } } }; holder.increamentReference(); return holder; } /** * Forces the controller to register a new <tt>StorageQuery</tt> instance. * This method will be called after an index has been modified to make the * changes available for searching. * * @throws IOException - * if an IO exception occurs */ protected void registerNewStorageQuery() throws IOException { if(this.isClosed.get()) throw new IllegalStateException("StorageController is already closed -- server is shutting down"); this.storageControllerLock.lock(); try{ if(this.isClosed.get()) throw new IllegalStateException("StorageController is already closed -- server is shutting down"); if (LOG.isInfoEnabled()) LOG.info("new StorageQuery requested -- create new storage buffer"); if (this.storageQuery != null) this.storageQuery.decrementRef(); this.searcher = new IndexSearcher(this.storageDir); this.storageQuery = null; this.currentBuffer = new StorageBuffer(this.storageBufferSize);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -