/* * 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. */ package my.test; import java.io.File; import org.h2.engine.Constants; import org.h2.engine.SysProperties; import org.h2.store.DataHandler; import org.h2.store.fs.FileUtils; import org.h2.util.MathUtils; import org.h2.util.SmallLRUCache; import org.h2.util.Utils; import org.h2.value.Value; import org.h2.value.ValueLob; public class ValueLobTest { public static void main2(String[] args) { System.setProperty("h2.lobInDatabase", "false"); System.setProperty("h2.lobClientMaxSizeMemory", "1024"); System.setProperty("java.io.tmpdir", "E:\\H2\\tmp"); System.setProperty("h2.lobFilesPerDirectory", "3"); // MyDataHandler handler = new MyDataHandler(); // int length = 2049; // byte[] bytes = new byte[length]; // for (int i = 0; i < length; i++) // bytes[i] = (byte) i; // // ByteArrayInputStream in = new ByteArrayInputStream(bytes); // // BufferedReader reader = new BufferedReader(new InputStreamReader(in)); // // ValueLob.createSmallLob(Value.BLOB, bytes); // ValueLob.createSmallLob(Value.CLOB, bytes); // ValueLob.createBlob(in, length, handler); // ValueLob.createClob(reader, length, handler); String p = getFileNamePrefix("a", 1); System.out.println(p); p = getFileNamePrefix("a", 2); System.out.println(p); p = getFileNamePrefix("a", 3); System.out.println(p); p = getFileNamePrefix("a", 5); System.out.println(p); p = getFileNamePrefix("a", 10); System.out.println(p); p = getFileNamePrefix("a", 27); System.out.println(p); } public static void main(String[] args) { System.setProperty("h2.lobInDatabase", "false"); System.setProperty("h2.lobClientMaxSizeMemory", "1024"); System.setProperty("java.io.tmpdir", "E:\\H2\\tmp"); // 要在初始SysProperties之前设置,因为LOB_FILES_PER_DIRECTORY是一个static final字段 System.setProperty("h2.lobFilesPerDirectory", "5"); MyDataHandler handler = new MyDataHandler(); String path = handler.getDatabasePath(); if ((path != null) && (path.length() == 0)) { path = new File(Utils.getProperty("java.io.tmpdir", "."), SysProperties.PREFIX_TEMP_FILE).getAbsolutePath(); } // System.setProperty("h2.lobFilesPerDirectory", "5"); //在这里设置不起作用了,SysProperties类中已设成256 // FileUtils.deleteRecursive("E:\\H2\\tmp\\h2.temp.lobs.db",false); for (int i = 0; i < 1; i++) { int objectId = getNewObjectId(handler); String fileName = getFileNamePrefix(path, objectId) + Constants.SUFFIX_TEMP_FILE; System.out.println(fileName); // handler.openFile(fileName, "rw", false); } ValueLob.openLinked(Value.BLOB, handler, 1, 2, 10, true); } static String getFileNamePrefix(String path, int objectId) { String name; int f = objectId % SysProperties.LOB_FILES_PER_DIRECTORY; if (f > 0) { name = SysProperties.FILE_SEPARATOR + objectId; } else { name = ""; } objectId /= SysProperties.LOB_FILES_PER_DIRECTORY; while (objectId > 0) { f = objectId % SysProperties.LOB_FILES_PER_DIRECTORY; name = SysProperties.FILE_SEPARATOR + f + Constants.SUFFIX_LOBS_DIRECTORY + name; objectId /= SysProperties.LOB_FILES_PER_DIRECTORY; } name = FileUtils.toRealPath(path + Constants.SUFFIX_LOBS_DIRECTORY + name); return name; } static int dirCounter; static int getNewObjectId(DataHandler h) { String path = h.getDatabasePath(); if ((path != null) && (path.length() == 0)) { path = new File(Utils.getProperty("java.io.tmpdir", "."), SysProperties.PREFIX_TEMP_FILE).getAbsolutePath(); } int newId = 0; int lobsPerDir = SysProperties.LOB_FILES_PER_DIRECTORY; while (true) { String dir = getFileNamePrefix(path, newId); // System.out.println(dir); System.out.println(newId); String[] list = getFileList(h, dir); int fileCount = 0; boolean[] used = new boolean[lobsPerDir]; for (String name : list) { if (name.endsWith(Constants.SUFFIX_DB_FILE)) { name = FileUtils.getName(name); String n = name.substring(0, name.indexOf('.')); int id; try { id = Integer.parseInt(n); } catch (NumberFormatException e) { id = -1; } if (id > 0) { fileCount++; used[id % lobsPerDir] = true; } } } int fileId = -1; if (fileCount < lobsPerDir) { for (int i = 1; i < lobsPerDir; i++) { if (!used[i]) { fileId = i; break; } } } if (fileId > 0) { newId += fileId; invalidateFileList(h, dir); break; } if (newId > Integer.MAX_VALUE / lobsPerDir) { // this directory path is full: start from zero newId = 0; dirCounter = MathUtils.randomInt(lobsPerDir - 1) * lobsPerDir; } else { // calculate the directory // start with 1 (otherwise we don't know the number of // directories) // it doesn't really matter what directory is used, it might as // well be random // (but that would generate more directories): // int dirId = RandomUtils.nextInt(lobsPerDir - 1) + 1; int dirId = (dirCounter++ / (lobsPerDir - 1)) + 1; newId = newId * lobsPerDir; newId += dirId * lobsPerDir; } } return newId; } static String[] getFileList(DataHandler h, String dir) { SmallLRUCache<String, String[]> cache = h.getLobFileListCache(); String[] list; if (cache == null) { list = FileUtils.newDirectoryStream(dir).toArray(new String[0]); } else { synchronized (cache) { list = cache.get(dir); if (list == null) { list = FileUtils.newDirectoryStream(dir).toArray(new String[0]); cache.put(dir, list); } } } return list; } static void invalidateFileList(DataHandler h, String dir) { SmallLRUCache<String, String[]> cache = h.getLobFileListCache(); if (cache != null) { synchronized (cache) { cache.remove(dir); } } } }