001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.compass.gps.impl;
018:
019: import java.util.Properties;
020:
021: import org.compass.core.Compass;
022: import org.compass.core.CompassCallback;
023: import org.compass.core.CompassException;
024: import org.compass.core.CompassTemplate;
025: import org.compass.core.CompassTransaction;
026: import org.compass.core.CompassTransaction.TransactionIsolation;
027: import org.compass.core.config.CompassEnvironment;
028: import org.compass.core.config.CompassSettings;
029: import org.compass.core.engine.SearchEngineException;
030: import org.compass.core.engine.SearchEngineIndexManager;
031: import org.compass.core.lucene.LuceneEnvironment;
032: import org.compass.core.lucene.engine.LuceneSearchEngineFactory;
033: import org.compass.core.mapping.CascadeMapping;
034: import org.compass.core.mapping.ResourceMapping;
035: import org.compass.core.spi.InternalCompass;
036: import org.compass.gps.CompassGpsDevice;
037: import org.compass.gps.CompassGpsException;
038:
039: /**
040: * <p>A {@link org.compass.gps.CompassGps} implementation that holds a
041: * single <code>Compass</code> instance. The <code>Compass</code> instance
042: * is used for both the index operation and the mirror operation.
043: *
044: * <p>When executing the mirror operation, the implementation will not use the
045: * configured transaction isolation, but will use the
046: * {@link #setIndexTransactionIsolation(CompassTransaction.TransactionIsolation)}
047: * transaction isolation, which defaults to <code>lucene</code>. Cascading
048: * will also be disabled.
049: *
050: * @author kimchy
051: */
052: public class SingleCompassGps extends AbstractCompassGps {
053:
054: private Compass compass;
055:
056: private CompassTemplate compassTemplate;
057:
058: private Compass indexCompass;
059:
060: private CompassTemplate indexCompassTemplate;
061:
062: private CompassTransaction.TransactionIsolation indexTransactionIsolation = CompassTransaction.TransactionIsolation.LUCENE;
063:
064: private Properties indexSettings;
065:
066: private CompassSettings indexCompassSettings;
067:
068: public SingleCompassGps() {
069:
070: }
071:
072: public SingleCompassGps(Compass compass) {
073: this .compass = compass;
074: }
075:
076: protected void doStart() throws CompassGpsException {
077: if (compass == null) {
078: throw new IllegalArgumentException(
079: "Must set the compass property");
080: }
081: TransactionIsolation defaultIsolation = ((LuceneSearchEngineFactory) ((InternalCompass) compass)
082: .getSearchEngineFactory()).getLuceneSettings()
083: .getTransactionIsolation();
084: if (defaultIsolation == TransactionIsolation.BATCH_INSERT) {
085: throw new IllegalArgumentException(
086: "The compass instance is configured with transaction isolation of batch_insert"
087: + ", there is no need since this CompassGps will execute the index operation with batch_index automatically, "
088: + " and mirroring with the configured transaction isolation");
089: }
090: indexCompassSettings = new CompassSettings();
091: if (indexSettings != null) {
092: indexCompassSettings.addSettings(indexSettings);
093: }
094: if (indexCompassSettings
095: .getSetting(CompassEnvironment.CONNECTION_SUB_CONTEXT) == null) {
096: indexCompassSettings.setSetting(
097: CompassEnvironment.CONNECTION_SUB_CONTEXT,
098: "gpsindex");
099: }
100: if (indexCompassSettings
101: .getSetting(LuceneEnvironment.LocalCache.DISABLE_LOCAL_CACHE) == null) {
102: indexCompassSettings.setBooleanSetting(
103: LuceneEnvironment.LocalCache.DISABLE_LOCAL_CACHE,
104: true);
105: }
106: // indexing relies on thread local binding of local transactions
107: if (indexCompassSettings
108: .getSetting(CompassEnvironment.Transaction.DISABLE_THREAD_BOUND_LOCAL_TRANSATION) == null) {
109: indexCompassSettings
110: .setBooleanSetting(
111: CompassEnvironment.Transaction.DISABLE_THREAD_BOUND_LOCAL_TRANSATION,
112: false);
113: }
114: if (indexCompassSettings
115: .getSetting(CompassEnvironment.Cascade.DISABLE) == null) {
116: indexCompassSettings.setBooleanSetting(
117: CompassEnvironment.Cascade.DISABLE, true);
118: }
119: indexCompassSettings
120: .setBooleanSetting(
121: CompassEnvironment.Transaction.DISABLE_AUTO_JOIN_SESSION,
122: true);
123: this .compassTemplate = new CompassTemplate(compass);
124: }
125:
126: protected void doStop() throws CompassGpsException {
127: }
128:
129: protected void doIndex() throws CompassGpsException {
130: ((InternalCompass) compass).stop();
131:
132: // create the temp compass index, and clean it
133: indexCompass = compass.clone(indexCompassSettings);
134: indexCompass.getSearchEngineIndexManager().cleanIndex();
135: indexCompassTemplate = new CompassTemplate(indexCompass);
136:
137: indexCompass.getSearchEngineIndexManager().clearCache();
138: compass.getSearchEngineIndexManager().replaceIndex(
139: indexCompass.getSearchEngineIndexManager(),
140: new SearchEngineIndexManager.ReplaceIndexCallback() {
141: public void buildIndexIfNeeded()
142: throws SearchEngineException {
143: for (CompassGpsDevice device : devices.values()) {
144: device.index();
145: }
146: }
147: });
148: indexCompass.getSearchEngineIndexManager().clearCache();
149: try {
150: indexCompass.getSearchEngineIndexManager().deleteIndex();
151: } catch (CompassException e) {
152: log
153: .debug(
154: "Failed to delete gps index after indexing, ignoring",
155: e);
156: }
157: indexCompass.close();
158: indexCompass = null;
159: indexCompassTemplate = null;
160:
161: ((InternalCompass) compass).start();
162:
163: if (compass.getSpellCheckManager() != null) {
164: log.info("Rebulding spell check index ...");
165: try {
166: compass.getSpellCheckManager().concurrentRebuild();
167: log.info("Spell check index rebuilt");
168: } catch (Exception e) {
169: log
170: .info(
171: "Spell check index failed, will rebuilt it next time",
172: e);
173: }
174: }
175: }
176:
177: public void executeForIndex(CompassCallback callback)
178: throws CompassException {
179: if (indexCompassTemplate == null) {
180: compassTemplate
181: .execute(indexTransactionIsolation, callback);
182: return;
183: }
184: indexCompassTemplate.execute(indexTransactionIsolation,
185: callback);
186: }
187:
188: public void executeForMirror(CompassCallback callback)
189: throws CompassException {
190: compassTemplate.execute(callback);
191: }
192:
193: public boolean hasMappingForEntityForIndex(Class clazz)
194: throws CompassException {
195: return hasRootMappingForEntity(clazz, getIndexCompass());
196: }
197:
198: public boolean hasMappingForEntityForIndex(String name)
199: throws CompassException {
200: return hasRootMappingForEntity(name, getIndexCompass());
201: }
202:
203: public boolean hasMappingForEntityForMirror(Class clazz,
204: CascadeMapping.Cascade cascade) throws CompassException {
205: return hasMappingForEntity(clazz, compass, cascade);
206: }
207:
208: public boolean hasMappingForEntityForMirror(String name,
209: CascadeMapping.Cascade cascade) throws CompassException {
210: return hasMappingForEntity(name, compass, cascade);
211: }
212:
213: public ResourceMapping getMappingForEntityForIndex(String name)
214: throws CompassException {
215: return getRootMappingForEntity(name, getIndexCompass());
216: }
217:
218: public ResourceMapping getMappingForEntityForIndex(Class clazz)
219: throws CompassException {
220: return getRootMappingForEntity(clazz, getIndexCompass());
221: }
222:
223: public Compass getIndexCompass() {
224: if (indexCompass == null) {
225: return compass;
226: }
227: return indexCompass;
228: }
229:
230: public Compass getMirrorCompass() {
231: return compass;
232: }
233:
234: /**
235: * Sets the compass instance that will be used with this Gps implementation.
236: * It will be used directly for mirror operations, and will be cloned
237: * (optionally adding the {@link #setIndexSettings(java.util.Properties)}
238: * for index operations.
239: */
240: public void setCompass(Compass compass) {
241: this .compass = compass;
242: }
243:
244: /**
245: * Sets the transaction isolation for the clones compass used for the index
246: * process.
247: */
248: public void setIndexTransactionIsolation(
249: CompassTransaction.TransactionIsolation indexTransactionIsolation) {
250: this .indexTransactionIsolation = indexTransactionIsolation;
251: }
252:
253: /**
254: * Sets the additional cloned compass index settings. The settings can
255: * override existing settings used to create the Compass instance. Can be
256: * used to define different connection string for example.
257: */
258: public void setIndexSettings(Properties indexSettings) {
259: this .indexSettings = indexSettings;
260: }
261:
262: /**
263: * Sets the additional cloned compass index settings. The settings can
264: * override existing settings used to create the Compass instance. Can be
265: * used to define different connection string for example.
266: */
267: public void setIndexProperties(Properties indexSettings) {
268: this .indexSettings = indexSettings;
269: }
270:
271: /**
272: * Sets the additional cloned compass index settings. The settings can
273: * override existing settings used to create the Compass instance. Can be
274: * used to define different connection string for example.
275: */
276: public void setIndexSettings(CompassSettings indexSettings) {
277: this.indexSettings = indexSettings.getProperties();
278: }
279: }
|