use of org.h2.mvstore.db.TransactionStore.Change in project h2database by h2database.
the class Database method reconnectModified.
/**
* Set or reset the pending change flag in the .lock.db file.
*
* @param pending the new value of the flag
* @return true if the call was successful,
* false if another connection was faster
*/
private synchronized boolean reconnectModified(boolean pending) {
if (readOnly || lock == null || fileLockMethod != FileLockMethod.SERIALIZED) {
return true;
}
try {
if (pending == reconnectChangePending) {
long now = System.nanoTime();
if (now > reconnectCheckNext) {
if (pending) {
String pos = pageStore == null ? null : "" + pageStore.getWriteCountTotal();
lock.setProperty("logPos", pos);
lock.save();
}
reconnectCheckNext = now + reconnectCheckDelayNs;
}
return true;
}
Properties old = lock.load();
if (pending) {
if (old.getProperty("changePending") != null) {
return false;
}
trace.debug("wait before writing");
Thread.sleep(TimeUnit.NANOSECONDS.toMillis((long) (reconnectCheckDelayNs * 1.1)));
Properties now = lock.load();
if (!now.equals(old)) {
// somebody else was faster
return false;
}
}
String pos = pageStore == null ? null : "" + pageStore.getWriteCountTotal();
lock.setProperty("logPos", pos);
if (pending) {
lock.setProperty("changePending", "true-" + Math.random());
} else {
lock.setProperty("changePending", null);
}
// ensure that the writer thread will
// not reset the flag before we are done
reconnectCheckNext = System.nanoTime() + 2 * reconnectCheckDelayNs;
old = lock.save();
if (pending) {
trace.debug("wait before writing again");
Thread.sleep(TimeUnit.NANOSECONDS.toMillis((long) (reconnectCheckDelayNs * 1.1)));
Properties now = lock.load();
if (!now.equals(old)) {
// somebody else was faster
return false;
}
} else {
Thread.sleep(1);
}
reconnectLastLock = old;
reconnectChangePending = pending;
reconnectCheckNext = System.nanoTime() + reconnectCheckDelayNs;
return true;
} catch (Exception e) {
trace.error(e, "pending {0}", pending);
return false;
}
}
use of org.h2.mvstore.db.TransactionStore.Change in project h2database by h2database.
the class Database method isReconnectNeeded.
/**
* Check if the contents of the database was changed and therefore it is
* required to re-connect. This method waits until pending changes are
* completed. If a pending change takes too long (more than 2 seconds), the
* pending change is broken (removed from the properties file).
*
* @return true if reconnecting is required
*/
public boolean isReconnectNeeded() {
if (fileLockMethod != FileLockMethod.SERIALIZED) {
return false;
}
if (reconnectChangePending) {
return false;
}
long now = System.nanoTime();
if (now < reconnectCheckNext) {
return false;
}
reconnectCheckNext = now + reconnectCheckDelayNs;
if (lock == null) {
lock = new FileLock(traceSystem, databaseName + Constants.SUFFIX_LOCK_FILE, Constants.LOCK_SLEEP);
}
try {
Properties prop = lock.load(), first = prop;
while (true) {
if (prop.equals(reconnectLastLock)) {
return false;
}
if (prop.getProperty("changePending", null) == null) {
break;
}
if (System.nanoTime() > now + reconnectCheckDelayNs * 10) {
if (first.equals(prop)) {
// the writing process didn't update the file -
// it may have terminated
lock.setProperty("changePending", null);
lock.save();
break;
}
}
trace.debug("delay (change pending)");
Thread.sleep(TimeUnit.NANOSECONDS.toMillis(reconnectCheckDelayNs));
prop = lock.load();
}
reconnectLastLock = prop;
} catch (Exception e) {
// DbException, InterruptedException
trace.error(e, "readOnly {0}", readOnly);
// ignore
}
return true;
}
use of org.h2.mvstore.db.TransactionStore.Change in project h2database by h2database.
the class ConstraintReferential method checkRowOwnTable.
private void checkRowOwnTable(Session session, Row oldRow, Row newRow) {
if (newRow == null) {
return;
}
boolean constraintColumnsEqual = oldRow != null;
for (IndexColumn col : columns) {
int idx = col.column.getColumnId();
Value v = newRow.getValue(idx);
if (v == ValueNull.INSTANCE) {
// return early if one of the columns is NULL
return;
}
if (constraintColumnsEqual) {
if (!database.areEqual(v, oldRow.getValue(idx))) {
constraintColumnsEqual = false;
}
}
}
if (constraintColumnsEqual) {
// return early if the key columns didn't change
return;
}
if (refTable == table) {
// special case self referencing constraints:
// check the inserted row first
boolean self = true;
for (int i = 0, len = columns.length; i < len; i++) {
int idx = columns[i].column.getColumnId();
Value v = newRow.getValue(idx);
Column refCol = refColumns[i].column;
int refIdx = refCol.getColumnId();
Value r = newRow.getValue(refIdx);
if (!database.areEqual(r, v)) {
self = false;
break;
}
}
if (self) {
return;
}
}
Row check = refTable.getTemplateRow();
for (int i = 0, len = columns.length; i < len; i++) {
int idx = columns[i].column.getColumnId();
Value v = newRow.getValue(idx);
Column refCol = refColumns[i].column;
int refIdx = refCol.getColumnId();
check.setValue(refIdx, refCol.convert(v));
}
if (!existsRow(session, refIndex, check, null)) {
throw DbException.get(ErrorCode.REFERENTIAL_INTEGRITY_VIOLATED_PARENT_MISSING_1, getShortDescription(refIndex, check));
}
}
use of org.h2.mvstore.db.TransactionStore.Change in project h2database by h2database.
the class PageStore method redo.
/**
* Redo a change in a table.
*
* @param tableId the object id of the table
* @param row the row
* @param add true if the record is added, false if deleted
*/
void redo(int tableId, Row row, boolean add) {
if (tableId == META_TABLE_ID) {
if (add) {
addMeta(row, pageStoreSession, true);
} else {
removeMeta(row);
}
}
Index index = metaObjects.get(tableId);
if (index == null) {
throw DbException.throwInternalError("Table not found: " + tableId + " " + row + " " + add);
}
Table table = index.getTable();
if (add) {
table.addRow(pageStoreSession, row);
} else {
table.removeRow(pageStoreSession, row);
}
}
use of org.h2.mvstore.db.TransactionStore.Change in project h2database by h2database.
the class FullText method setIgnoreList.
/**
* Change the ignore list. The ignore list is a comma separated list of
* common words that must not be indexed. The default ignore list is empty.
* If indexes already exist at the time this list is changed, reindex must
* be called.
*
* @param conn the connection
* @param commaSeparatedList the list
*/
public static void setIgnoreList(Connection conn, String commaSeparatedList) throws SQLException {
try {
init(conn);
FullTextSettings setting = FullTextSettings.getInstance(conn);
setIgnoreList(setting, commaSeparatedList);
Statement stat = conn.createStatement();
stat.execute("TRUNCATE TABLE " + SCHEMA + ".IGNORELIST");
PreparedStatement prep = conn.prepareStatement("INSERT INTO " + SCHEMA + ".IGNORELIST VALUES(?)");
prep.setString(1, commaSeparatedList);
prep.execute();
} catch (DbException e) {
throw DbException.toSQLException(e);
}
}
Aggregations