org.lilyproject.repository.impl.HBaseBlobStoreAccess.java Source code

Java tutorial

Introduction

Here is the source code for org.lilyproject.repository.impl.HBaseBlobStoreAccess.java

Source

/*
 * Copyright 2010 Outerthought bvba
 *
 * 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.lilyproject.repository.impl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import org.apache.commons.codec.binary.Hex;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HTableInterface;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.util.Bytes;
import org.lilyproject.repository.api.Blob;
import org.lilyproject.repository.api.BlobException;
import org.lilyproject.repository.api.BlobStoreAccess;
import org.lilyproject.util.hbase.HBaseTableFactory;
import org.lilyproject.util.hbase.HBaseTableFactoryImpl;

public class HBaseBlobStoreAccess implements BlobStoreAccess {

    private static final byte[] BLOB_TABLE = Bytes.toBytes("blob");
    private static final String ID = "HBASE";
    private static final String BLOBS_COLUMN_FAMILY = "data";
    private static final byte[] BLOBS_COLUMN_FAMILY_BYTES = Bytes.toBytes(BLOBS_COLUMN_FAMILY);
    private static final byte[] BLOB_COLUMN = Bytes.toBytes("b");

    private boolean clientMode = false;
    private HTableInterface table;

    public HBaseBlobStoreAccess(Configuration hbaseConf) throws IOException, InterruptedException {
        this(hbaseConf, false);
    }

    public HBaseBlobStoreAccess(Configuration hbaseConf, boolean clientMode)
            throws IOException, InterruptedException {
        this(new HBaseTableFactoryImpl(hbaseConf), clientMode);
    }

    public HBaseBlobStoreAccess(HBaseTableFactory tableFactory) throws IOException, InterruptedException {
        this(tableFactory, false);
    }

    public HBaseBlobStoreAccess(HBaseTableFactory tableFactory, boolean clientMode)
            throws IOException, InterruptedException {
        HTableDescriptor tableDescriptor = new HTableDescriptor(BLOB_TABLE);
        tableDescriptor.addFamily(new HColumnDescriptor(BLOBS_COLUMN_FAMILY));

        table = tableFactory.getTable(tableDescriptor, !clientMode);
    }

    @Override
    public String getId() {
        return ID;
    }

    @Override
    public OutputStream getOutputStream(Blob blob) throws BlobException {
        UUID uuid = UUID.randomUUID();
        byte[] blobKey = Bytes.toBytes(uuid.getMostSignificantBits());
        blobKey = Bytes.add(blobKey, Bytes.toBytes(uuid.getLeastSignificantBits()));
        return new HBaseBlobOutputStream(table, blobKey, blob);
    }

    @Override
    public InputStream getInputStream(byte[] blobKey) throws BlobException {
        Get get = new Get(blobKey);
        get.addColumn(BLOBS_COLUMN_FAMILY_BYTES, BLOB_COLUMN);
        Result result;
        try {
            result = table.get(get);
        } catch (IOException e) {
            throw new BlobException("Failed to open an inputstream for blobkey '" + Hex.encodeHexString(blobKey)
                    + "' on the HBASE blobstore", e);
        }
        byte[] value = result.getValue(BLOBS_COLUMN_FAMILY_BYTES, BLOB_COLUMN);
        if (value == null) {
            throw new BlobException("Failed to open an inputstream for blobkey '" + Hex.encodeHexString(blobKey)
                    + "' since no blob was found on the HBASE blobstore");
        }
        return new ByteArrayInputStream(value);
    }

    @Override
    public void delete(byte[] blobKey) throws BlobException {
        Delete delete = new Delete(blobKey);
        try {
            table.delete(delete);
        } catch (IOException e) {
            throw new BlobException(
                    "Failed to delete blob with key '" + Hex.encodeHexString(blobKey) + "' from the DFS blobstore",
                    e);
        }
    }

    @Override
    public boolean incubate() {
        return true;
    }

    private class HBaseBlobOutputStream extends ByteArrayOutputStream {

        private final HTableInterface blobTable;
        private final byte[] blobKey;
        private final Blob blob;

        HBaseBlobOutputStream(HTableInterface table, byte[] blobKey, Blob blob) {
            super();
            blobTable = table;
            this.blobKey = blobKey;
            this.blob = blob;
        }

        @Override
        public void close() throws IOException {
            super.close();
            byte[] bytes = toByteArray();
            Put put = new Put(blobKey);
            put.add(BLOBS_COLUMN_FAMILY_BYTES, BLOB_COLUMN, bytes);
            blobTable.put(put);
            blob.setValue(blobKey);
        }
    }
}