Package com.carrotgarden.nexus.aws.s3.publish.amazon

Source Code of com.carrotgarden.nexus.aws.s3.publish.amazon.AmazonProvider

/**
* Copyright (C) 2010-2012 Andrei Pozolotin <Andrei.Pozolotin@gmail.com>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.carrotgarden.nexus.aws.s3.publish.amazon;

import java.io.File;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;
import javax.inject.Named;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonatype.nexus.threads.NexusThreadFactory;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import com.amazonaws.services.s3.model.DeleteObjectRequest;
import com.amazonaws.services.s3.model.GetBucketLocationRequest;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.PutObjectResult;
import com.carrotgarden.nexus.aws.s3.publish.config.ConfigBean;
import com.carrotgarden.nexus.aws.s3.publish.metrics.AmazonReporter;
import com.carrotgarden.nexus.aws.s3.publish.metrics.Reporter;
import com.carrotgarden.nexus.aws.s3.publish.util.ConfigHelp;
import com.carrotgarden.nexus.aws.s3.publish.util.PathHelp;

@Named(AmazonProvider.NAME)
public class AmazonProvider implements AmazonService, AmazonManager {

  public static final String NAME = "carrot.amazon.provider";

  private static final NexusThreadFactory threadFactory = //
  new NexusThreadFactory("carrot", NAME);

  private static final ScheduledExecutorService scheduler = //
  Executors.newScheduledThreadPool(1, threadFactory);

  private final AmazonReporter reporter;

  @Inject
  public AmazonProvider( //
      final AmazonReporter reporter //
  ) {

    this.reporter = reporter;

  }

  private long checkCount;

  private volatile AmazonS3Client client;

  private volatile ConfigBean config;

  private volatile ScheduledFuture<?> healthFuture;

  private final Runnable healtTask = new Runnable() {
    @Override
    public void run() {
      checkAvailable();
    }
  };

  private boolean isAvailable;

  protected final Logger log = LoggerFactory.getLogger(getClass());

  private long amazonThrottleExpiration() {
    return ConfigHelp.reference().getMilliseconds(
        "amazon-provider.throttle-expiration");
  }

  private boolean amazonThrottleExceptions() {
    return ConfigHelp.reference().getBoolean(
        "amazon-provider.throttle-exceptions");
  }

  // private final Cache<String, String> exceptionCache = CacheBuilder
  // .newBuilder()
  // .maximumSize(1000)
  // .expireAfterWrite(amazonThrottleExpiration(), TimeUnit.MILLISECONDS)
  // .build();

  private synchronized void checkAvailable() {

    reporter.requestCheckCount.inc();
    reporter.requestTotalCount.inc();

    try {

      final String bucket = config.bucket();

      final GetBucketLocationRequest request = //
      new GetBucketLocationRequest(bucket);

      final String result = client.getBucketLocation(request);

      if (!setAvailable(true) || isFirstScheck()) {
        log.info(NAME + " available");
      }

    } catch (final Exception e) {

      if (setAvailable(false) || isFirstScheck()) {
        log.error(NAME + " unavailable", e);
      }

    }

    checkCount++;

  }

  @Override
  public synchronized void config(final ConfigBean config) {
    this.config = config;
  }

  private AWSCredentials credentials() {

    final String username = config.awsAccess();
    final String password = config.awsSecret();

    return new BasicAWSCredentials(username, password);

  }

  @Override
  public boolean isAvailable() {
    return isAvailable;
  }

  private boolean isFirstScheck() {
    return checkCount == 0;
  }

  @Override
  public boolean kill(final String path) {

    reporter.requestKillCount.inc();
    reporter.requestTotalCount.inc();

    try {

      final String bucket = config.bucket();

      final DeleteObjectRequest request = //
      new DeleteObjectRequest(bucket, PathHelp.rootLessPath(path));

      client.deleteObject(request);

      setAvailable(true);

      return true;

    } catch (final Exception e) {

      processFailure(e);
      return false;

    }

  }

  @Override
  public boolean load(final String path, final File file) {

    reporter.requestLoadCount.inc();
    reporter.requestTotalCount.inc();

    try {

      final String bucket = config.bucket();

      final GetObjectRequest request = //
      new GetObjectRequest(bucket, PathHelp.rootLessPath(path));

      final ObjectMetadata result = client.getObject(request, file);

      setAvailable(true);

      return true;

    } catch (final AmazonS3Exception e) {

      switch (e.getStatusCode()) {
      case 404:
        log.error("path={} code={}", path, e.getErrorCode());
        break;
      default:
        processFailure(e);
        break;
      }
      return false;

    } catch (final Exception e) {

      processFailure(e);
      return false;

    }

  }

  protected void processFailure(final Throwable e) {

    reporter.requestFailedCount.inc();

    setAvailable(false);

    final String message = "" + e.getMessage();

    // if (amazonThrottleExceptions()) {
    // if (exceptionCache.getIfPresent(message) != null) {
    // return;
    // } else {
    // exceptionCache.put(message, "");
    // }
    // }

    log.error("amazon falilure", e);

  }

  @Override
  public boolean save(final String path, final File file) {

    reporter.requestSaveCount.inc();
    reporter.requestTotalCount.inc();

    try {

      final String bucket = config.bucket();

      final PutObjectRequest request = //
      new PutObjectRequest(bucket, PathHelp.rootLessPath(path), file);

      final PutObjectResult result = client.putObject(request);

      setAvailable(true);

      return true;

    } catch (final Exception e) {

      processFailure(e);
      return false;

    }

  }

  protected boolean setAvailable(final boolean next) {

    final boolean past = isAvailable;

    isAvailable = next;

    reporter.providerAvailable.value(isAvailable);

    return past;

  }

  @Override
  public synchronized void ensure() {
    stop();
    start();
  }

  @Override
  public synchronized void start() {

    if (config == null) {
      throw new IllegalStateException("config is missing");
    }

    if (client == null) {
      client = new AmazonS3Client(credentials());
      client.setEndpoint(config.endpoint());
    } else {
      // throw new IllegalStateException("client is present");
    }

    if (healthFuture == null) {
      final int period = config.healthPeriod();
      healthFuture = scheduler.scheduleAtFixedRate( //
          healtTask, 0, period, TimeUnit.SECONDS);
    } else {
      // throw new IllegalStateException("future is present");
    }

    checkCount = 0;

    log.info("\n\t ### start");

  }

  @Override
  public synchronized void stop() {

    if (healthFuture == null) {
      // throw new IllegalStateException("future is missing");
    } else {
      healthFuture.cancel(true);
      healthFuture = null;
    }

    if (client == null) {
      // throw new IllegalStateException("client is missing");
    } else {
      client.shutdown();
      client = null;
    }

    log.info("\n\t ### stop");

  }

  @Override
  public Reporter reporter() {
    return reporter;
  }

}
TOP

Related Classes of com.carrotgarden.nexus.aws.s3.publish.amazon.AmazonProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.