示例#1
0
 private void invokeCallbacks(Callback<Void>[] callbacks, Throwable e) {
   for (Callback<Void> callback : callbacks) {
     try {
       callback.onDone(null, e);
     } catch (Throwable e2) {
       Log.error("Transaction callback error", e2);
     }
   }
 }
示例#2
0
  private void persist() {
    while (!Thread.interrupted()) {
      try {
        persistData();
      } catch (Exception e1) {
        Log.error("Failed to persist data!", e1);
      }

      if (data.active.get()) {
        try {
          Thread.sleep(100);
        } catch (InterruptedException e) {
        }
      } else {
        try {
          persistData();
        } catch (Exception e1) {
          Log.error("Failed to persist data!", e1);
        }
        return;
      }
    }
  }
示例#3
0
  /**
   * ACID transactional semantics:<br>
   * - Atomicity with automatic rollback in case of exception,<br>
   * - Consistency - only with constraints enforced programmatically inside transaction,<br>
   * - Isolation is serializable (with global lock),<br>
   * - Durability through on-commit callbacks.<br>
   */
  public void transaction(Runnable transaction, boolean readOnly, Callback<Void> txCallback) {
    globalLock();

    data.txIdCounter.set(data.ids.get());
    data.txChanges.clear();
    data.txInsertions.clear();
    data.txReadonly.set(readOnly);
    data.insideTx.set(true);

    boolean success = false;
    try {
      transaction.run();
      success = true;

    } catch (Throwable e) {
      if (SuccessException.isSuccess(e)) {
        success = true;
        throw U.rte(e);
      } else {
        Log.error("Error in transaction, rolling back", e);
        txRollback();
        if (txCallback != null) {
          txCallback.onDone(null, e);
          txCallback = null;
        }
      }

    } finally {
      data.txChanges.clear();
      data.txInsertions.clear();
      data.insideTx.set(false);

      if (persistor != null) {
        if (success && txCallback != null) {
          data.txCallbacks.add(txCallback);
        }
      } else {
        if (success && txCallback != null) {
          txCallback.onDone(null, null);
        }
      }

      globalUnlock();
    }
  }
示例#4
0
  public void loadFrom(InputStream in) {
    globalLock();

    try {
      data.data.clear();

      BufferedReader reader = new BufferedReader(new InputStreamReader(in));

      String line = reader.readLine();
      byte[] bytes = line.getBytes();

      U.must(line != null, "Missing meta-data at the first line in the database file!");

      Map<String, Object> meta = U.map();
      data.serializer.deserialize(bytes, meta);

      Log.info(
          "Database meta-data",
          META_TIMESTAMP,
          meta.get(META_TIMESTAMP),
          META_UPTIME,
          meta.get(META_UPTIME));

      while ((line = reader.readLine()) != null) {
        bytes = line.getBytes();
        Map<String, Object> map = U.map();
        data.serializer.deserialize(bytes, map);

        Object idObj = map.get(ID);
        U.must(idObj != null, "Found DB record without ID: %s", line);

        long id = Cls.convert(idObj, Long.class);
        String className = ((String) map.get("_class"));

        String[] nameParts = className.split("\\.");
        String simpleName = nameParts[nameParts.length - 1];
        List<Class<?>> classes = Scan.byName(simpleName, null, null);

        if (classes.size() == 1) {
          Class<?> type = classes.get(0);
          data.data.put(id, new Rec(type, bytes));

          if (id > data.ids.get()) {
            data.ids.set(id);
          }

        } else {
          if (classes.isEmpty()) {
            Log.error("Cannot find the class of a DB record!", "id", id, "class", className);
          } else {
            Log.error("Found more than 1 class of a DB record!", "id", id, "class", className);
          }
        }
      }

      data.prevData = new ConcurrentSkipListMap<Long, Rec>(data.data);

      reader.close();

    } catch (IOException e) {
      throw new RuntimeException("Cannot load database!", e);
    } finally {
      globalUnlock();
    }
  }