public void rollbackThreadTransaction() {
		if (multiclientSupport) {
			synchronized (transactionMonitor) {
				transactionLock.reset();
				rollback();
				file.unlock();
				nNestedTransactions = 0;
			}

			return;
		}

		ThreadTransactionContext ctx = getTransactionContext();

		if (ctx.nested != 0) { // serializable transaction
			ArrayList modified = ctx.modified;
			Map locked = ctx.locked;

			synchronized (this) {
				synchronized (objectCache) {
					int i = modified.size();

					while (--i >= 0) {
						Object obj = modified.get(i);
						int oid = getOid(obj);
						Assert.that(oid != 0);
						invalidate(obj);

						if (getPos(oid) == 0) {
							freeId(oid);
							objectCache.remove(oid);
						}
						else {
							loadStub(oid, obj, obj.getClass());
							objectCache.clearDirty(obj);
						}
					}
				}
			}

			Iterator iterator = locked.values().iterator();

			while (iterator.hasNext()) {
				((IResource) iterator.next()).reset();
			}

			ctx.nested = 0;
			modified.clear();
			ctx.deleted.clear();
			locked.clear();

			if (listener != null) {
				listener.onTransactionRollback();
			}
		}
		else {
			synchronized (transactionMonitor) {
				transactionLock.reset();
				nNestedTransactions = 0;

				if (nBlockedTransactions != 0) {
					transactionMonitor.notifyAll();
				}

				rollback();
			}
		}
	}