/** * Undo all operations back to the log position of the given savepoint. * * @param name the savepoint name */ public void rollbackToSavepoint(String name) { checkCommitRollback(); if (savepoints == null) { throw DbException.get(ErrorCode.SAVEPOINT_IS_INVALID_1, name); } Integer savepointIndex = savepoints.get(name); if (savepointIndex == null) { throw DbException.get(ErrorCode.SAVEPOINT_IS_INVALID_1, name); } int i = savepointIndex.intValue(); rollbackTo(i, false); }
/** * Automatically re-connect if necessary and if configured to do so. * * @param count the retry count index * @return true if reconnected */ private boolean autoReconnect(int count) { if (!isClosed()) { return false; } if (!autoReconnect) { return false; } if (!cluster && !autoCommit) { return false; } if (count > SysProperties.MAX_RECONNECT) { return false; } lastReconnect++; while (true) { try { embedded = connectEmbeddedOrServer(false); break; } catch (DbException e) { if (e.getErrorCode() != ErrorCode.DATABASE_IS_IN_EXCLUSIVE_MODE) { throw e; } // exclusive mode: re-try endlessly try { Thread.sleep(500); } catch (Exception e2) { // ignore } } } if (embedded == this) { // connected to a server somewhere else embedded = null; } else { // opened an embedded connection now - // must connect to this database in server mode // unfortunately connectEmbeddedOrServer(true); } recreateSessionState(); if (eventListener != null) { eventListener.setProgress( DatabaseEventListener.STATE_RECONNECTED, databaseName, count, SysProperties.MAX_RECONNECT); } return true; }
public synchronized void checkTransfers() { if (transferList != null) { for (int i = 0; i < transferList.size(); i++) { Transfer transfer = transferList.get(i); try { if (transfer.available() > 0) throw DbException.throwInternalError( "the transfer available bytes was " + transfer.available()); } catch (IOException e) { throw DbException.convert(e); } } } }
/** * Get the local host address as a string. For performance, the result is cached for one second. * * @return the local host address */ public static synchronized String getLocalAddress() { long now = System.currentTimeMillis(); if (cachedLocalAddress != null) { if (cachedLocalAddressTime + CACHE_MILLIS > now) { return cachedLocalAddress; } } InetAddress bind = null; boolean useLocalhost = false; try { bind = getBindAddress(); if (bind == null) { useLocalhost = true; } } catch (UnknownHostException e) { // ignore } if (useLocalhost) { try { bind = InetAddress.getLocalHost(); } catch (UnknownHostException e) { throw DbException.convert(e); } } String address = bind == null ? "localhost" : getHostAddress(bind); if (address.equals("127.0.0.1")) { address = "localhost"; } cachedLocalAddress = address; cachedLocalAddressTime = now; return address; }
private static ServerSocket createServerSocketTry(int port, boolean ssl) { try { InetAddress bindAddress = getBindAddress(); if (ssl) { return CipherFactory.createServerSocket(port, bindAddress); } if (bindAddress == null) { return new ServerSocket(port); } return new ServerSocket(port, 0, bindAddress); } catch (BindException be) { throw DbException.get(ErrorCode.EXCEPTION_OPENING_PORT_2, be, "" + port, be.toString()); } catch (IOException e) { throw DbException.convertIOException(e, "port: " + port + " ssl: " + ssl); } }
/** * Add an undo log entry to this session. * * @param table the table * @param operation the operation type (see {@link UndoLogRecord}) * @param row the row */ public void log(Table table, short operation, Row row) { if (undoLogEnabled) { UndoLogRecord log = new UndoLogRecord(table, operation, row); // called _after_ the row was inserted successfully into the table, // otherwise rollback will try to rollback a not-inserted row if (SysProperties.CHECK) { int lockMode = database.getLockMode(); if (lockMode != Constants.LOCK_MODE_OFF && !database.isMultiVersion()) { String tableType = log.getTable().getTableType(); if (locks.indexOf(log.getTable()) < 0 && !Table.TABLE_LINK.equals(tableType) && !Table.EXTERNAL_TABLE_ENGINE.equals(tableType)) { DbException.throwInternalError(); } } } undoLog.add(log); } else { if (database.isMultiVersion()) { // see also UndoLogRecord.commit ArrayList<Index> indexes = table.getIndexes(); for (int i = 0, size = indexes.size(); i < size; i++) { Index index = indexes.get(i); index.commit(operation, row); } row.commit(); } } }
/** * Commit or roll back the given transaction. * * @param transactionName the name of the transaction * @param commit true for commit, false for rollback */ public void setPreparedTransaction(String transactionName, boolean commit) { if (currentTransactionName != null && currentTransactionName.equals(transactionName)) { if (commit) { commit(false); } else { rollback(); } } else { ArrayList<InDoubtTransaction> list = database.getInDoubtTransactions(); int state = commit ? InDoubtTransaction.COMMIT : InDoubtTransaction.ROLLBACK; boolean found = false; if (list != null) { for (InDoubtTransaction p : list) { if (p.getTransaction().equals(transactionName)) { p.setState(state); found = true; break; } } } if (!found) { throw DbException.get(ErrorCode.TRANSACTION_NOT_FOUND_1, transactionName); } } }
public synchronized Command prepareCommand(String sql) { if (closed) { throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, "session closed"); } Command command; if (queryCacheSize > 0) { if (queryCache == null) { queryCache = SmallLRUCache.newInstance(queryCacheSize); } else { command = queryCache.get(sql); if (command != null && command.canReuse()) { command.reuse(); return command; } } } Parser parser = createParser(); command = parser.prepareCommand(sql); if (queryCache != null) { if (command.isCacheable()) { queryCache.put(sql, command); } } return command; }
/** * Add a lock for the given table. The object is unlocked on commit or rollback. * * @param table the table that is locked */ public void addLock(Table table) { if (SysProperties.CHECK) { if (locks.indexOf(table) >= 0) { DbException.throwInternalError(); } } locks.add(table); }
public static void deletePgPortEphemeralNode(ServerName sn, int port, boolean isMaster) { try { ZKUtil.deleteNode( ZooKeeperAdmin.getZooKeeperWatcher(), getPgPortEphemeralNodePath(sn, port, isMaster)); } catch (KeeperException e) { throw DbException.convert(e); } }
Value getMergedValue(Database database, boolean distinct) { if (distinct) { count = 0; groupDistinct(database); } Value v = null; switch (aggregateType) { case Aggregate.COUNT: case Aggregate.COUNT_ALL: v = ValueLong.get(count); break; case Aggregate.SUM: case Aggregate.MIN: case Aggregate.MAX: case Aggregate.BOOL_OR: case Aggregate.BOOL_AND: v = value; break; case Aggregate.AVG: case Aggregate.STDDEV_POP: case Aggregate.STDDEV_SAMP: case Aggregate.VAR_POP: case Aggregate.VAR_SAMP: return value == null ? ValueNull.INSTANCE : value; case Aggregate.SELECTIVITY: if (value != null) { v = divide(value, count); } break; case Aggregate.GROUP_CONCAT: return null; case Aggregate.HISTOGRAM: ValueArray[] values = new ValueArray[distinctValues.size()]; int i = 0; for (Value dv : distinctValues.keys()) { AggregateData d = distinctValues.get(dv); values[i] = ValueArray.get(new Value[] {dv, ValueLong.get(d.count)}); i++; } final CompareMode compareMode = database.getCompareMode(); Arrays.sort( values, new Comparator<ValueArray>() { public int compare(ValueArray v1, ValueArray v2) { Value a1 = v1.getList()[0]; Value a2 = v2.getList()[0]; return a1.compareTo(a2, compareMode); } }); v = ValueArray.get(values); break; default: DbException.throwInternalError("type=" + aggregateType); } return v == null ? ValueNull.INSTANCE : v.convertTo(dataType); }
/** * Remember that the given LOB value must be un-linked (disconnected from the table) at commit. * * @param v the value */ public void unlinkAtCommit(Value v) { if (SysProperties.CHECK && !v.isLinked()) { DbException.throwInternalError(); } if (unlinkLobMap == null) { unlinkLobMap = New.hashMap(); } unlinkLobMap.put(v.toString(), v); }
/** * Add a local temporary index to this session. * * @param index the index to add * @throws DbException if a index with this name already exists */ public void addLocalTempTableIndex(Index index) { if (localTempTableIndexes == null) { localTempTableIndexes = database.newStringMap(); } if (localTempTableIndexes.get(index.getName()) != null) { throw DbException.get(ErrorCode.INDEX_ALREADY_EXISTS_1, index.getSQL()); } localTempTableIndexes.put(index.getName(), index); }
/** * Add a local temporary constraint to this session. * * @param constraint the constraint to add * @throws DbException if a constraint with the same name already exists */ public void addLocalTempTableConstraint(Constraint constraint) { if (localTempTableConstraints == null) { localTempTableConstraints = database.newStringMap(); } String name = constraint.getName(); if (localTempTableConstraints.get(name) != null) { throw DbException.get(ErrorCode.CONSTRAINT_ALREADY_EXISTS_1, constraint.getSQL()); } localTempTableConstraints.put(name, constraint); }
/** * Add a local temporary table to this session. * * @param table the table to add * @throws DbException if a table with this name already exists */ public void addLocalTempTable(Table table) { if (localTempTables == null) { localTempTables = database.newStringMap(); } if (localTempTables.get(table.getName()) != null) { throw DbException.get(ErrorCode.TABLE_OR_VIEW_ALREADY_EXISTS_1, table.getSQL()); } modificationId++; localTempTables.put(table.getName(), table); }
public static void createPgPortEphemeralNode(ServerName sn, int port, boolean isMaster) { try { ZKUtil.createEphemeralNodeAndWatch( ZooKeeperAdmin.getZooKeeperWatcher(), getPgPortEphemeralNodePath(sn, port, isMaster), HConstants.EMPTY_BYTE_ARRAY); } catch (KeeperException e) { throw DbException.convert(e); } }
/** * Check if the current transaction is canceled by calling Statement.cancel() or because a session * timeout was set and expired. * * @throws DbException if the transaction is canceled */ public void checkCanceled() { throttle(); if (cancelAt == 0) { return; } long time = System.currentTimeMillis(); if (time >= cancelAt) { cancelAt = 0; throw DbException.get(ErrorCode.STATEMENT_WAS_CANCELED); } }
@Override public boolean next() { readBuffer.clear(); searchRow = null; row = null; index++; if (result != null && index < result.length) { setSearchRow(); return true; } Transaction transaction = session.getTransaction(); List<KeyValue> kvs; KeyValue kv; Result r; long queryTimestamp; try { result = session.getRegionServer().next(scannerId, fetchSize); ArrayList<Result> list = new ArrayList<Result>(result.length); for (int i = 0; i < result.length; i++) { r = result[i]; kvs = r.list(); // 当Result.isEmpty=true时,r.list()也返回null,所以这里不用再判断kvs.isEmpty if (kvs != null) { kv = kvs.get(0); queryTimestamp = kv.getTimestamp(); if (queryTimestamp < transaction.getStartTimestamp() & queryTimestamp % 2 == 0) { if (kv.getValueLength() != 0) // kv已删除,不需要再处理 list.add(r); continue; } } // TODO Filter.filter很慢 r = new Result(Filter.filter(session.getRegionServer(), regionName, transaction, kvs, 1)); if (!r.isEmpty()) list.add(r); } result = list.toArray(new Result[0]); } catch (Exception e) { close(); throw DbException.convert(e); } index = 0; if (result != null && result.length > 0) { setSearchRow(); return true; } close(); return false; }
/** * Open a new (remote or embedded) session. * * @param openNew whether to open a new session in any case * @return the session */ public SessionInterface connectEmbeddedOrServer(boolean openNew) { ConnectionInfo ci = connectionInfo; if (ci.isRemote() || ci.isDynamic()) { connectServer(ci); return this; } // create the session using reflection, // so that the JDBC layer can be compiled without it boolean autoServerMode = Boolean.valueOf(ci.getProperty("AUTO_SERVER", "false")).booleanValue(); ConnectionInfo backup = null; try { if (autoServerMode) { backup = (ConnectionInfo) ci.clone(); connectionInfo = (ConnectionInfo) ci.clone(); } if (openNew) { ci.setProperty("OPEN_NEW", "true"); } if (sessionFactory == null) { sessionFactory = ci.getSessionFactory(); } return sessionFactory.createSession(ci); } catch (Exception re) { DbException e = DbException.convert(re); if (e.getErrorCode() == ErrorCode.DATABASE_ALREADY_OPEN_1) { if (autoServerMode) { String serverKey = ((JdbcSQLException) e.getSQLException()).getSQL(); if (serverKey != null) { backup.setServerKey(serverKey); // OPEN_NEW must be removed now, otherwise // opening a session with AUTO_SERVER fails // if another connection is already open backup.removeProperty("OPEN_NEW", null); connectServer(backup); return this; } } } throw e; } }
/** * Called to flush the output after data has been sent to the server and just before receiving * data. This method also reads the status code from the server and throws any exception the * server sent. * * @param transfer the transfer object * @throws DbException if the server sent an exception * @throws IOException if there is a communication problem between client and server */ public void done(Transfer transfer) throws IOException { // 正常来讲不会出现这种情况,如果出现了,说明存在bug,找出为什么transfer的输入流没正常读完的原因 if (transfer.available() > 0) { throw DbException.throwInternalError( "before transfer flush, the available bytes was " + transfer.available()); } transfer.flush(); int status = transfer.readInt(); if (status == STATUS_ERROR) { parseError(transfer); } else if (status == STATUS_CLOSED) { transferList = null; } else if (status == STATUS_OK_STATE_CHANGED) { sessionStateChanged = true; } else if (status == STATUS_OK) { // ok } else { throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, "unexpected status " + status); } }
private void initWrite() throws IOException { if (output == null) { try { OutputStream out = FileUtils.newOutputStream(fileName, false); out = new BufferedOutputStream(out, Constants.IO_BUFFER_SIZE); output = new BufferedWriter(new OutputStreamWriter(out, characterSet)); } catch (Exception e) { close(); throw DbException.convertToIOException(e); } } }
public void parseError(Transfer transfer) throws IOException { String sqlstate = transfer.readString(); String message = transfer.readString(); String sql = transfer.readString(); int errorCode = transfer.readInt(); String stackTrace = transfer.readString(); JdbcSQLException s = new JdbcSQLException(message, sql, sqlstate, errorCode, null, stackTrace); if (errorCode == ErrorCode.CONNECTION_BROKEN_1) { // allow re-connect IOException e = new IOException(s.toString()); e.initCause(s); throw e; } throw DbException.convert(s); }
private void sendErrorResponse(Exception re) throws IOException { SQLException e = DbException.toSQLException(re); server.traceError(e); startMessage('E'); write('S'); writeString("ERROR"); write('C'); writeString(e.getSQLState()); write('M'); writeString(e.getMessage()); write('D'); writeString(e.toString()); write(0); sendMessage(); }
private int writeResultSet(ResultSet rs) throws SQLException { try { int rows = 0; ResultSetMetaData meta = rs.getMetaData(); int columnCount = meta.getColumnCount(); String[] row = new String[columnCount]; int[] sqlTypes = new int[columnCount]; for (int i = 0; i < columnCount; i++) { row[i] = meta.getColumnLabel(i + 1); sqlTypes[i] = meta.getColumnType(i + 1); } if (writeColumnHeader) { writeRow(row); } while (rs.next()) { for (int i = 0; i < columnCount; i++) { Object o; switch (sqlTypes[i]) { case Types.DATE: o = rs.getDate(i + 1); break; case Types.TIME: o = rs.getTime(i + 1); break; case Types.TIMESTAMP: o = rs.getTimestamp(i + 1); break; default: o = rs.getString(i + 1); } row[i] = o == null ? null : o.toString(); } writeRow(row); rows++; } output.close(); return rows; } catch (IOException e) { throw DbException.convertIOException(e, null); } finally { close(); JdbcUtils.closeSilently(rs); } }
private void unlockAll() { if (SysProperties.CHECK) { if (undoLog.size() > 0) { DbException.throwInternalError(); } } if (locks.size() > 0) { synchronized (database) { // don't use the enhanced for loop to save memory for (int i = 0, size = locks.size(); i < size; i++) { Table t = locks.get(i); t.unlock(this); } locks.clear(); } } savepoints = null; sessionStateChanged = true; }
public FileStore openFile(String name, String mode, boolean mustExist) { if (mustExist && !FileUtils.exists(name)) { throw DbException.get(ErrorCode.FILE_NOT_FOUND_1, name); } FileStore store; if (cipher == null) { store = FileStore.open(this, name, mode); } else { store = FileStore.open(this, name, mode, cipher, fileEncryptionKey, 0); } store.setCheckedWriting(false); try { store.init(); } catch (DbException e) { store.closeSilently(); throw e; } return store; }
@Override public Row get() { if (row == null) { if (searchRow != null) { Result r; try { Get get = new Get(HBaseUtils.toBytes(searchRow.getRowKey())); get.setTimeStamp(searchTimestamp); if (columns != null) { for (Column c : columns) { if (c.isRowKeyColumn()) continue; else if (c.getColumnFamilyName() != null) get.addColumn(c.getColumnFamilyNameAsBytes(), c.getNameAsBytes()); else get.addColumn(defaultColumnFamilyName, c.getNameAsBytes()); } } r = secondaryIndex.dataTable.get(get); } catch (IOException e) { throw DbException.convert(e); } if (r != null) { Value[] data = new Value[columns.size()]; Value rowKey = ValueString.get(Bytes.toString(r.getRow())); if (columns != null) { int i = 0; for (Column c : columns) { i = c.getColumnId(); if (c.isRowKeyColumn()) data[i] = rowKey; else data[i] = HBaseUtils.toValue( // r.getValue(c.getColumnFamilyNameAsBytes(), c.getNameAsBytes()), c.getType()); } } row = new HBaseRow(null, rowKey, data, Row.MEMORY_CALCULATE, r); } } } return row; }
/** * INTERNAL. Parse and set the CSV options. * * @param options the the options * @return the character set */ public String setOptions(String options) { String charset = null; String[] keyValuePairs = StringUtils.arraySplit(options, ' ', false); for (String pair : keyValuePairs) { if (pair.length() == 0) { continue; } int index = pair.indexOf('='); String key = StringUtils.trim(pair.substring(0, index), true, true, " "); String value = pair.substring(index + 1); char ch = value.length() == 0 ? 0 : value.charAt(0); if (isParam(key, "escape", "esc", "escapeCharacter")) { setEscapeCharacter(ch); } else if (isParam(key, "fieldDelimiter", "fieldDelim")) { setFieldDelimiter(ch); } else if (isParam(key, "fieldSeparator", "fieldSep")) { setFieldSeparatorRead(ch); setFieldSeparatorWrite(value); } else if (isParam(key, "lineComment", "lineCommentCharacter")) { setLineCommentCharacter(ch); } else if (isParam(key, "lineSeparator", "lineSep")) { setLineSeparator(value); } else if (isParam(key, "null", "nullString")) { setNullString(value); } else if (isParam(key, "rowSeparator", "rowSep")) { setRowSeparatorWrite(value); } else if (isParam(key, "charset", "characterSet")) { charset = value; } else if (isParam(key, "preserveWhitespace")) { setPreserveWhitespace(Boolean.parseBoolean(value)); } else if (isParam(key, "writeColumnHeader")) { setWriteColumnHeader(Boolean.parseBoolean(value)); } else if (isParam(key, "caseSensitiveColumnNames")) { setCaseSensitiveColumnNames(Boolean.parseBoolean(value)); } else { throw DbException.get(ErrorCode.FEATURE_NOT_SUPPORTED_1, key); } } return charset; }
private static void installPgCatalog(Statement stat) throws SQLException { Reader r = null; try { r = new InputStreamReader( new ByteArrayInputStream( Utils.getResource("/com/codefollower/lealone/server/pg/pg_catalog.sql"))); ScriptReader reader = new ScriptReader(r); while (true) { String sql = reader.readStatement(); if (sql == null) { break; } stat.execute(sql); } reader.close(); } catch (IOException e) { throw DbException.convertIOException(e, "Can not read pg_catalog resource"); } finally { IOUtils.closeSilently(r); } }
private void initDb() throws SQLException { Statement stat = null; ResultSet rs = null; try { synchronized (server) { // better would be: set the database to exclusive mode rs = conn.getMetaData().getTables(null, "PG_CATALOG", "PG_VERSION", null); boolean tableFound = rs.next(); stat = conn.createStatement(); if (!tableFound) { installPgCatalog(stat); } rs = stat.executeQuery("SELECT * FROM PG_CATALOG.PG_VERSION"); if (!rs.next() || rs.getInt(1) < 2) { // installation incomplete, or old version installPgCatalog(stat); } else { // version 2 or newer: check the read version int versionRead = rs.getInt(2); if (versionRead > 2) { throw DbException.throwInternalError("Incompatible PG_VERSION"); } } } stat.execute("set search_path = PUBLIC, pg_catalog"); HashSet<Integer> typeSet = server.getTypeSet(); if (typeSet.size() == 0) { rs = stat.executeQuery("SELECT OID FROM PG_CATALOG.PG_TYPE"); while (rs.next()) { typeSet.add(rs.getInt(1)); } } } finally { JdbcUtils.closeSilently(stat); JdbcUtils.closeSilently(rs); } }