001: package org.apache.lucene.store.db;
002:
003: /**
004: * Licensed to the Apache Software Foundation (ASF) under one or more
005: * contributor license agreements. See the NOTICE file distributed with
006: * this work for additional information regarding copyright ownership.
007: * The ASF licenses this file to You under the Apache License, Version 2.0
008: * (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: */
019:
020: import java.io.IOException;
021: import java.io.ByteArrayOutputStream;
022: import java.io.DataOutputStream;
023: import java.io.ByteArrayInputStream;
024: import java.io.DataInputStream;
025: import java.util.Random;
026:
027: import com.sleepycat.db.DatabaseEntry;
028: import com.sleepycat.db.internal.DbConstants;
029: import com.sleepycat.db.internal.Dbc;
030: import com.sleepycat.db.internal.Db;
031: import com.sleepycat.db.internal.DbTxn;
032: import com.sleepycat.db.DatabaseException;
033:
034: /**
035: * @author Andi Vajda
036: */
037:
038: public class File extends Object {
039:
040: static protected Random random = new Random();
041:
042: protected DatabaseEntry key, data;
043: protected long length, timeModified;
044: protected String name;
045: protected byte[] uuid;
046:
047: protected File(String name) throws IOException {
048: setName(name);
049:
050: data = new DatabaseEntry(new byte[32]);
051: data.setUserBuffer(data.getSize(), true);
052: }
053:
054: protected File(DbDirectory directory, String name, boolean create)
055: throws IOException {
056: this (name);
057:
058: if (!exists(directory)) {
059: if (!create)
060: throw new IOException("File does not exist: " + name);
061: else {
062: DatabaseEntry key = new DatabaseEntry(new byte[24]);
063: DatabaseEntry data = new DatabaseEntry((byte[]) null);
064: Db blocks = directory.blocks;
065: DbTxn txn = directory.txn;
066: int flags = directory.flags;
067:
068: key.setUserBuffer(24, true);
069: data.setPartial(true);
070:
071: uuid = new byte[16];
072:
073: try {
074: do {
075: /* generate a v.4 random-uuid unique to this db */
076: random.nextBytes(uuid);
077: uuid[6] = (byte) ((byte) 0x40 | (uuid[6] & (byte) 0x0f));
078: uuid[8] = (byte) ((byte) 0x80 | (uuid[8] & (byte) 0x3f));
079: System.arraycopy(uuid, 0, key.getData(), 0, 16);
080: } while (blocks.get(txn, key, data, flags) != DbConstants.DB_NOTFOUND);
081: } catch (DatabaseException e) {
082: throw new IOException(e.getMessage());
083: }
084: }
085: } else if (create)
086: length = 0L;
087: }
088:
089: protected String getName() {
090: return name;
091: }
092:
093: private void setName(String name) throws IOException {
094: ByteArrayOutputStream buffer = new ByteArrayOutputStream(128);
095: DataOutputStream out = new DataOutputStream(buffer);
096:
097: out.writeUTF(name);
098: out.close();
099:
100: key = new DatabaseEntry(buffer.toByteArray());
101: key.setUserBuffer(key.getSize(), true);
102:
103: this .name = name;
104: }
105:
106: protected byte[] getKey() throws IOException {
107: if (uuid == null)
108: throw new IOException("Uninitialized file");
109:
110: return uuid;
111: }
112:
113: protected long getLength() {
114: return length;
115: }
116:
117: protected long getTimeModified() {
118: return timeModified;
119: }
120:
121: protected boolean exists(DbDirectory directory) throws IOException {
122: Db files = directory.files;
123: DbTxn txn = directory.txn;
124: int flags = directory.flags;
125:
126: try {
127: if (files.get(txn, key, data, flags) == DbConstants.DB_NOTFOUND)
128: return false;
129: } catch (DatabaseException e) {
130: throw new IOException(e.getMessage());
131: }
132:
133: byte[] bytes = data.getData();
134: ByteArrayInputStream buffer = new ByteArrayInputStream(bytes);
135: DataInputStream in = new DataInputStream(buffer);
136:
137: length = in.readLong();
138: timeModified = in.readLong();
139: in.close();
140:
141: uuid = new byte[16];
142: System.arraycopy(bytes, 16, uuid, 0, 16);
143:
144: return true;
145: }
146:
147: protected void modify(DbDirectory directory, long length,
148: long timeModified) throws IOException {
149: ByteArrayOutputStream buffer = new ByteArrayOutputStream(32);
150: DataOutputStream out = new DataOutputStream(buffer);
151: Db files = directory.files;
152: DbTxn txn = directory.txn;
153:
154: out.writeLong(length);
155: out.writeLong(timeModified);
156: out.write(getKey());
157: out.close();
158:
159: System
160: .arraycopy(buffer.toByteArray(), 0, data.getData(), 0,
161: 32);
162:
163: try {
164: files.put(txn, key, data, 0);
165: } catch (DatabaseException e) {
166: throw new IOException(e.getMessage());
167: }
168:
169: this .length = length;
170: this .timeModified = timeModified;
171: }
172:
173: protected void delete(DbDirectory directory) throws IOException {
174: if (!exists(directory))
175: throw new IOException("File does not exist: " + getName());
176:
177: Dbc cursor = null;
178:
179: try {
180: try {
181: byte[] bytes = getKey();
182: int ulen = bytes.length + 8;
183: byte[] cursorBytes = new byte[ulen];
184: DatabaseEntry cursorKey = new DatabaseEntry(cursorBytes);
185: DatabaseEntry cursorData = new DatabaseEntry(
186: (byte[]) null);
187: Db files = directory.files;
188: Db blocks = directory.blocks;
189: DbTxn txn = directory.txn;
190: int flags = directory.flags;
191:
192: System
193: .arraycopy(bytes, 0, cursorBytes, 0,
194: bytes.length);
195: cursorKey.setUserBuffer(ulen, true);
196: cursorData.setPartial(true);
197:
198: cursor = blocks.cursor(txn, flags);
199:
200: if (cursor.get(cursorKey, cursorData,
201: DbConstants.DB_SET_RANGE | flags) != DbConstants.DB_NOTFOUND) {
202: cursor.del(0);
203:
204: outer: while (cursor.get(cursorKey, cursorData,
205: DbConstants.DB_NEXT | flags) != DbConstants.DB_NOTFOUND) {
206: for (int i = 0; i < bytes.length; i++)
207: if (bytes[i] != cursorBytes[i])
208: break outer;
209:
210: cursor.del(0);
211: }
212: }
213:
214: files.del(txn, key, 0);
215: } finally {
216: if (cursor != null)
217: cursor.close();
218: }
219: } catch (DatabaseException e) {
220: throw new IOException(e.getMessage());
221: }
222: }
223:
224: protected void rename(DbDirectory directory, String name)
225: throws IOException {
226: if (!exists(directory))
227: throw new IOException("File does not exist: " + getName());
228:
229: File newFile = new File(name);
230:
231: if (newFile.exists(directory))
232: newFile.delete(directory);
233:
234: try {
235: Db files = directory.files;
236: DbTxn txn = directory.txn;
237:
238: files.del(txn, key, 0);
239: setName(name);
240: files.put(txn, key, data, 0);
241: } catch (DatabaseException e) {
242: throw new IOException(e.getMessage());
243: }
244: }
245: }
|