/**
* Copyright (c) 2011-2013 Optimax Software Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Optimax Software, ElasticInbox, nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.elasticinbox.core.cassandra.persistence;
import java.util.UUID;
import com.elasticinbox.core.cassandra.CassandraDAOFactory;
import static com.elasticinbox.config.DatabaseConstants.BLOB_BLOCK_SIZE;
import static com.elasticinbox.core.cassandra.CassandraDAOFactory.CF_BLOB;
import static me.prettyprint.hector.api.factory.HFactory.createColumn;
import me.prettyprint.cassandra.serializers.BytesArraySerializer;
import me.prettyprint.cassandra.serializers.CompositeSerializer;
import me.prettyprint.cassandra.serializers.IntegerSerializer;
import me.prettyprint.cassandra.serializers.UUIDSerializer;
import me.prettyprint.hector.api.beans.Composite;
import me.prettyprint.hector.api.beans.HColumn;
import me.prettyprint.hector.api.factory.HFactory;
import me.prettyprint.hector.api.mutation.Mutator;
import me.prettyprint.hector.api.query.ColumnQuery;
import me.prettyprint.hector.api.query.QueryResult;
/**
* Blob block operations. Currently supports only single block blobs.
* <p>
* Do not batch read/write requests. Delete requests can be batched up when
* multi-block operations introduced).
*
* @author Rustam Aliyev
*/
public class BlobPersistence
{
private final static IntegerSerializer intSe = IntegerSerializer.get();
private final static BytesArraySerializer byteSe = BytesArraySerializer.get();
private final static UUIDSerializer uuidSe = UUIDSerializer.get();
/** Default sub-block ID. Currently only single sub-block operations supported. */
public static int DEFAULT_SUB_BLOCK_ID = 0;
/**
* Write blob block into Cassandra.
*
* @param objectId Blob ID
* @param blockId Block ID (starting from 0)
* @param data
*/
public static void writeBlock(final UUID objectId, final int blockId, byte[] data)
{
if (data.length > BLOB_BLOCK_SIZE) {
throw new IllegalArgumentException("Data (" + data.length
+ " bytes) is larger than the maximum block size ("
+ BLOB_BLOCK_SIZE + " bytes)");
}
Mutator<Composite> mutator = HFactory.createMutator(
CassandraDAOFactory.getKeyspace(), CompositeSerializer.get());
Composite key = new Composite();
key.addComponent(objectId, uuidSe);
key.addComponent(blockId, intSe);
mutator.insert(key, CF_BLOB,
createColumn(DEFAULT_SUB_BLOCK_ID, data, intSe, byteSe));
}
/**
* Read blob block from Cassandra.
*
* @param objectId Blob ID
* @param blockId Block ID
* @return
*/
public static byte[] readBlock(final UUID objectId, final int blockId)
{
Composite key = new Composite();
key.addComponent(objectId, uuidSe);
key.addComponent(blockId, intSe);
ColumnQuery<Composite, Integer, byte[]> q = HFactory.createColumnQuery(
CassandraDAOFactory.getKeyspace(), CompositeSerializer.get(), intSe, byteSe);
QueryResult<HColumn<Integer, byte[]>> result = q.setColumnFamily(CF_BLOB)
.setKey(key).setName(DEFAULT_SUB_BLOCK_ID).execute();
return result.get().getValue();
}
/**
* Delete blob block from Cassandra.
*
* @param objectId Blob ID
* @param blockId Block ID
*/
public static void deleteBlock(final UUID objectId, final int blockId)
{
Composite key = new Composite();
key.addComponent(objectId, uuidSe);
key.addComponent(blockId, intSe);
Mutator<Composite> mutator = HFactory.createMutator(
CassandraDAOFactory.getKeyspace(), CompositeSerializer.get());
mutator.delete(key, CF_BLOB, null, intSe);
}
}