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

io.permazen.jsck.Storage Maven / Gradle / Ivy

Go to download

Permazen analog to UNIX fsck(8) command for checking the consistency of, and repairing any corruption in, a Permazen key/value database

There is a newer version: 5.1.0
Show newest version

/*
 * Copyright (C) 2015 Archie L. Cobbs. All rights reserved.
 */

package io.permazen.jsck;

import com.google.common.base.Preconditions;

import io.permazen.core.FieldType;
import io.permazen.core.ObjId;
import io.permazen.kv.KeyRange;
import io.permazen.util.ByteReader;
import io.permazen.util.ByteWriter;
import io.permazen.util.UnsignedIntEncoder;

import java.util.Arrays;

/**
 * Represents a storage ID used for stored information.
 */
abstract class Storage {

    protected final JsckInfo info;
    protected final int storageId;

    private int schemaVersion;

    protected Storage(JsckInfo info, int storageId) {
        Preconditions.checkArgument(info != null, "null info");
        Preconditions.checkArgument(storageId > 0, "non-positive storageId");
        this.info = info;
        this.storageId = storageId;
    }

    /**
     * Get one schema version where this storage is defined. Informational only - not included in {@link #equals equals()}.
     */
    public int getSchemaVersion() {
        return this.schemaVersion;
    }
    public void setSchemaVersion(int schemaVersion) {
        this.schemaVersion = schemaVersion;
    }

    /**
     * Get corresponding storage ID.
     */
    public int getStorageId() {
        return this.storageId;
    }

    /**
     * Get key range.
     */
    public KeyRange getKeyRange() {
        return KeyRange.forPrefix(UnsignedIntEncoder.encode(this.storageId));
    }

    /**
     * Validate the object actually exists.
     *
     * 

* If we are not repairing, this does nothing. */ protected void validateObjectExists(JsckInfo info, ByteReader reader, ObjId id) { if (info.getConfig().isRepair() && info.getKVStore().get(id.getBytes()) == null) throw new IllegalArgumentException("object with " + id + " does not exist"); } /** * Validate proper encoding of a field value. * * @return encoded field value */ protected byte[] validateEncodedBytes(ByteReader reader, FieldType type) { // Decode value and capture bytes final T value; final int off = reader.getOffset(); try { value = type.read(reader); } catch (IndexOutOfBoundsException e) { throw new IllegalArgumentException("can't decode value of " + type + " because value is truncated"); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("can't decode value of " + type + ": " + e.getMessage()); } final int len = reader.getOffset() - off; final byte[] bytes = reader.getBytes(off, len); // Verify correct and consistent encoding final ByteWriter writer = new ByteWriter(bytes.length); try { type.write(writer, value); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("decoding then re-encoding value " + Jsck.ds(bytes) + " (" + value + ") using " + type + " throws " + e, e); } final byte[] bytes2 = writer.getBytes(); if (!Arrays.equals(bytes2, bytes)) { throw new IllegalArgumentException("decoding then re-encoding value " + Jsck.ds(bytes) + " (" + value + ") using " + type + " results in" + " a different value " + Jsck.ds(bytes2)); } // Done return bytes; } /** * Same as {@link #validateEncodedBytes validateEncodedBytes()} but returns the decoded value. * * @return decoded field value */ protected T validateEncodedValue(ByteReader reader, FieldType type) { return type.read(new ByteReader(this.validateEncodedBytes(reader, type))); } protected void validateEOF(ByteReader reader) { if (reader.remain() > 0) { throw new IllegalArgumentException("value contains extra trailing garbage " + Jsck.ds(reader.getBytes(reader.getOffset()))); } } /** * Instantiate a {@link ByteWriter} and write the given {@link ObjId} and field storage ID into it. */ protected ByteWriter buildFieldKey(ObjId id, int storageId) { final ByteWriter writer = new ByteWriter(); id.writeTo(writer); UnsignedIntEncoder.write(writer, storageId); return writer; } // Object @Override public abstract String toString(); public boolean isCompatible(Storage that) { if (this.storageId != that.storageId) return false; if (this.getClass() != that.getClass()) return false; return true; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy