All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.mapsmessaging.storage.AsyncStorage Maven / Gradle / Ivy

There is a newer version: 2.4.10
Show newest version
/*
 *   Copyright [2020 - 2022]   [Matthew Buckton]
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 *
 */

package io.mapsmessaging.storage;

import io.mapsmessaging.logging.Logger;
import io.mapsmessaging.logging.LoggerFactory;
import io.mapsmessaging.storage.impl.tier.memory.MemoryTierStorage;
import io.mapsmessaging.storage.logging.StorageLogMessages;
import io.mapsmessaging.storage.tasks.AddTask;
import io.mapsmessaging.storage.tasks.AutoPauseTask;
import io.mapsmessaging.storage.tasks.CloseTask;
import io.mapsmessaging.storage.tasks.Completion;
import io.mapsmessaging.storage.tasks.ContainsTask;
import io.mapsmessaging.storage.tasks.DeleteTask;
import io.mapsmessaging.storage.tasks.GetKeysTask;
import io.mapsmessaging.storage.tasks.GetTask;
import io.mapsmessaging.storage.tasks.IsEmptyTask;
import io.mapsmessaging.storage.tasks.KeepOnlyTask;
import io.mapsmessaging.storage.tasks.LastKeyTask;
import io.mapsmessaging.storage.tasks.PauseTask;
import io.mapsmessaging.storage.tasks.RemoveTask;
import io.mapsmessaging.storage.tasks.RetrieveStatisticsTask;
import io.mapsmessaging.storage.tasks.SizeTask;
import io.mapsmessaging.utilities.threads.tasks.PriorityConcurrentTaskScheduler;
import java.io.Closeable;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import lombok.SneakyThrows;
import org.jetbrains.annotations.NotNull;

public class AsyncStorage implements Closeable {

  private final Logger logger;

  private static final int BACKGROUND_PRIORITY = 0;
  private static final int FOREGROUND_PRIORITY = 1;

  private final Storage storage;
  private final PriorityConcurrentTaskScheduler scheduler;
  private final AtomicBoolean closed;

  private ScheduledFuture autoPauseFuture;

  public AsyncStorage(@NotNull Storage storage) {
    this.storage = storage;
    scheduler = new PriorityConcurrentTaskScheduler(storage.getName(), 2);
    closed = new AtomicBoolean(false);
    storage.setExecutor(scheduler);
    autoPauseFuture = null;
    logger = LoggerFactory.getLogger("AsyncStorage - "+storage.getName());
    logger.log(StorageLogMessages.ASYNC_STORAGE_CREATED, storage.getName());
  }

  @SneakyThrows
  @Override
  public void close() throws IOException {
    Future future = close(null);
    try {
      future.get();
      logger.log(StorageLogMessages.ASYNC_CLOSE_COMPLETED);
    } catch (ExecutionException e) {
      logger.log(StorageLogMessages.ASYNC_CLOSE_FAILED, e);
      throw new IOException(e);
    }
  }

  public final Future close(Completion completion) throws IOException {
    checkClose();
    if (autoPauseFuture != null) {
      autoPauseFuture.cancel(false);
    }
    logger.log(StorageLogMessages.ASYNC_CLOSE_REQUESTED);
    closed.set(true);
    storage.shutdown();
    return scheduler.submit(new CloseTask<>(storage, completion), FOREGROUND_PRIORITY);
  }

  public void enableAutoPause(long idleTime) {
    logger.log(StorageLogMessages.ASYNC_ENABLE_AUTO_PAUSE);
    if(storage instanceof MemoryTierStorage){
      long migrationTime = ((MemoryTierStorage)storage).getMigrationTime();
      if(migrationTime > idleTime){ // We would pause the file store before migrating from memory to file
        idleTime = (long)(migrationTime * 1.5f);
      }
    }
    AutoPauseTask autoPauseTask = new AutoPauseTask(this, idleTime);
    autoPauseFuture = storage.getTaskScheduler().scheduleAtFixedRate(autoPauseTask, idleTime, TimeUnit.MILLISECONDS);
  }

  public final Future delete() throws IOException {
    return delete(null);
  }

  public final Future delete(Completion completion) throws IOException {
    checkClose();
    if (autoPauseFuture != null) {
      autoPauseFuture.cancel(false);
    }
    storage.getTaskScheduler().purge();
    logger.log(StorageLogMessages.ASYNC_DELETE_REQUESTED);
    closed.set(true);
    storage.shutdown();
    return scheduler.submit(new DeleteTask<>(storage, completion), FOREGROUND_PRIORITY);
  }

  public final Future add(@NotNull T toStore) throws IOException {
    return add(toStore, null);
  }

  public Future add(@NotNull T toStore, Completion completion) throws IOException {
    checkClose();
    logger.log(StorageLogMessages.ASYNC_ADD_REQUESTED, toStore.getKey());
    return scheduler.submit(new AddTask<>(storage, toStore, completion), FOREGROUND_PRIORITY);
  }

  public Future remove(long key) throws IOException {
    return remove(key, null);
  }

  public Future remove(long key, Completion completion) throws IOException {
    checkClose();
    logger.log(StorageLogMessages.ASYNC_REMOVE_REQUESTED, key);
    return scheduler.submit(new RemoveTask<>(storage, key, completion), FOREGROUND_PRIORITY);
  }

  public Future get(long key) throws IOException {
    return get(key, null);
  }

  public Future get(long key, Completion completion) throws IOException {
    checkClose();
    logger.log(StorageLogMessages.ASYNC_GET_REQUESTED, key);
    return scheduler.submit(new GetTask<>(storage, key, completion), FOREGROUND_PRIORITY);
  }

  public Future size() throws IOException {
    checkClose();
    logger.log(StorageLogMessages.ASYNC_SIZE_REQUESTED);
    return scheduler.submit(new SizeTask<>(storage), FOREGROUND_PRIORITY);
  }

  public Future getLastKey() throws IOException {
    checkClose();
    logger.log(StorageLogMessages.ASYNC_LAST_KEY_REQUESTED);
    return scheduler.submit(new LastKeyTask<>(storage), FOREGROUND_PRIORITY);
  }

  public Future isEmpty() {
    logger.log(StorageLogMessages.ASYNC_IS_EMPTY_REQUESTED);
    return scheduler.submit(new IsEmptyTask<>(storage), FOREGROUND_PRIORITY);
  }

  // Returns a list of events NOT found but was in the to keep list
  public Future> keepOnly(@NotNull Collection listToKeep) throws IOException {
    return keepOnly(listToKeep, null);
  }

  public Future> keepOnly(@NotNull Collection listToKeep, Completion> completion) throws IOException {
    checkClose();
    return scheduler.submit(new KeepOnlyTask<>(storage, listToKeep, completion), FOREGROUND_PRIORITY);
  }

  public Future> getKeys() throws IOException {
    return getKeys(null);
  }

  public Future> getKeys(Completion> completion) throws IOException {
    checkClose();
    return scheduler.submit(new GetKeysTask<>(storage, completion), FOREGROUND_PRIORITY);
  }

  public Future contains(long key) throws IOException {
    return contains(key, null);
  }

  public Future contains(long key, Completion completion) throws IOException {
    checkClose();
    return scheduler.submit(new ContainsTask<>(storage, key, completion), FOREGROUND_PRIORITY);
  }

  public Future getStatistics() {
    return getStatistics(null);
  }

  public Future getStatistics(Completion completion) {
    logger.log(StorageLogMessages.ASYNC_STATISTICS_REQUESTED);
    return scheduler.submit(new RetrieveStatisticsTask<>(storage, completion), FOREGROUND_PRIORITY);
  }

  public Future pause() throws IOException {
    checkClose();
    logger.log(StorageLogMessages.ASYNC_PAUSE_REQUESTED);
    return scheduler.submit(new PauseTask<>(storage), BACKGROUND_PRIORITY);
  }

  public long getLastAccess() {
    return storage.getLastAccess();
  }

  protected void checkClose() throws IOException {
    if (closed.get()) {
      logger.log(StorageLogMessages.ASYNC_REQUEST_ON_CLOSED_STORE);
      throw new IOException("Store has been scheduled to close");
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy