2
* Licensed to the Apache Software Foundation (ASF) under one or more
3
* contributor license agreements. See the NOTICE file distributed with
4
* this work for additional information regarding copyright ownership.
5
* The ASF licenses this file to You under the Apache License, Version 2.0
6
* (the "License"); you may not use this file except in compliance with
7
* the License. You may obtain a copy of the License at
9
* http://www.apache.org/licenses/LICENSE-2.0
11
* Unless required by applicable law or agreed to in writing, software
12
* distributed under the License is distributed on an "AS IS" BASIS,
13
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
* See the License for the specific language governing permissions and
15
* limitations under the License.
18
package org.apache.solr.update;
20
import org.apache.lucene.index.*;
21
import org.apache.lucene.store.*;
22
import org.apache.solr.common.SolrException;
23
import org.apache.solr.core.DirectoryFactory;
24
import org.apache.solr.schema.IndexSchema;
26
import org.slf4j.Logger;
27
import org.slf4j.LoggerFactory;
30
import java.io.FileOutputStream;
31
import java.io.IOException;
32
import java.io.OutputStream;
33
import java.io.PrintStream;
34
import java.text.DateFormat;
35
import java.util.Date;
36
import java.util.Locale;
39
* An IndexWriter that is configured via Solr config mechanisms.
41
* @version $Id: SolrIndexWriter.java 1065312 2011-01-30 16:08:25Z rmuir $
45
public class SolrIndexWriter extends IndexWriter {
46
private static Logger log = LoggerFactory.getLogger(SolrIndexWriter.class);
49
private PrintStream infoStream;
51
public static Directory getDirectory(String path, DirectoryFactory directoryFactory, SolrIndexConfig config) throws IOException {
53
Directory d = directoryFactory.open(path);
55
String rawLockType = (null == config) ? null : config.lockType;
56
if (null == rawLockType) {
57
// we default to "simple" for backwards compatibility
58
log.warn("No lockType configured for " + path + " assuming 'simple'");
59
rawLockType = "simple";
61
final String lockType = rawLockType.toLowerCase(Locale.ENGLISH).trim();
63
if ("simple".equals(lockType)) {
64
// multiple SimpleFSLockFactory instances should be OK
65
d.setLockFactory(new SimpleFSLockFactory(path));
66
} else if ("native".equals(lockType)) {
67
d.setLockFactory(new NativeFSLockFactory(path));
68
} else if ("single".equals(lockType)) {
69
if (!(d.getLockFactory() instanceof SingleInstanceLockFactory))
70
d.setLockFactory(new SingleInstanceLockFactory());
71
} else if ("none".equals(lockType)) {
72
// Recipe for disaster
73
log.error("CONFIGURATION WARNING: locks are disabled on " + path);
74
d.setLockFactory(NoLockFactory.getNoLockFactory());
76
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
77
"Unrecognized lockType: " + rawLockType);
82
public SolrIndexWriter(String name, String path, DirectoryFactory dirFactory, boolean create, IndexSchema schema, SolrIndexConfig config, IndexDeletionPolicy delPolicy) throws IOException {
84
getDirectory(path, dirFactory, config),
85
config.toIndexWriterConfig(schema).
86
setOpenMode(create ? IndexWriterConfig.OpenMode.CREATE : IndexWriterConfig.OpenMode.APPEND).
87
setIndexDeletionPolicy(delPolicy)
90
if (config.maxFieldLength != -1)
91
setMaxFieldLength(config.maxFieldLength);
93
log.debug("Opened Writer " + name);
96
String infoStreamFile = config.infoStreamFile;
97
if (infoStreamFile != null) {
98
File f = new File(infoStreamFile);
99
File parent = f.getParentFile();
100
if (parent != null) parent.mkdirs();
101
FileOutputStream fos = new FileOutputStream(f, true);
102
infoStream = new TimeLoggingPrintStream(fos, true);
103
setInfoStream(infoStream);
109
* use DocumentBuilder now...
110
* private final void addField(Document doc, String name, String val) {
111
* SchemaField ftype = schema.getField(name);
113
* // we don't check for a null val ourselves because a solr.FieldType
114
* // might actually want to map it to something. If createField()
115
* // returns null, then we don't store the field.
117
* Field field = ftype.createField(val, boost);
118
* if (field != null) doc.add(field);
122
* public void addRecord(String[] fieldNames, String[] fieldValues) throws IOException {
123
* Document doc = new Document();
124
* for (int i=0; i<fieldNames.length; i++) {
125
* String name = fieldNames[i];
126
* String val = fieldNames[i];
128
* // first null is end of list. client can reuse arrays if they want
129
* // and just write a single null if there is unused space.
130
* if (name==null) break;
132
* addField(doc,name,val);
138
private volatile boolean isClosed = false;
140
public void close() throws IOException {
141
log.debug("Closing Writer " + name);
144
if(infoStream != null) {
153
public void rollback() throws IOException {
162
protected void finalize() throws Throwable {
165
log.error("SolrIndexWriter was not closed prior to finalize(), indicates a bug -- POSSIBLE RESOURCE LEAK!!!");
174
// Helper class for adding timestamps to infoStream logging
175
class TimeLoggingPrintStream extends PrintStream {
176
private DateFormat dateFormat;
177
public TimeLoggingPrintStream(OutputStream underlyingOutputStream,
179
super(underlyingOutputStream, autoFlush);
180
this.dateFormat = DateFormat.getDateTimeInstance();
183
// We might ideally want to override print(String) as well, but
184
// looking through the code that writes to infoStream, it appears
185
// that all the classes except CheckIndex just use println.
187
public void println(String x) {
188
print(dateFormat.format(new Date()) + " ");