add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / contrib / misc / src / java / org / apache / lucene / store / NativePosixUtil.cpp
1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with this
4  * work for additional information regarding copyright ownership. The ASF
5  * licenses this file to You under the Apache License, Version 2.0 (the
6  * "License"); you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  * 
9  * http://www.apache.org/licenses/LICENSE-2.0
10  * 
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14  * License for the specific language governing permissions and limitations under
15  * the License.
16  */
17
18 #include <jni.h>
19 #include <fcntl.h>   // posix_fadvise, constants for open
20 #include <string.h>   // strerror
21 #include <errno.h>   // errno
22 #include <unistd.h>   // pread
23 #include <sys/mman.h>   // posix_madvise, madvise
24 #include <sys/types.h>  // constants for open
25 #include <sys/stat.h>  // constants for open
26
27 // java -cp .:lib/junit-4.7.jar:./build/classes/test:./build/classes/java:./build/classes/demo -Dlucene.version=2.9-dev -DtempDir=build -ea org.junit.runner.JUnitCore org.apache.lucene.index.TestDoc
28
29 /*
30  * Class:     org_apache_lucene_store_NativePosixUtil
31  * Method:    posix_fadvise
32  * Signature: (Ljava/io/FileDescriptor;JJI)V
33  */
34 extern "C"
35 JNIEXPORT jint JNICALL Java_org_apache_lucene_store_NativePosixUtil_posix_1fadvise(JNIEnv *env, jclass _ignore, jobject fileDescriptor, jlong offset, jlong len, jint advice)
36 {
37   jfieldID field_fd;
38   jmethodID const_fdesc;
39
40   jclass ioex = env->FindClass("java/io/IOException");
41   if (ioex == NULL) {
42     return -1;
43   }
44
45   jclass fdesc = env->FindClass("java/io/FileDescriptor");
46   if (fdesc == NULL) {
47     return -2;
48   }
49
50   // read the int fd field
51   jfieldID fdField = env->GetFieldID(fdesc, "fd", "I");
52   if (fdField == NULL) {
53     return -3;
54   }
55
56   int fd = env->GetIntField(fileDescriptor, fdField);
57   //printf("fd=%d\n", fd);  fflush(stdout);
58
59   int osAdvice;
60   switch(advice) {
61
62   case 0:
63     osAdvice = POSIX_FADV_NORMAL;
64     break;
65   case 1:
66     osAdvice = POSIX_FADV_SEQUENTIAL;
67     break;
68   case 2:
69     osAdvice = POSIX_FADV_RANDOM;
70     break;
71   case 3:
72     osAdvice = POSIX_FADV_WILLNEED;
73     break;
74   case 4:
75     osAdvice = POSIX_FADV_DONTNEED;
76     break;
77   case 5:
78     osAdvice = POSIX_FADV_NOREUSE;
79     break;
80   }
81
82   int result = posix_fadvise(fd, (off_t) offset, (off_t) len, osAdvice);
83   if (result == 0) {
84     // ok
85   } else {
86     env->ThrowNew(ioex, strerror(errno));
87     return -1;
88   }
89
90   return 0;
91 }
92
93
94 /*
95  * Class:     org_apache_lucene_store_NativePosixUtil
96  * Method:    open_direct
97  * Signature: (Ljava/lang/String;Z)Ljava/io/FileDescriptor;
98  */
99 extern "C"
100 JNIEXPORT jobject JNICALL Java_org_apache_lucene_store_NativePosixUtil_open_1direct(JNIEnv *env, jclass _ignore, jstring filename, jboolean readOnly)
101 {
102   jfieldID field_fd;
103   jmethodID const_fdesc;
104   jclass class_fdesc, class_ioex;
105   jobject ret;
106   int fd;
107   char *fname;
108
109   class_ioex = env->FindClass("java/io/IOException");
110   if (class_ioex == NULL) return NULL;
111   class_fdesc = env->FindClass("java/io/FileDescriptor");
112   if (class_fdesc == NULL) return NULL;
113
114   fname = (char *) env->GetStringUTFChars(filename, NULL);
115
116   if (readOnly) {
117     fd = open(fname, O_RDONLY | O_DIRECT | O_NOATIME);
118   } else {
119     fd = open(fname, O_RDWR | O_CREAT | O_DIRECT | O_NOATIME, 0666);
120   }
121
122   //printf("open %s -> %d; ro %d\n", fname, fd, readOnly); fflush(stdout);
123
124   env->ReleaseStringUTFChars(filename, fname);
125
126   if (fd < 0) {
127     // open returned an error. Throw an IOException with the error string
128     env->ThrowNew(class_ioex, strerror(errno));
129     return NULL;
130   }
131
132   // construct a new FileDescriptor
133   const_fdesc = env->GetMethodID(class_fdesc, "<init>", "()V");
134   if (const_fdesc == NULL) return NULL;
135   ret = env->NewObject(class_fdesc, const_fdesc);
136
137   // poke the "fd" field with the file descriptor
138   field_fd = env->GetFieldID(class_fdesc, "fd", "I");
139   if (field_fd == NULL) return NULL;
140   env->SetIntField(ret, field_fd, fd);
141
142   // and return it
143   return ret;
144 }
145
146
147 /*
148  * Class:     org_apache_lucene_store_NativePosixUtil
149  * Method:    pread
150  * Signature: (Ljava/io/FileDescriptor;JLjava/nio/ByteBuffer;)I
151  */
152 extern "C"
153 JNIEXPORT jlong JNICALL Java_org_apache_lucene_store_NativePosixUtil_pread(JNIEnv *env, jclass _ignore, jobject jfd, jlong pos, jobject byteBuf)
154 {
155   // get int fd:
156   jclass class_fdesc = env->FindClass("java/io/FileDescriptor");
157   if (class_fdesc == NULL) {
158     return -1;
159   }
160
161   jfieldID field_fd = env->GetFieldID(class_fdesc, "fd", "I");
162   if (field_fd == NULL) {
163     return -1;
164   }
165
166   const int fd = env->GetIntField(jfd, field_fd);
167
168   void *p = env->GetDirectBufferAddress(byteBuf);
169   if (p == NULL) {
170     return -1;
171   }
172
173   size_t size = (size_t) env->GetDirectBufferCapacity(byteBuf);
174   if (size <= 0) {
175     return -1;
176   }
177
178   size_t numBytesRead = pread(fd, p, (size_t) size, (off_t) pos);
179   if (numBytesRead == -1) {
180     jclass class_ioex = env->FindClass("java/io/IOException");
181     if (class_ioex == NULL) {
182       return -1;
183     }
184
185     env->ThrowNew(class_ioex, strerror(errno));
186     return -1;
187   }
188
189   return (jlong) numBytesRead;
190 }
191
192 /*
193  * Class:     org_apache_lucene_store_NativePosixUtil
194  * Method:    posix_madvise
195  * Signature: (Ljava/nio/ByteBuffer;I)I
196  */
197 extern "C"
198 JNIEXPORT jint JNICALL Java_org_apache_lucene_store_NativePosixUtil_posix_1madvise(JNIEnv *env, jclass _ignore, jobject buffer, jint advice) {
199   void *p = env->GetDirectBufferAddress(buffer);
200   if (p == NULL) {
201     return -1;
202   }
203
204   size_t size = (size_t) env->GetDirectBufferCapacity(buffer);
205   if (size <= 0) {
206     return -1;
207   }
208
209   int page = getpagesize();
210
211   // round start down to start of page
212   long long start = (long long) p;
213   start = start & (~(page-1));
214
215   // round end up to start of page
216   long long end = start + size;
217   end = (end + page-1)&(~(page-1));
218   size = (end-start);
219
220   int osAdvice;
221   switch(advice) {
222   case 0:
223     osAdvice = POSIX_MADV_NORMAL;
224     break;
225   case 1:
226     osAdvice = POSIX_MADV_SEQUENTIAL;
227     break;
228   case 2:
229     osAdvice = POSIX_MADV_RANDOM;
230     break;
231   case 3:
232     osAdvice = POSIX_MADV_WILLNEED;
233     break;
234   case 4:
235     osAdvice = POSIX_MADV_DONTNEED;
236     break;
237   case 5:
238     return -1;
239     break;
240   }
241
242   //printf("DO posix_madvise: %lx %d\n", p, size);fflush(stdout);
243
244   if (posix_madvise((void *) start, size, osAdvice) != 0) {
245     jclass class_ioex = env->FindClass("java/io/IOException");
246     if (class_ioex == NULL) {
247       return -1;
248     }
249
250     env->ThrowNew(class_ioex, strerror(errno));
251     return -1;
252   }
253   
254   return 0;
255 }
256
257
258 /*
259  * Class:     org_apache_lucene_store_NativePosixUtil
260  * Method:    madvise
261  * Signature: (Ljava/nio/ByteBuffer;I)I
262  */
263 extern "C"
264 JNIEXPORT jint JNICALL Java_org_apache_lucene_store_NativePosixUtil_madvise(JNIEnv *env, jclass _ignore, jobject buffer, jint advice) {
265   void *p = env->GetDirectBufferAddress(buffer);
266   if (p == NULL) {
267     return -1;
268   }
269
270   size_t size = (size_t) env->GetDirectBufferCapacity(buffer);
271   if (size <= 0) {
272     return -1;
273   }
274
275   int page = getpagesize();
276
277   // round start down to start of page
278   long long start = (long long) p;
279   start = start & (~(page-1));
280
281   // round end up to start of page
282   long long end = start + size;
283   end = (end + page-1)&(~(page-1));
284   size = (end-start);
285
286   int osAdvice;
287   switch(advice) {
288   case 0:
289     osAdvice = MADV_NORMAL;
290     break;
291   case 1:
292     osAdvice = MADV_SEQUENTIAL;
293     break;
294   case 2:
295     osAdvice = MADV_RANDOM;
296     break;
297   case 3:
298     osAdvice = MADV_WILLNEED;
299     break;
300   case 4:
301     osAdvice = MADV_DONTNEED;
302     break;
303   case 5:
304     return -1;
305     break;
306   }
307
308
309   //printf("DO madvise: page=%d p=0x%lx 0x%lx size=0x%lx\n", page, p, start, size);fflush(stdout);
310
311   if (madvise((void *) start, size, osAdvice) != 0) {
312     jclass class_ioex = env->FindClass("java/io/IOException");
313     if (class_ioex == NULL) {
314       return -1;
315     }
316
317     env->ThrowNew(class_ioex, strerror(errno));
318     return -1;
319   }
320   
321   return 0;
322 }