Example #1
0
  /**
   * Commit all changes and persist them to disk. This method does nothing if there are no unsaved
   * changes, otherwise it increments the current version and stores the data (for file based
   * storages).
   *
   * <p>At most one storage operation may run at any time.
   *
   * @return the new version (incremented if there were changes)
   */
  private synchronized long commitAndSave() {
    if (closed) {
      return currentVersion;
    }
    if (map.isInMemory()) {
      throw DataUtils.newIllegalStateException(
          DataUtils.ERROR_WRITING_FAILED, "This is an in-memory storage");
    }
    if (map.isReadOnly()) {
      throw DataUtils.newIllegalStateException(
          DataUtils.ERROR_WRITING_FAILED, "This storage is read-only");
    }

    if (!hasUnsavedChanges()) {
      return currentVersion;
    }

    try {
      currentStoreVersion = currentVersion;
      return save();
    } catch (IllegalStateException e) {
      panic(e);
      return -1;
    } finally {
      currentStoreVersion = -1;
    }
  }
Example #2
0
 /**
  * Get the oldest version to retain in memory, which is the manually set retain version, or the
  * current store version (whatever is older).
  *
  * @return the version
  */
 long getOldestVersionToKeep() {
   long v = currentVersion;
   if (map.isInMemory()) {
     return v - versionsToKeep;
   }
   long storeVersion = currentStoreVersion;
   if (storeVersion > -1) {
     v = Math.min(v, storeVersion);
   }
   return v;
 }
Example #3
0
 /** Close the file and the storage. Unsaved changes are written to disk first. */
 void close() {
   if (closed) {
     return;
   }
   if (!map.isInMemory()) {
     if (hasUnsavedChanges()) {
       commitAndSave();
     }
   }
   closeStorage();
 }
Example #4
0
  private void closeStorage() {
    if (closed) {
      return;
    }

    closed = true;
    if (map.isInMemory()) {
      return;
    }
    synchronized (this) {
      for (BTreeChunk c : chunks.values()) {
        if (c.fileStorage != null) c.fileStorage.close();
      }
      // release memory early - this is important when called
      // because of out of memory
      if (cache != null) cache.clear();
      chunks.clear();
    }
  }
Example #5
0
  /**
   * Rename a map.
   *
   * @param map the map
   * @param newName the new name
   */
  public synchronized void renameMap(BTreeMap<?, ?> map, String newName) { // TODO
    if (map.isInMemory()) return;
    checkOpen();
    String oldName = map.getName();
    if (oldName.equals(newName)) {
      return;
    }

    String fileName = (String) map.config.get("storageName");
    if (fileName != null) {
      fileName = fileName + File.separator + newName;
      if (!FileUtils.exists(fileName)) FileUtils.createDirectories(fileName);

      close();

      FileUtils.move(btreeStorageName, fileName);
      // btreeStorageName = fileName;
    }
  }
Example #6
0
 /**
  * Commit the changes.
  *
  * <p>For in-memory storages, this method increments the version.
  *
  * <p>For persistent storages, it also writes changes to disk. It does nothing if there are no
  * unsaved changes, and returns the old version. It is not necessary to call this method when
  * auto-commit is enabled (the default setting), as in this case it is automatically called from
  * time to time or when enough changes have accumulated. However, it may still be called to flush
  * all changes to disk.
  *
  * @return the new version
  */
 public synchronized long commit() {
   if (map.isInMemory()) {
     return ++currentVersion;
   }
   return commitAndSave();
 }
Example #7
0
  /**
   * Create and open the storage.
   *
   * @param map the map to use
   * @throws IllegalStateException if the file is corrupt, or an exception occurred while opening
   * @throws IllegalArgumentException if the directory does not exist
   */
  protected BTreeStorage(BTreeMap<Object, Object> map) {
    this.map = map;
    btreeStorageName = map.getBTreeStorageName();
    Map<String, Object> config = map.config;

    Object value = config.get("retentionTime");
    retentionTime = value == null ? 45000 : (Long) value;

    value = config.get("versionsToKeep");
    versionsToKeep = value == null ? 5 : (Integer) value;

    reuseSpace = config.containsKey("reuseSpace");

    value = config.get("pageSplitSize");
    pageSplitSize = value != null ? (Integer) value : (map.isInMemory() ? 4 * 1024 : 16 * 1024);

    backgroundExceptionHandler =
        (UncaughtExceptionHandler) config.get("backgroundExceptionHandler");

    if (map.isInMemory()) {
      cache = null;
      compressionLevel = 0;
      autoCompactFillRate = 0;
      autoCommitMemory = 0;

      createVersion = 0;
      creationTime = getTimeAbsolute();
      return;
    }

    value = config.get("cacheSize");
    int mb = value == null ? 16 : (Integer) value;
    if (mb > 0) {
      CacheLongKeyLIRS.Config cc = new CacheLongKeyLIRS.Config();
      cc.maxMemory = mb * 1024L * 1024L;
      cache = new CacheLongKeyLIRS<BTreePage>(cc);
    } else {
      cache = null;
    }

    value = config.get("compress");
    compressionLevel = value == null ? 0 : (Integer) value;

    value = config.get("autoCompactFillRate");
    autoCompactFillRate = value == null ? 50 : (Integer) value;

    value = config.get("autoCommitBufferSize");
    int kb = value == null ? 1024 : (Integer) value;
    // 19 KB memory is about 1 KB storage
    autoCommitMemory = kb * 1024 * 19;

    lastChunkId = 0;
    long createVersion = Long.MAX_VALUE;
    if (!FileUtils.exists(btreeStorageName)) FileUtils.createDirectories(btreeStorageName);
    String[] files = new File(btreeStorageName).list();
    if (files != null && files.length > 0) {
      for (String f : files) {
        int id = Integer.parseInt(f.substring(0, f.length() - AOStorage.SUFFIX_AO_FILE_LENGTH));
        if (id > lastChunkId) lastChunkId = id;

        if (id < createVersion) createVersion = id;
      }
    }
    if (createVersion == Long.MAX_VALUE) createVersion = 0;
    this.createVersion = createVersion;

    try {
      if (lastChunkId > 0) readLastChunk();
    } catch (IllegalStateException e) {
      panic(e);
    }

    if (lastChunk != null) creationTime = lastChunk.creationTime;
    else creationTime = getTimeAbsolute();
    lastCommitTime = getTimeSinceCreation();
  }