Index: lucene/src/test/org/apache/lucene/search/TestSearchWithThreads.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestSearchWithThreads.java (revision 0)
+++ lucene/src/test/org/apache/lucene/search/TestSearchWithThreads.java (revision 0)
@@ -0,0 +1,115 @@
+package org.apache.lucene.search;
+
+/**
+ * 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.
+ */
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.FSDirectory;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util._TestUtil;
+
+public class TestSearchWithThreads extends LuceneTestCase {
+
+ final int NUM_DOCS = 100000;
+ final int NUM_SEARCH_THREADS = 20;
+ final int RUN_TIME_MSEC = 10000 * RANDOM_MULTIPLIER;
+
+ public void test() throws Exception {
+ final Directory dir = FSDirectory.open(_TestUtil.getTempDir("SearchWithThreads"));
+ //final Directory dir = new RAMDirectory();
+ final IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()));
+
+ final long startTime = System.currentTimeMillis();
+
+ // TODO: replace w/ the @nightly test data; make this
+ // into an optional @nightly stress test
+ final Document doc = new Document();
+ final Field body = newField("body", "", Field.Index.ANALYZED);
+ doc.add(body);
+ final StringBuilder sb = new StringBuilder();
+ for(int docCount=0;docCount 0);
+ netSearch.addAndGet(totSearch);
+ } catch (Exception exc) {
+ failed.set(true);
+ throw new RuntimeException(exc);
+ }
+ }
+ };
+ threads[threadID].setDaemon(true);
+ threads[threadID].start();
+ }
+
+ for(int threadID=0;threadID
+ * Steps:
+ *
+ * - Compile the source code to create WindowsDirectory.dll:
+ *
+ * c:\mingw\bin\g++ -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at
+ * -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -static-libgcc
+ * -static-libstdc++ -shared WindowsDirectory.cpp -o WindowsDirectory.dll
+ *
+ * For 64-bit JREs, use mingw64, with the -m64 option.
+ * - Put WindowsDirectory.dll into some directory in your windows PATH
+ *
- Open indexes with WindowsDirectory and use it.
+ *
+ * @lucene.experimental
+ */
+public class WindowsDirectory extends FSDirectory {
+
+ static {
+ System.loadLibrary("WindowsDirectory");
+ }
+
+ /** Create a new WindowsDirectory for the named location.
+ *
+ * @param path the path of the directory
+ * @param lockFactory the lock factory to use, or null for the default
+ * ({@link NativeFSLockFactory});
+ * @throws IOException
+ */
+ public WindowsDirectory(File path, LockFactory lockFactory) throws IOException {
+ super(path, lockFactory);
+ }
+
+ /** Create a new WindowsDirectory for the named location and {@link NativeFSLockFactory}.
+ *
+ * @param path the path of the directory
+ * @throws IOException
+ */
+ public WindowsDirectory(File path) throws IOException {
+ super(path, null);
+ }
+
+ public IndexInput openInput(String name, int bufferSize) throws IOException {
+ ensureOpen();
+ return new WindowsIndexInput(new File(getDirectory(), name), bufferSize);
+ }
+
+ protected static class WindowsIndexInput extends BufferedIndexInput {
+ private final long fd;
+ private final long length;
+ boolean isClone;
+ boolean isOpen;
+
+ public WindowsIndexInput(File file, int bufferSize) throws IOException {
+ super(bufferSize);
+ fd = WindowsDirectory.open(file.getPath());
+ length = WindowsDirectory.length(fd);
+ isOpen = true;
+ }
+
+ protected void readInternal(byte[] b, int offset, int length) throws IOException {
+ if (WindowsDirectory.read(fd, b, offset, length, getFilePointer()) != length)
+ throw new IOException("Read past EOF");
+ }
+
+ protected void seekInternal(long pos) throws IOException {
+ }
+
+ public synchronized void close() throws IOException {
+ // NOTE: we synchronize and track "isOpen" because Lucene sometimes closes IIs twice!
+ if (!isClone && isOpen) {
+ WindowsDirectory.close(fd);
+ isOpen = false;
+ }
+ }
+
+ public long length() {
+ return length;
+ }
+
+ @Override
+ public Object clone() {
+ WindowsIndexInput clone = (WindowsIndexInput)super.clone();
+ clone.isClone = true;
+ return clone;
+ }
+ }
+
+ /** Opens a handle to a file. */
+ private static native long open(String filename) throws IOException;
+
+ /** Reads data from a file at pos into bytes */
+ private static native int read(long fd, byte bytes[], int offset, int length, long pos) throws IOException;
+
+ /** Closes a handle to a file */
+ private static native void close(long fd) throws IOException;
+
+ /** Returns the length of a file */
+ private static native long length(long fd) throws IOException;
+}
Property changes on: lucene\contrib\misc\src\java\org\apache\lucene\store\WindowsDirectory.java
___________________________________________________________________
Added: svn:eol-style
+ native
Index: lucene/contrib/misc/src/java/org/apache/lucene/store/WindowsDirectory.cpp
===================================================================
--- lucene/contrib/misc/src/java/org/apache/lucene/store/WindowsDirectory.cpp (revision 0)
+++ lucene/contrib/misc/src/java/org/apache/lucene/store/WindowsDirectory.cpp (revision 0)
@@ -0,0 +1,181 @@
+/**
+ * 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.
+ */
+
+#include
+#include "windows.h"
+
+/**
+ * Windows Native IO methods.
+ */
+extern "C" {
+
+/**
+ * Utility to format a Windows system error code into an exception.
+ */
+void throwIOException(JNIEnv *env, DWORD error)
+{
+ jclass ioex;
+ char *msg;
+
+ ioex = env->FindClass("java/io/IOException");
+
+ if (ioex != NULL) {
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msg, 0, NULL );
+ env->ThrowNew(ioex, msg);
+ LocalFree(msg);
+ }
+}
+
+/**
+ * Utility to throw Exceptions on bad input
+ */
+void throwException(JNIEnv *env, const char *clazz, const char *msg)
+{
+ jclass exc = env->FindClass(clazz);
+
+ if (exc != NULL) {
+ env->ThrowNew(exc, msg);
+ }
+}
+
+/**
+ * Opens a handle to a file.
+ *
+ * Class: org_apache_lucene_store_WindowsDirectory
+ * Method: open
+ * Signature: (Ljava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL Java_org_apache_lucene_store_WindowsDirectory_open
+ (JNIEnv *env, jclass ignored, jstring filename)
+{
+ char *fname;
+ HANDLE handle;
+ jboolean isCopy;
+
+ if (filename == NULL) {
+ throwException(env, "java/lang/NullPointerException", "filename cannot be null");
+ return -1;
+ }
+
+ fname = (char *) env->GetStringUTFChars(filename, &isCopy);
+
+ if (fname == NULL) {
+ throwException(env, "java/lang/IllegalArgumentException", "invalid filename");
+ return -1;
+ }
+
+ handle = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
+
+ if (isCopy) {
+ env->ReleaseStringUTFChars(filename, fname);
+ }
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ throwIOException(env, GetLastError());
+ return -1;
+ }
+
+ return (jlong) handle;
+}
+
+/**
+ * Reads data into the byte array, starting at offset, for length characters.
+ * The read is positioned at pos.
+ *
+ * Class: org_apache_lucene_store_WindowsDirectory
+ * Method: read
+ * Signature: (J[BIIJ)I
+ */
+JNIEXPORT jint JNICALL Java_org_apache_lucene_store_WindowsDirectory_read
+ (JNIEnv *env, jclass ignored, jlong fd, jbyteArray bytes, jint offset, jint length, jlong pos)
+{
+ OVERLAPPED io = { 0 };
+ DWORD numRead = -1;
+
+ io.Offset = (DWORD) (pos & 0xFFFFFFFF);
+ io.OffsetHigh = (DWORD) ((pos >> 0x20) & 0x7FFFFFFF);
+
+ if (bytes == NULL) {
+ throwException(env, "java/lang/NullPointerException", "bytes cannot be null");
+ return -1;
+ }
+
+ if (length <= 2048) { /* For small buffers, avoid GetByteArrayElements' copy */
+ char buffer[length];
+
+ if (!ReadFile((HANDLE) fd, &buffer, length, &numRead, &io)) {
+ throwIOException(env, GetLastError());
+ numRead = -1;
+ }
+
+ env->SetByteArrayRegion(bytes, offset, numRead, (const jbyte *) buffer);
+
+ } else {
+ jboolean isCopy;
+ jbyte *buffer = env->GetByteArrayElements (bytes, &isCopy);
+
+ if (!ReadFile((HANDLE) fd, (void *)(buffer+offset), length, &numRead, &io)) {
+ throwIOException(env, GetLastError());
+ numRead = -1;
+ }
+
+ if (isCopy == JNI_TRUE) {
+ env->ReleaseByteArrayElements(bytes, buffer, numRead == 0 || numRead == -1 ? JNI_ABORT : 0);
+ }
+ }
+
+ return numRead;
+}
+
+/**
+ * Closes a handle to a file
+ *
+ * Class: org_apache_lucene_store_WindowsDirectory
+ * Method: close
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_org_apache_lucene_store_WindowsDirectory_close
+ (JNIEnv *env, jclass ignored, jlong fd)
+{
+ if (!CloseHandle((HANDLE) fd)) {
+ throwIOException(env, GetLastError());
+ }
+}
+
+/**
+ * Returns the length in bytes of a file.
+ *
+ * Class: org_apache_lucene_store_WindowsDirectory
+ * Method: length
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_org_apache_lucene_store_WindowsDirectory_length
+ (JNIEnv *env, jclass ignored, jlong fd)
+{
+ BY_HANDLE_FILE_INFORMATION info;
+
+ if (GetFileInformationByHandle((HANDLE) fd, (LPBY_HANDLE_FILE_INFORMATION) &info)) {
+ return (jlong) (((DWORDLONG) info.nFileSizeHigh << 0x20) + info.nFileSizeLow);
+ } else {
+ throwIOException(env, GetLastError());
+ return -1;
+ }
+}
+
+} /* extern "C" */
Property changes on: lucene\contrib\misc\src\java\org\apache\lucene\store\WindowsDirectory.cpp
___________________________________________________________________
Added: svn:eol-style
+ native