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

io.permazen.jsck.Issue 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.ObjId;
import io.permazen.kv.KVStore;
import io.permazen.schema.SchemaCompositeIndex;
import io.permazen.schema.SchemaField;
import io.permazen.util.ByteUtil;
import io.permazen.util.ParseContext;

import java.util.Arrays;
import java.util.Objects;

/**
 * Represents a point of corruption or inconsistency in a Permazen key/value database.
 *
 * 

* {@link Issue}s are specific to a single key/value pair in the database. */ public abstract class Issue { private static final int HEX_STRING_LIMIT = 100; private final String description; private final byte[] key; private final byte[] oldValue; private final byte[] newValue; private String detail; /** * Constructor. * * @param description short description of the issue * @param key key of invalid key/value pair * @param oldValue the original, invalid value for {@code key}, or null if {@code key} was missing or don't care * @param newValue the corrected replacement value for {@code key}, or null if {@code key} should be deleted * @throws IllegalArgumentException if {@code key} is null * @throws IllegalArgumentException if {@code oldValue} and {@code newValue} are equal */ protected Issue(String description, byte[] key, byte[] oldValue, byte[] newValue) { Preconditions.checkArgument(description != null, "null description"); Preconditions.checkArgument(key != null, "null key"); Preconditions.checkArgument(!Arrays.equals(oldValue, newValue) || oldValue == null, "newValue = oldValue"); this.description = description; this.key = key; this.oldValue = oldValue; this.newValue = newValue; } /** * Get the databse key. * * @return key of this issue */ public byte[] getKey() { return this.key; } /** * Get the original value, if any. * * @return original value, null if key/value pair was missing */ public byte[] getOldValue() { return this.oldValue; } /** * Get the replacement value, if any. * * @return replacement value, null if key/value pair was missing or should be deleted */ public byte[] getNewValue() { return this.newValue; } /** * Apply the fix for this issue to the given {@link KVStore}. * *

* This overwrites the key/value pair with the new value, or deletes it if {@link #getNewValue} is null. * * @param kvstore target key/value store * @throws IllegalArgumentException if {@code kvstore} is null */ public void apply(KVStore kvstore) { Preconditions.checkArgument(kvstore != null, "null kvstore"); if (this.newValue != null) kvstore.put(this.key, this.newValue); else kvstore.remove(this.key); } public Issue setDetail(String detail) { this.detail = detail; return this; } public Issue setDetail(ObjId id, String detail) { return this.setDetail("for object " + id + ": " + detail); } public Issue setDetail(ObjId id, SchemaField field, String detail) { return this.setDetail("for object " + id + " " + field + ": " + detail); } public Issue setDetail(ObjId id, SchemaCompositeIndex index, String detail) { return this.setDetail("for object " + id + " " + index + ": " + detail); } public Issue setDetail(Index index, String detail) { return this.setDetail("for " + index + ": " + detail); } // Object @Override public String toString() { final StringBuilder buf = new StringBuilder(); buf.append(this.description) .append(": key [") .append(ParseContext.truncate(ByteUtil.toString(this.key), HEX_STRING_LIMIT)) .append(']'); if (this.oldValue != null && this.newValue != null) { buf.append(": incorrect value [") .append(ParseContext.truncate(ByteUtil.toString(this.oldValue), HEX_STRING_LIMIT)) .append("]; corrected value [") .append(ParseContext.truncate(ByteUtil.toString(this.newValue), HEX_STRING_LIMIT)) .append(']'); } else if (this.oldValue != null) { buf.append(", value [") .append(ParseContext.truncate(ByteUtil.toString(this.oldValue), HEX_STRING_LIMIT)) .append(']'); } else if (this.newValue != null && this.newValue.length > 0) { buf.append(", corrected value [") .append(ParseContext.truncate(ByteUtil.toString(this.newValue), HEX_STRING_LIMIT)) .append(']'); } if (this.detail != null) { buf.append(": ") .append(this.detail); } return buf.toString(); } @Override public boolean equals(Object obj) { if (obj == null || obj.getClass() != this.getClass()) return false; final Issue that = (Issue)obj; return Arrays.equals(this.key, that.key) && Arrays.equals(this.oldValue, that.oldValue) && Arrays.equals(this.newValue, that.newValue) && Objects.equals(this.description, that.description) && Objects.equals(this.detail, that.detail); } @Override public int hashCode() { return Arrays.hashCode(this.key) ^ Arrays.hashCode(this.oldValue) ^ Arrays.hashCode(this.newValue) ^ Objects.hashCode(this.description) ^ Objects.hashCode(this.detail); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy