Пример #1
0
 /**
  * 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;
 }
Пример #2
0
 /**
  * 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()) {
     connectServer(ci);
     return this;
   }
   // create the session using reflection,
   // so that the JDBC layer can be compiled without it
   boolean autoServerMode = Boolean.parseBoolean(ci.getProperty("AUTO_SERVER", "false"));
   ConnectionInfo backup = null;
   try {
     if (autoServerMode) {
       backup = ci.clone();
       connectionInfo = ci.clone();
     }
     if (openNew) {
       ci.setProperty("OPEN_NEW", "true");
     }
     if (sessionFactory == null) {
       sessionFactory =
           (SessionFactory)
               Class.forName("org.h2.engine.Engine").getMethod("getInstance").invoke(null);
     }
     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;
   }
 }
Пример #3
0
  private void handleOnDuplicate(DbException de) {
    if (de.getErrorCode() != ErrorCode.DUPLICATE_KEY_1) {
      throw de;
    }
    if (duplicateKeyAssignmentMap == null || duplicateKeyAssignmentMap.isEmpty()) {
      throw de;
    }

    ArrayList<String> variableNames = new ArrayList<String>(duplicateKeyAssignmentMap.size());
    for (int i = 0; i < columns.length; i++) {
      String key =
          session.getCurrentSchemaName() + "." + table.getName() + "." + columns[i].getName();
      variableNames.add(key);
      session.setVariable(key, list.get(getCurrentRowNumber() - 1)[i].getValue(session));
    }

    Update command = new Update(session);
    command.setTableFilter(new TableFilter(session, table, null, true, null));
    for (Column column : duplicateKeyAssignmentMap.keySet()) {
      command.setAssignment(column, duplicateKeyAssignmentMap.get(column));
    }

    Index foundIndex = searchForUpdateIndex();

    if (foundIndex != null) {
      command.setCondition(prepareUpdateCondition(foundIndex));
    } else {
      throw DbException.getUnsupportedException(
          "Unable to apply ON DUPLICATE KEY UPDATE, no index found!");
    }

    command.prepare();
    command.update();
    for (String variableName : variableNames) {
      session.setVariable(variableName, ValueNull.INSTANCE);
    }
  }
Пример #4
0
 /**
  * Run one recovery stage. There are three recovery stages: 0: only the undo steps are run
  * (restoring the state before the last checkpoint). 1: the pages that are used by the transaction
  * log are allocated. 2: the committed operations are re-applied.
  *
  * @param stage the recovery stage
  * @return whether the transaction log was empty
  */
 boolean recover(int stage) {
   if (trace.isDebugEnabled()) {
     trace.debug("log recover stage: " + stage);
   }
   if (stage == RECOVERY_STAGE_ALLOCATE) {
     PageInputStream in = new PageInputStream(store, logKey, firstTrunkPage, firstDataPage);
     usedLogPages = in.allocateAllPages();
     in.close();
     return true;
   }
   PageInputStream pageIn = new PageInputStream(store, logKey, firstTrunkPage, firstDataPage);
   DataReader in = new DataReader(pageIn);
   int logId = 0;
   Data data = store.createData();
   boolean isEmpty = true;
   try {
     int pos = 0;
     while (true) {
       int x = in.readByte();
       if (x < 0) {
         break;
       }
       pos++;
       isEmpty = false;
       if (x == UNDO) {
         int pageId = in.readVarInt();
         int size = in.readVarInt();
         if (size == 0) {
           in.readFully(data.getBytes(), store.getPageSize());
         } else if (size == 1) {
           // empty
           Arrays.fill(data.getBytes(), 0, store.getPageSize(), (byte) 0);
         } else {
           in.readFully(compressBuffer, size);
           try {
             compress.expand(compressBuffer, 0, size, data.getBytes(), 0, store.getPageSize());
           } catch (ArrayIndexOutOfBoundsException e) {
             DbException.convertToIOException(e);
           }
         }
         if (stage == RECOVERY_STAGE_UNDO) {
           if (!undo.get(pageId)) {
             if (trace.isDebugEnabled()) {
               trace.debug("log undo {0}", pageId);
             }
             store.writePage(pageId, data);
             undo.set(pageId);
             undoAll.set(pageId);
           } else {
             if (trace.isDebugEnabled()) {
               trace.debug("log undo skip {0}", pageId);
             }
           }
         }
       } else if (x == ADD) {
         int sessionId = in.readVarInt();
         int tableId = in.readVarInt();
         Row row = readRow(in, data);
         if (stage == RECOVERY_STAGE_UNDO) {
           store.allocateIfIndexRoot(pos, tableId, row);
         } else if (stage == RECOVERY_STAGE_REDO) {
           if (isSessionCommitted(sessionId, logId, pos)) {
             if (trace.isDebugEnabled()) {
               trace.debug("log redo + table: " + tableId + " s: " + sessionId + " " + row);
             }
             store.redo(tableId, row, true);
           } else {
             if (trace.isDebugEnabled()) {
               trace.debug("log ignore s: " + sessionId + " + table: " + tableId + " " + row);
             }
           }
         }
       } else if (x == REMOVE) {
         int sessionId = in.readVarInt();
         int tableId = in.readVarInt();
         long key = in.readVarLong();
         if (stage == RECOVERY_STAGE_REDO) {
           if (isSessionCommitted(sessionId, logId, pos)) {
             if (trace.isDebugEnabled()) {
               trace.debug("log redo - table: " + tableId + " s:" + sessionId + " key: " + key);
             }
             store.redoDelete(tableId, key);
           } else {
             if (trace.isDebugEnabled()) {
               trace.debug("log ignore s: " + sessionId + " - table: " + tableId + " " + key);
             }
           }
         }
       } else if (x == TRUNCATE) {
         int sessionId = in.readVarInt();
         int tableId = in.readVarInt();
         if (stage == RECOVERY_STAGE_REDO) {
           if (isSessionCommitted(sessionId, logId, pos)) {
             if (trace.isDebugEnabled()) {
               trace.debug("log redo truncate table: " + tableId);
             }
             store.redoTruncate(tableId);
           } else {
             if (trace.isDebugEnabled()) {
               trace.debug("log ignore s: " + sessionId + " truncate table: " + tableId);
             }
           }
         }
       } else if (x == PREPARE_COMMIT) {
         int sessionId = in.readVarInt();
         String transaction = in.readString();
         if (trace.isDebugEnabled()) {
           trace.debug("log prepare commit " + sessionId + " " + transaction + " pos: " + pos);
         }
         if (stage == RECOVERY_STAGE_UNDO) {
           int page = pageIn.getDataPage();
           setPrepareCommit(sessionId, page, transaction);
         }
       } else if (x == ROLLBACK) {
         int sessionId = in.readVarInt();
         if (trace.isDebugEnabled()) {
           trace.debug("log rollback " + sessionId + " pos: " + pos);
         }
         // ignore - this entry is just informational
       } else if (x == COMMIT) {
         int sessionId = in.readVarInt();
         if (trace.isDebugEnabled()) {
           trace.debug("log commit " + sessionId + " pos: " + pos);
         }
         if (stage == RECOVERY_STAGE_UNDO) {
           setLastCommitForSession(sessionId, logId, pos);
         }
       } else if (x == NOOP) {
         // nothing to do
       } else if (x == CHECKPOINT) {
         logId++;
       } else if (x == FREE_LOG) {
         int count = in.readVarInt();
         for (int i = 0; i < count; i++) {
           int pageId = in.readVarInt();
           if (stage == RECOVERY_STAGE_REDO) {
             if (!usedLogPages.get(pageId)) {
               store.free(pageId, false);
             }
           }
         }
       } else {
         if (trace.isDebugEnabled()) {
           trace.debug("log end");
           break;
         }
       }
     }
   } catch (DbException e) {
     if (e.getErrorCode() == ErrorCode.FILE_CORRUPTED_1) {
       trace.debug("log recovery stopped");
     } else {
       throw e;
     }
   } catch (IOException e) {
     trace.debug("log recovery completed");
   }
   undo = new BitField();
   if (stage == RECOVERY_STAGE_REDO) {
     usedLogPages = null;
   }
   return isEmpty;
 }