コード例 #1
0
ファイル: ValueLob.java プロジェクト: zhoupan/Lealone
 /**
  * Create a BLOB value from a stream.
  *
  * @param in the input stream
  * @param length the number of characters to read, or -1 for no limit
  * @param handler the data handler
  * @return the lob value
  */
 private static ValueLob createBlob(InputStream in, long length, DataHandler handler) {
   try {
     if (handler == null) {
       byte[] data = IOUtils.readBytesAndClose(in, (int) length);
       return createSmallLob(Value.BLOB, data);
     }
     long remaining = Long.MAX_VALUE;
     boolean compress = handler.getLobCompressionAlgorithm(Value.BLOB) != null;
     if (length >= 0 && length < remaining) {
       remaining = length;
     }
     int len = getBufferSize(handler, compress, remaining);
     byte[] buff;
     if (len >= Integer.MAX_VALUE) {
       buff = IOUtils.readBytesAndClose(in, -1);
       len = buff.length;
     } else {
       buff = DataUtils.newBytes(len);
       len = IOUtils.readFully(in, buff, len);
     }
     if (len <= handler.getMaxLengthInplaceLob()) {
       byte[] small = DataUtils.newBytes(len);
       System.arraycopy(buff, 0, small, 0, len);
       return ValueLob.createSmallLob(Value.BLOB, small);
     }
     ValueLob lob = new ValueLob(Value.BLOB, null);
     lob.createFromStream(buff, len, in, remaining, handler);
     return lob;
   } catch (IOException e) {
     throw DbException.convertIOException(e, null);
   }
 }
コード例 #2
0
ファイル: ValueLob.java プロジェクト: zhoupan/Lealone
 /**
  * Create a CLOB value from a stream.
  *
  * @param in the reader
  * @param length the number of characters to read, or -1 for no limit
  * @param handler the data handler
  * @return the lob value
  */
 private static ValueLob createClob(Reader in, long length, DataHandler handler) {
   try {
     if (handler == null) {
       String s = IOUtils.readStringAndClose(in, (int) length);
       return createSmallLob(Value.CLOB, s.getBytes(Constants.UTF8));
     }
     boolean compress = handler.getLobCompressionAlgorithm(Value.CLOB) != null;
     long remaining = Long.MAX_VALUE;
     if (length >= 0 && length < remaining) {
       remaining = length;
     }
     int len = getBufferSize(handler, compress, remaining);
     char[] buff;
     if (len >= Integer.MAX_VALUE) {
       String data = IOUtils.readStringAndClose(in, -1);
       buff = data.toCharArray();
       len = buff.length;
     } else {
       buff = new char[len];
       len = IOUtils.readFully(in, buff, len);
     }
     if (len <= handler.getMaxLengthInplaceLob()) {
       byte[] small = new String(buff, 0, len).getBytes(Constants.UTF8);
       return ValueLob.createSmallLob(Value.CLOB, small);
     }
     ValueLob lob = new ValueLob(Value.CLOB, null);
     lob.createFromReader(buff, len, in, remaining, handler);
     return lob;
   } catch (IOException e) {
     throw DbException.convertIOException(e, null);
   }
 }
コード例 #3
0
ファイル: ValueLob.java プロジェクト: zhoupan/Lealone
 private static synchronized void deleteFile(DataHandler handler, String fileName) {
   // synchronize on the database, to avoid concurrent temp file creation /
   // deletion / backup
   synchronized (handler.getLobSyncObject()) {
     FileUtils.delete(fileName);
   }
 }
コード例 #4
0
ファイル: ValueLob.java プロジェクト: zhoupan/Lealone
 private static void invalidateFileList(DataHandler h, String dir) {
   SmallLRUCache<String, String[]> cache = h.getLobFileListCache();
   if (cache != null) {
     synchronized (cache) {
       cache.remove(dir);
     }
   }
 }
コード例 #5
0
ファイル: ValueLob.java プロジェクト: zhoupan/Lealone
 private static void copyFileTo(DataHandler h, String sourceFileName, String targetFileName) {
   synchronized (h.getLobSyncObject()) {
     try {
       IOUtils.copyFiles(sourceFileName, targetFileName);
     } catch (IOException e) {
       throw DbException.convertIOException(e, null);
     }
   }
 }
コード例 #6
0
ファイル: ValueLob.java プロジェクト: zhoupan/Lealone
 private static String getFileName(DataHandler handler, int tableId, int objectId) {
   if (SysProperties.CHECK && tableId == 0 && objectId == 0) {
     DbException.throwInternalError("0 LOB");
   }
   String table = tableId < 0 ? ".temp" : ".t" + tableId;
   return getFileNamePrefix(handler.getDatabasePath(), objectId)
       + table
       + Constants.SUFFIX_LOB_FILE;
 }
コード例 #7
0
ファイル: ValueLob.java プロジェクト: zhoupan/Lealone
 /**
  * Store the lob data to a file if the size of the buffer is larger than the maximum size for an
  * in-place lob.
  *
  * @param h the data handler
  */
 public void convertToFileIfRequired(DataHandler h) {
   try {
     if (small != null && small.length > h.getMaxLengthInplaceLob()) {
       boolean compress = h.getLobCompressionAlgorithm(type) != null;
       int len = getBufferSize(h, compress, Long.MAX_VALUE);
       int tabId = tableId;
       if (type == Value.BLOB) {
         createFromStream(DataUtils.newBytes(len), 0, getInputStream(), Long.MAX_VALUE, h);
       } else {
         createFromReader(new char[len], 0, getReader(), Long.MAX_VALUE, h);
       }
       Value v2 = link(h, tabId);
       if (SysProperties.CHECK && v2 != this) {
         DbException.throwInternalError();
       }
     }
   } catch (IOException e) {
     throw DbException.convertIOException(e, null);
   }
 }
コード例 #8
0
ファイル: ValueLob.java プロジェクト: zhoupan/Lealone
 @Override
 public InputStream getInputStream() {
   if (fileName == null) {
     return new ByteArrayInputStream(small);
   }
   FileStore store = handler.openFile(fileName, "r", true);
   boolean alwaysClose = SysProperties.LOB_CLOSE_BETWEEN_READS;
   return new BufferedInputStream(
       new FileStoreInputStream(store, handler, compressed, alwaysClose),
       Constants.IO_BUFFER_SIZE);
 }
コード例 #9
0
ファイル: ValueLob.java プロジェクト: zhoupan/Lealone
 private FileStoreOutputStream initLarge(DataHandler h) {
   this.handler = h;
   this.tableId = 0;
   this.linked = false;
   this.precision = 0;
   this.small = null;
   this.hash = 0;
   String compressionAlgorithm = h.getLobCompressionAlgorithm(type);
   this.compressed = compressionAlgorithm != null;
   synchronized (h) {
     String path = h.getDatabasePath();
     if ((path != null) && (path.length() == 0)) {
       path =
           new File(Utils.getProperty("java.io.tmpdir", "."), SysProperties.PREFIX_TEMP_FILE)
               .getAbsolutePath();
     }
     objectId = getNewObjectId(h);
     fileName = getFileNamePrefix(path, objectId) + Constants.SUFFIX_TEMP_FILE;
     tempFile = h.openFile(fileName, "rw", false);
     tempFile.autoDelete();
   }
   FileStoreOutputStream out = new FileStoreOutputStream(tempFile, h, compressionAlgorithm);
   return out;
 }
コード例 #10
0
ファイル: ValueLob.java プロジェクト: zhoupan/Lealone
 private 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;
 }
コード例 #11
0
ファイル: ValueLob.java プロジェクト: zhoupan/Lealone
 private static int getBufferSize(DataHandler handler, boolean compress, long remaining) {
   if (remaining < 0 || remaining > Integer.MAX_VALUE) {
     remaining = Integer.MAX_VALUE;
   }
   int inplace = handler.getMaxLengthInplaceLob();
   long m = compress ? Constants.IO_BUFFER_SIZE_COMPRESS : Constants.IO_BUFFER_SIZE;
   if (m < remaining && m <= inplace) {
     // using "1L" to force long arithmetic
     m = Math.min(remaining, inplace + 1L);
     // the buffer size must be bigger than the inplace lob, otherwise we
     // can't know if it must be stored in-place or not
     m = MathUtils.roundUpLong(m, Constants.IO_BUFFER_SIZE);
   }
   m = Math.min(remaining, m);
   m = MathUtils.convertLongToInt(m);
   if (m < 0) {
     m = Integer.MAX_VALUE;
   }
   return (int) m;
 }
コード例 #12
0
ファイル: ValueLob.java プロジェクト: zhoupan/Lealone
 private void createFromStream(byte[] buff, int len, InputStream in, long remaining, DataHandler h)
     throws IOException {
   FileStoreOutputStream out = initLarge(h);
   boolean compress = h.getLobCompressionAlgorithm(Value.BLOB) != null;
   try {
     while (true) {
       precision += len;
       out.write(buff, 0, len);
       remaining -= len;
       if (remaining <= 0) {
         break;
       }
       len = getBufferSize(h, compress, remaining);
       len = IOUtils.readFully(in, buff, len);
       if (len <= 0) {
         break;
       }
     }
   } finally {
     out.close();
   }
 }
コード例 #13
0
ファイル: ValueLob.java プロジェクト: zhoupan/Lealone
 private void createFromReader(char[] buff, int len, Reader in, long remaining, DataHandler h)
     throws IOException {
   FileStoreOutputStream out = initLarge(h);
   boolean compress = h.getLobCompressionAlgorithm(Value.CLOB) != null;
   try {
     while (true) {
       precision += len;
       byte[] b = new String(buff, 0, len).getBytes(Constants.UTF8);
       out.write(b, 0, b.length);
       remaining -= len;
       if (remaining <= 0) {
         break;
       }
       len = getBufferSize(h, compress, remaining);
       len = IOUtils.readFully(in, buff, len);
       if (len == 0) {
         break;
       }
     }
   } finally {
     out.close();
   }
 }
コード例 #14
0
ファイル: ValueLob.java プロジェクト: zhoupan/Lealone
 private static synchronized void renameFile(DataHandler handler, String oldName, String newName) {
   synchronized (handler.getLobSyncObject()) {
     FileUtils.move(oldName, newName);
   }
 }
コード例 #15
0
ファイル: ValueLob.java プロジェクト: zhoupan/Lealone
 private 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);
     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;
 }