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

org.akubraproject.mux.AbstractMuxConnection Maven / Gradle / Ivy

There is a newer version: 0.4.0
Show newest version
/* $HeadURL::                                                                            $
 * $Id$
 *
 * Copyright (c) 2009-2010 DuraSpace
 * http://duraspace.org
 *
 * In collaboration with Topaz Inc.
 * http://www.topazproject.org
 *
 * 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 org.akubraproject.mux;

import java.io.IOException;

import java.net.URI;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.transaction.Transaction;

import com.google.common.collect.Iterators;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.akubraproject.Blob;
import org.akubraproject.BlobStore;
import org.akubraproject.BlobStoreConnection;
import org.akubraproject.UnsupportedIdException;
import org.akubraproject.impl.AbstractBlobStoreConnection;

/**
 * An abstract base class for connections returned by multiplexing BlobStores. Sub-class
 * implementations must provide a {@link #getStore} implementation. Additionally for multiplexing
 * content addressable stores, sub-classes must override the default implementation of {@link
 * org.akubraproject.impl.AbstractBlobStoreConnection#getBlob(java.io.InputStream, long,
 * Map)} and direct the call to the appropriate backing store. Note that the returned Blob from
 * the backing store must be wrapped so that the {@link
 * org.akubraproject.Blob#getConnection()} of the returned Blob will return this connection
 * object.
 *
 * @author Pradeep Krishnan
 *
 * @see #getStore(URI, Map)
 * @see #getStores(String)
 * @see #getConnection(BlobStore, Map)
 * @see MuxBlob
 */
public abstract class AbstractMuxConnection extends AbstractBlobStoreConnection {
  private static final Logger log = LoggerFactory.getLogger(AbstractBlobStoreConnection.class);

  /**
   * The transaction to pass to while opening connections to the backing stores. Note that
   * this transaction is only passed to transaction capable stores. A null is passed for
   * non-transactional stores.
   *
   * @see #getConnection(BlobStore, Map)
   */
  protected final Transaction txn;

  /**
   * A map of store-ids to connections.
   *
   * @see #getConnection(BlobStore, Map)
   * @see #close()
   */
  protected Map cons = new HashMap();

  /**
   * Creates a new AbstractMuxConnection object.
   *
   * @param store the mux store
   * @param txn the txn passed in by the user
   */
  public AbstractMuxConnection(BlobStore store, Transaction txn) {
    super(store);
    this.txn = txn;
  }

  /**
   * Gets the backing store where the given blob is persisted.
   *
   * @param blobId the blob id (can be null)
   * @param hints A set of hints to allow the implementation to optimize the operation (can be
   *        null)
   *
   * @return the store. Cannot be null and must be one of the backing stores.
   *
   * @throws IOException for IO errors
   * @throws UnsupportedIdException if blobId is not in a recognized/usable pattern by any of the
   *         backing stores
   */
  public abstract BlobStore getStore(URI blobId, Map hints)
                              throws IOException, UnsupportedIdException;

  /**
   * Gets the set of a backing stores matching the given blobId prefix. By default the
   * returned set is the set of all backing stores. Override in sub-classes to narrow down the
   * set.
   *
   * @param prefix the blobId prefix or null
   *
   * @return the set of stores matching the blobId prefix
   */
  public Set getStores(String prefix) {
    return new HashSet(((AbstractMuxStore) getBlobStore()).getBackingStores());
  }

  /**
   * Closes this connection and all underlying connections created using {@link
   * #getConnection(BlobStore, Map)}.
   */
  @Override
  public void close() {
    super.close();

    if (cons != null) {
      for (BlobStoreConnection con : cons.values())
        con.close();

      cons.clear();
      cons = null;
    }
  }

  /**
   * Lookup/Create a connection to the given backing store.
   *
   * @param store the backing store
   * @param hints A set of hints to allow the implementation to optimize the operation (can be
   *              null)
   *
   * @return the backing store connection or null
   *
   * @throws IOException on an error in opening a connection to the backing store
   * @throws UnsupportedOperationException on an error in opening a connection to the backing store
   */
  protected BlobStoreConnection getConnection(BlobStore store, Map hints)
                                       throws IOException {
    if (store == null)
      return null;

    if (cons == null)
      throw new IllegalStateException("Connection closed.");

    BlobStoreConnection con = cons.get(store.getId());

    if (con == null) {
      con = store.openConnection(txn, hints);
      cons.put(store.getId(), con);
    }

    return con;
  }

  @Override
  public Blob getBlob(URI blobId, Map hints)
               throws IOException {
    return new MuxBlob(getConnection(getStore(blobId, hints), hints).getBlob(blobId, hints), this);
  }

  @Override
  public Iterator listBlobIds(String filterPrefix) throws IOException {
    List> iterators = new ArrayList>();

    for (BlobStore store : getStores(filterPrefix))
      iterators.add(getConnection(store, null).listBlobIds(filterPrefix));

    return Iterators.concat(iterators.iterator());
  }

  @Override
  public void sync() throws IOException {
    if (cons == null)
      throw new IllegalStateException("Connection closed.");

    Exception exc = null;

    for (BlobStoreConnection con : cons.values()) {
      try {
        con.sync();
      } catch (Exception e) {
        if (exc == null)
          exc = e;
        else
          log.warn("Error sync'ing connection " + con, e);
      }
    }

    if (exc instanceof IOException)
      throw (IOException) exc;
    if (exc instanceof RuntimeException)
      throw (RuntimeException) exc;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy