org.stem.client.MetaStoreClient.java Source code

Java tutorial

Introduction

Here is the source code for org.stem.client.MetaStoreClient.java

Source

/*
 * Copyright 2014 Alexey Plotnik
 *
 * 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.stem.client;

import com.datastax.driver.core.*;
import com.datastax.driver.core.policies.DowngradingConsistencyRetryPolicy;
import com.datastax.driver.core.policies.ExponentialReconnectionPolicy;
import com.datastax.driver.core.policies.RoundRobinPolicy;
import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.apache.commons.lang3.Validate;
import org.stem.domain.ExtendedBlobDescriptor;
import org.stem.domain.Schema;

import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.List;
import java.util.UUID;

public class MetaStoreClient {

    private static final String INSERT_STATEMENT = "INSERT INTO stem.blobs_meta (blob, disk, data) VALUES (?, ?, ?)";
    private static final String SELECT_STATEMENT = "SELECT * FROM stem.blobs_meta WHERE blob = ?";
    private static final String SELECT_REPLICA_STATEMENT = "SELECT * FROM stem.blobs_meta WHERE blob = ? AND disk = ?";
    private static final String UPDATE_STATEMENT = "UPDATE stem.blobs_meta SET data = ? WHERE blob = ? AND disk = ?";
    private static final String DELETE_STATEMENT = "DELETE FROM stem.blobs_meta WHERE blob = ?";
    private static final String DELETE_REPLICA_STATEMENT = "DELETE FROM stem.blobs_meta WHERE blob=? AND disk=?";

    protected Cluster cluster;
    protected Session session;
    private volatile boolean started;
    private volatile boolean statementsPrepared;

    private PreparedStatement insertToBlobsMeta;
    private PreparedStatement selectBlobsMeta;
    private PreparedStatement selectReplicaBlobsMeta;
    private PreparedStatement updateBlobsMeta;
    private PreparedStatement deleteBlobsMeta;
    private PreparedStatement deleteReplicaBlobsMeta;

    public MetaStoreClient(String... contactPoints) {
        if (contactPoints.length == 0)
            throw new RuntimeException("No contact points specified");

        cluster = Cluster.builder().addContactPoints(contactPoints).withClusterName(Schema.CLUSTER)
                .withLoadBalancingPolicy(new RoundRobinPolicy())
                .withRetryPolicy(DowngradingConsistencyRetryPolicy.INSTANCE)
                .withReconnectionPolicy(new ExponentialReconnectionPolicy(100, 10000)).withoutMetrics().build();
    }

    public void start() {
        start(true);
    }

    protected void start(boolean prepareStatements) {
        if (started)
            throw new IllegalStateException("Cassandra client is already started");

        session = cluster.connect();

        if (prepareStatements)
            maybePrepareStatements();

        started = true;
    }

    public boolean isStarted() {
        return started;
    }

    private void prepareStatements() {
        session.execute("use stem");

        insertToBlobsMeta = session.prepare(INSERT_STATEMENT);
        selectBlobsMeta = session.prepare(SELECT_STATEMENT);
        selectReplicaBlobsMeta = session.prepare(SELECT_REPLICA_STATEMENT);
        updateBlobsMeta = session.prepare(UPDATE_STATEMENT);
        deleteBlobsMeta = session.prepare(DELETE_STATEMENT);
        deleteReplicaBlobsMeta = session.prepare(DELETE_REPLICA_STATEMENT);
    }

    private void maybePrepareStatements() {
        if (!statementsPrepared) {
            prepareStatements();
            statementsPrepared = true;
        }
    }

    public void stop() {
        cluster.close();
    }

    public Session getSession() {
        return session;
    }

    public List<ExtendedBlobDescriptor> readMeta(byte[] key) {
        BoundStatement statement = selectBlobsMeta.bind(ByteBuffer.wrap(key));
        List<Row> rows = getSession().execute(statement).all();

        List<ExtendedBlobDescriptor> results = Lists.newArrayList();

        for (Row row : rows) {
            ExtendedBlobDescriptor writeResult = extractMeta(row);
            results.add(writeResult);
        }
        return results;
    }

    public ExtendedBlobDescriptor readMeta(byte[] key, UUID diskId) {
        maybePrepareStatements();
        BoundStatement statement = selectReplicaBlobsMeta.bind(ByteBuffer.wrap(key), diskId);
        Row row = getSession().execute(statement).one(); // TODO: check is there are many replicas for this particular blob and disk ??? (is it possible?)
        if (null == row)
            return null;

        return extractMeta(row);
    }

    public void writeMeta(Collection<ExtendedBlobDescriptor> results) {
        maybePrepareStatements();
        BatchStatement batch = new BatchStatement();
        for (ExtendedBlobDescriptor wr : results) {
            ByteBuffer key = ByteBuffer.wrap(wr.getKey());
            ByteBuffer data = buildMeta(wr.getFFIndex(), wr.getBodyOffset(), wr.getLength());

            batch.add(insertToBlobsMeta.bind(key, wr.getDisk(), data));
        }
        ResultSet execute = session.execute(batch);
        // TODO: continue here
    }

    public void updateMeta(ExtendedBlobDescriptor d) {
        updateMeta(d.getKey(), d.getDisk(), d.getFFIndex(), d.getBodyOffset(), d.getLength());
    }

    public void updateMeta(byte[] key, UUID diskId, int fatFileIndex, int offset, int length) {
        maybePrepareStatements();
        ByteBuffer data = buildMeta(fatFileIndex, offset, length);
        BoundStatement statement = updateBlobsMeta.bind(data, ByteBuffer.wrap(key), diskId);
        session.execute(statement);
    }

    public void deleteMeta(byte[] key) {
        maybePrepareStatements();
        BoundStatement statement = deleteBlobsMeta.bind(ByteBuffer.wrap(key));
        getSession().execute(statement);
    }

    public void deleteReplica(byte[] key, UUID diskId) {
        maybePrepareStatements();
        BoundStatement statement = deleteReplicaBlobsMeta.bind(ByteBuffer.wrap(key), diskId);
        getSession().execute(statement);
    }

    private ByteBuffer buildMeta(int fatFileIndex, int offset, int length) {
        ByteBuf b = Unpooled.buffer(12);
        b.writeInt(fatFileIndex);
        b.writeInt(offset);
        b.writeInt(length);

        return b.nioBuffer();
    }

    private ExtendedBlobDescriptor extractMeta(Row row) {
        ByteBuffer keyBuf = row.getBytes("blob");
        byte[] key = new byte[keyBuf.remaining()];
        keyBuf.get(key, 0, key.length);

        UUID disk = row.getUUID("disk");
        ByteBuffer data = row.getBytes("data");
        Validate.notNull(data);

        ByteBuf buf = Unpooled.wrappedBuffer(data);
        int fatFileIndex = buf.readInt();
        int offset = buf.readInt();
        int length = buf.readInt();

        return new ExtendedBlobDescriptor(key, length, disk, fatFileIndex, -1, offset);
    }
}