1 package org.apache.lucene.store;
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.List;
27 import java.util.HashSet;
30 * Expert: A Directory instance that switches files between
31 * two other Directory instances.
33 * <p>Files with the specified extensions are placed in the
34 * primary directory; others are placed in the secondary
35 * directory. The provided Set must not change once passed
36 * to this class, and must allow multiple threads to call
37 * contains at once.</p>
39 * @lucene.experimental
42 public class FileSwitchDirectory extends Directory {
43 private final Directory secondaryDir;
44 private final Directory primaryDir;
45 private final Set<String> primaryExtensions;
46 private boolean doClose;
48 public FileSwitchDirectory(Set<String> primaryExtensions, Directory primaryDir, Directory secondaryDir, boolean doClose) {
49 this.primaryExtensions = primaryExtensions;
50 this.primaryDir = primaryDir;
51 this.secondaryDir = secondaryDir;
52 this.doClose = doClose;
53 this.lockFactory = primaryDir.getLockFactory();
56 /** Return the primary directory */
57 public Directory getPrimaryDir() {
61 /** Return the secondary directory */
62 public Directory getSecondaryDir() {
67 public void close() throws IOException {
79 public String[] listAll() throws IOException {
80 Set<String> files = new HashSet<String>();
81 // LUCENE-3380: either or both of our dirs could be FSDirs,
82 // but if one underlying delegate is an FSDir and mkdirs() has not
83 // yet been called, because so far everything is written to the other,
84 // in this case, we don't want to throw a NoSuchDirectoryException
85 NoSuchDirectoryException exc = null;
87 for(String f : primaryDir.listAll()) {
90 } catch (NoSuchDirectoryException e) {
94 for(String f : secondaryDir.listAll()) {
97 } catch (NoSuchDirectoryException e) {
98 // we got NoSuchDirectoryException from both dirs
103 // we got NoSuchDirectoryException from the secondary,
104 // and the primary is empty.
105 if (files.isEmpty()) {
109 // we got NoSuchDirectoryException from the primary,
110 // and the secondary is empty.
111 if (exc != null && files.isEmpty()) {
114 return files.toArray(new String[files.size()]);
117 /** Utility method to return a file's extension. */
118 public static String getExtension(String name) {
119 int i = name.lastIndexOf('.');
123 return name.substring(i+1, name.length());
126 private Directory getDirectory(String name) {
127 String ext = getExtension(name);
128 if (primaryExtensions.contains(ext)) {
136 public boolean fileExists(String name) throws IOException {
137 return getDirectory(name).fileExists(name);
141 public long fileModified(String name) throws IOException {
142 return getDirectory(name).fileModified(name);
147 /* @deprecated Lucene never uses this API; it will be
149 public void touchFile(String name) throws IOException {
150 getDirectory(name).touchFile(name);
154 public void deleteFile(String name) throws IOException {
155 getDirectory(name).deleteFile(name);
159 public long fileLength(String name) throws IOException {
160 return getDirectory(name).fileLength(name);
164 public IndexOutput createOutput(String name) throws IOException {
165 return getDirectory(name).createOutput(name);
170 public void sync(String name) throws IOException {
171 sync(Collections.singleton(name));
175 public void sync(Collection<String> names) throws IOException {
176 List<String> primaryNames = new ArrayList<String>();
177 List<String> secondaryNames = new ArrayList<String>();
179 for (String name : names)
180 if (primaryExtensions.contains(getExtension(name)))
181 primaryNames.add(name);
183 secondaryNames.add(name);
185 primaryDir.sync(primaryNames);
186 secondaryDir.sync(secondaryNames);
190 public IndexInput openInput(String name) throws IOException {
191 return getDirectory(name).openInput(name);