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

com.cloudhopper.datastore.kyoto.KyotoDataStoreIterator Maven / Gradle / Ivy

The newest version!
package com.cloudhopper.datastore.kyoto;

/*
 * #%L
 * ch-datastore
 * %%
 * Copyright (C) 2012 Cloudhopper by Twitter
 * %%
 * 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.
 * #L%
 */

import com.cloudhopper.datastore.DataStoreFatalException;
import com.cloudhopper.datastore.DataStoreIterator;
import kyotocabinet.Cursor;
import kyotocabinet.DB;
import kyotocabinet.Error;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * DateStoreIterator for Kyoto Cabinet that uses a Cursor, and assumes a .kct
 * database type.
 *
 * @author garth
 */
public class KyotoDataStoreIterator implements DataStoreIterator {

    private final static Logger logger = LoggerFactory.getLogger(KyotoDataStoreIterator.class);

    private final DB db;
    private Cursor cursor;
    private boolean firstNextCall;

    public KyotoDataStoreIterator(DB db) {
	this.db = db;
        this.cursor = db.cursor();
        // flag to indicate this is the first call to next()
        this.firstNextCall = true;
    }

    public boolean next() throws DataStoreFatalException {
        // kyoto cabinet does things a little different in that the first record
        // is already selected by default -- our interface says that you need
        // to call next() first, so we will only call next on calls after the
        // first one
        if (this.firstNextCall) {
            this.firstNextCall = false;
	    // Jump the cursor to the first record for forward scan.
            return this.cursor.jump();
        } else {
	    // Step the cursor to the next record.
            return cursor.step();
        }
    }

    public boolean jump(byte[] key) throws DataStoreFatalException {
	if (this.firstNextCall) this.firstNextCall = false;
	boolean jumped = this.cursor.jump(key);
	if (!jumped) {
	    Error e = db.error();
	    if (e != null) logger.debug("DataStoreIterator failed to jump to record {} {}", new String(key), errorToString(e));
	}
	return jumped;
    }

    public Record getRecord() throws DataStoreFatalException {
        byte[] key = cursor.get_key(false);
        byte[] value = cursor.get_value(false);
        if (key == null) {
	    Error e = db.error();
	    if (e != null) logger.warn("Kyoto reporting error {}", errorToString(e));
            throw new DataStoreFatalException("Record key was null", e);
	}
	if (value == null) {
	    Error e = db.error();
	    if (e != null) logger.warn("Kyoto reporting error {}", errorToString(e));
            throw new DataStoreFatalException("Record value for key "+new String(key)+" was null", e);
        }
        return new Record(key, value);
    }

    public void close() throws DataStoreFatalException {
        // This method should be called explicitly when the cursor is no longer in use.
	cursor.disable();
        cursor = null;
    }

    private String errorToString(Error e) {
        return new StringBuilder()
            .append("[code=")
            .append(e.code())
            .append(", name=")
            .append(e.name())
            .append(", message=")
            .append(e.message())
            .append("]")
            .toString();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy