@Override public Value convertPrecision(long precision, boolean force) { if (this.precision <= precision) { return this; } ValueLobDb lob; if (type == CLOB) { if (handler == null) { try { int p = MathUtils.convertLongToInt(precision); String s = IOUtils.readStringAndClose(getReader(), p); byte[] data = s.getBytes(Constants.UTF8); lob = ValueLobDb.createSmallLob(type, data, s.length()); } catch (IOException e) { throw DbException.convertIOException(e, null); } } else { lob = ValueLobDb.createTempClob(getReader(), precision, handler); } } else { if (handler == null) { try { int p = MathUtils.convertLongToInt(precision); byte[] data = IOUtils.readBytesAndClose(getInputStream(), p); lob = ValueLobDb.createSmallLob(type, data, data.length); } catch (IOException e) { throw DbException.convertIOException(e, null); } } else { lob = ValueLobDb.createTempBlob(getInputStream(), precision, handler); } } return lob; }
/** * Create a new random xid. * * @return the new object */ public static SimpleXid createRandom() { int formatId = next.getAndIncrement(); byte[] bq = new byte[MAXBQUALSIZE]; MathUtils.randomBytes(bq); byte[] gt = new byte[MAXGTRIDSIZE]; MathUtils.randomBytes(gt); return new SimpleXid(formatId, bq, gt); }
private void init() throws IOException { if (xts != null) { return; } this.size = base.size() - HEADER_LENGTH; boolean newFile = size < 0; byte[] salt; if (newFile) { byte[] header = Arrays.copyOf(HEADER, BLOCK_SIZE); salt = MathUtils.secureRandomBytes(SALT_LENGTH); System.arraycopy(salt, 0, header, SALT_POS, salt.length); DataUtils.writeFully(base, 0, ByteBuffer.wrap(header)); size = 0; } else { salt = new byte[SALT_LENGTH]; DataUtils.readFully(base, SALT_POS, ByteBuffer.wrap(salt)); if ((size & BLOCK_SIZE_MASK) != 0) { size -= BLOCK_SIZE; } } AES cipher = new AES(); cipher.setKey(SHA256.getPBKDF2(encryptionKey, salt, HASH_ITERATIONS, 16)); encryptionKey = null; xts = new XTS(cipher); }
/** * Fill up the buffer with empty space and an (initially empty) checksum until the size is a * multiple of Constants.FILE_BLOCK_SIZE. */ public void fillAligned() { // 0..6 > 8, 7..14 > 16, 15..22 > 24, ... int len = MathUtils.roundUpInt(pos + 2, Constants.FILE_BLOCK_SIZE); pos = len; if (data.length < len) { checkCapacity(len - data.length); } }
/** * Returns the parameter precision. The value 0 is returned if the precision is not known. * * @param param the column index (1,2,...) * @return the precision */ public int getPrecision(int param) throws SQLException { try { debugCodeCall("getPrecision", param); ParameterInterface p = getParameter(param); return MathUtils.convertLongToInt(p.getPrecision()); } catch (Exception e) { throw logAndConvert(e); } }
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 because // inplace could be Integer.MAX_VALUE 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; }
/** * Compare the positions of two rows. * * @param rowData the first row * @param compare the second row * @return 0 if both rows are equal, -1 if the first row is smaller, otherwise 1 */ int compareKeys(SearchRow rowData, SearchRow compare) { long k1 = rowData.getKey(); long k2 = compare.getKey(); if (k1 == k2) { if (isMultiVersion) { int v1 = rowData.getVersion(); int v2 = compare.getVersion(); return MathUtils.compareInt(v2, v1); } return 0; } return k1 > k2 ? 1 : -1; }
private void changeLength(long len) { length = len; len = MathUtils.roundUpLong(len, BLOCK_SIZE); int blocks = (int) (len >>> BLOCK_SIZE_SHIFT); if (blocks != data.length) { ByteBuffer[] n = new ByteBuffer[blocks]; System.arraycopy(data, 0, n, 0, Math.min(data.length, n.length)); for (int i = data.length; i < blocks; i++) { n[i] = COMPRESSED_EMPTY_BLOCK; } data = n; } }
/** * Truncate the file. * * @param newLength the new length */ void truncate(long newLength) { changeLength(newLength); long end = MathUtils.roundUpLong(newLength, BLOCK_SIZE); if (end != newLength) { int lastPage = (int) (newLength >>> BLOCK_SIZE_SHIFT); expand(data, lastPage); ByteBuffer d = data[lastPage]; for (int i = (int) (newLength & BLOCK_SIZE_MASK); i < BLOCK_SIZE; i++) { d.put(i, (byte) 0); } if (compress) { compressLater(data, lastPage); } } }
protected int compareSecure(Value o, CompareMode mode) { return MathUtils.compareLong(nanos, ((ValueTime) o).nanos); }
@Override public boolean next() { synchronized (sync) { if (SysProperties.CHECK && end) { DbException.throwInternalError(); } while (true) { if (needNewDelta) { loadNext(false); needNewDelta = false; } if (needNewBase) { loadNext(true); needNewBase = false; } if (deltaRow == null) { if (baseRow == null) { end = true; return false; } onBase = true; needNewBase = true; return true; } int sessionId = deltaRow.getSessionId(); boolean isThisSession = sessionId == session.getId(); boolean isDeleted = deltaRow.isDeleted(); if (isThisSession && isDeleted) { needNewDelta = true; continue; } if (baseRow == null) { if (isDeleted) { if (isThisSession) { end = true; return false; } // the row was deleted by another session: return it onBase = false; needNewDelta = true; return true; } DbException.throwInternalError(); } int compare = index.compareRows(deltaRow, baseRow); if (compare == 0) { // can't use compareKeys because the // version would be compared as well long k1 = deltaRow.getKey(); long k2 = baseRow.getKey(); compare = MathUtils.compareLong(k1, k2); } if (compare == 0) { if (isDeleted) { if (isThisSession) { DbException.throwInternalError(); } // another session updated the row } else { if (isThisSession) { onBase = false; needNewBase = true; needNewDelta = true; return true; } // another session inserted the row: ignore needNewBase = true; needNewDelta = true; continue; } } if (compare > 0) { onBase = true; needNewBase = true; return true; } onBase = false; needNewDelta = true; return true; } } }
/** * Get the next temporary file name part (the part in the middle). * * @param newRandom if the random part of the filename should change * @return the file name part */ protected static synchronized String getNextTempFileNamePart(boolean newRandom) { if (newRandom || tempRandom == null) { tempRandom = MathUtils.randomInt(Integer.MAX_VALUE) + "."; } return tempRandom + tempSequence++; }
public boolean next() { synchronized (this.sync) { if ((SysProperties.CHECK) && (this.end)) { DbException.throwInternalError(); } int compare; for (; ; ) { if (this.needNewDelta) { loadNext(false); this.needNewDelta = false; } if (this.needNewBase) { loadNext(true); this.needNewBase = false; } if (this.deltaRow == null) { if (this.baseRow == null) { this.end = true; return false; } this.onBase = true; this.needNewBase = true; return true; } int sessionId = this.deltaRow.getSessionId(); boolean isThisSession = sessionId == this.session.getId(); boolean isDeleted = this.deltaRow.isDeleted(); if ((isThisSession) && (isDeleted)) { this.needNewDelta = true; } else { if (this.baseRow == null) { if (isDeleted) { if (isThisSession) { this.end = true; return false; } this.onBase = false; this.needNewDelta = true; return true; } DbException.throwInternalError(); } compare = this.index.compareRows(this.deltaRow, this.baseRow); if (compare == 0) { long k1 = this.deltaRow.getKey(); long k2 = this.baseRow.getKey(); compare = MathUtils.compareLong(k1, k2); } if (compare != 0) { break; } if (isDeleted) { if (!isThisSession) { break; } DbException.throwInternalError(); break; } if (isThisSession) { this.onBase = false; this.needNewBase = true; this.needNewDelta = true; return true; } this.needNewBase = true; this.needNewDelta = true; } } if (compare > 0) { this.onBase = true; this.needNewBase = true; return true; } this.onBase = false; this.needNewDelta = true; return true; } }
@Override public int getDisplaySize() { return MathUtils.convertLongToInt(getPrecision()); }
@Override protected int compareSecure(Value o, CompareMode mode) { ValueByte v = (ValueByte) o; return MathUtils.compareInt(value, v.value); }
private void connectServer(ConnectionInfo ci) { String name = ci.getName(); if (name.startsWith("//")) { name = name.substring("//".length()); } int idx = name.indexOf('/'); if (idx < 0) { throw ci.getFormatException(); } databaseName = name.substring(idx + 1); String server = name.substring(0, idx); traceSystem = new TraceSystem(null); String traceLevelFile = ci.getProperty(SetTypes.TRACE_LEVEL_FILE, null); if (traceLevelFile != null) { int level = Integer.parseInt(traceLevelFile); String prefix = getFilePrefix(SysProperties.CLIENT_TRACE_DIRECTORY); try { traceSystem.setLevelFile(level); if (level > 0 && level < 4) { String file = FileUtils.createTempFile(prefix, Constants.SUFFIX_TRACE_FILE, false, false); traceSystem.setFileName(file); } } catch (IOException e) { throw DbException.convertIOException(e, prefix); } } String traceLevelSystemOut = ci.getProperty(SetTypes.TRACE_LEVEL_SYSTEM_OUT, null); if (traceLevelSystemOut != null) { int level = Integer.parseInt(traceLevelSystemOut); traceSystem.setLevelSystemOut(level); } trace = traceSystem.getTrace(Trace.JDBC); String serverList = null; if (server.indexOf(',') >= 0) { serverList = StringUtils.quoteStringSQL(server); ci.setProperty("CLUSTER", Constants.CLUSTERING_ENABLED); } autoReconnect = Boolean.parseBoolean(ci.getProperty("AUTO_RECONNECT", "false")); // AUTO_SERVER implies AUTO_RECONNECT boolean autoServer = Boolean.parseBoolean(ci.getProperty("AUTO_SERVER", "false")); if (autoServer && serverList != null) { throw DbException.getUnsupportedException("autoServer && serverList != null"); } autoReconnect |= autoServer; if (autoReconnect) { String className = ci.getProperty("DATABASE_EVENT_LISTENER"); if (className != null) { className = StringUtils.trim(className, true, true, "'"); try { eventListener = (DatabaseEventListener) JdbcUtils.loadUserClass(className).newInstance(); } catch (Throwable e) { throw DbException.convert(e); } } } cipher = ci.getProperty("CIPHER"); if (cipher != null) { fileEncryptionKey = MathUtils.secureRandomBytes(32); } String[] servers = StringUtils.arraySplit(server, ',', true); int len = servers.length; transferList.clear(); sessionId = StringUtils.convertBytesToHex(MathUtils.secureRandomBytes(32)); // TODO cluster: support more than 2 connections boolean switchOffCluster = false; try { for (int i = 0; i < len; i++) { String s = servers[i]; try { Transfer trans = initTransfer(ci, databaseName, s); transferList.add(trans); } catch (IOException e) { if (len == 1) { throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, e, e + ": " + s); } switchOffCluster = true; } } checkClosed(); if (switchOffCluster) { switchOffCluster(); } checkClusterDisableAutoCommit(serverList); } catch (DbException e) { traceSystem.close(); throw e; } }