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

net.openhft.chronicle.wire.HashWire Maven / Gradle / Ivy

There is a newer version: 2.27ea1
Show newest version
/*
 * Copyright 2016-2020 chronicle.software
 *
 *       https://chronicle.software
 *
 * 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 net.openhft.chronicle.wire;

import net.openhft.chronicle.bytes.Bytes;
import net.openhft.chronicle.bytes.HexDumpBytesDescription;
import net.openhft.chronicle.bytes.BytesStore;
import net.openhft.chronicle.bytes.CommonMarshallable;
import net.openhft.chronicle.core.Maths;
import net.openhft.chronicle.core.io.InvalidMarshallableException;
import net.openhft.chronicle.core.pool.ClassAliasPool;
import net.openhft.chronicle.core.pool.ClassLookup;
import net.openhft.chronicle.core.values.*;
import net.openhft.chronicle.threads.Pauser;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.ObjectOutput;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
/**
 * The {@code HashWire} class is responsible for generating hash values from provided objects or {@link WriteMarshallable} instances.
 * 

* This class provides a consistent hashing mechanism by leveraging a predefined set of constants and algorithms. * Instances are stored in a {@code ThreadLocal} to ensure thread-safety and optimized access across the application. * * @see WriteMarshallable */ @SuppressWarnings("rawtypes") public class HashWire implements WireOut, HexDumpBytesDescription { // Thread-local storage for HashWire instances. private static final ThreadLocal hwTL = new ThreadLocal() { @Override protected HashWire initialValue() { return new HashWire(); } @Override public HashWire get() { HashWire hashWire = super.get(); hashWire.hash = 0; return hashWire; } }; // Hashing constants private static final int K0 = 0x6d0f27bd; private static final int M0 = 0x5bc80bad; private static final int M1 = 0xea7585d7; private static final int M2 = 0x7a646e19; private static final int M3 = 0x855dd4db; // Value output for hashing. private final ValueOut valueOut = new HashValueOut(); // Current hash value. long hash = 0; /** * Computes a 64-bit hash for the provided {@link WriteMarshallable} value. * * @param value The {@link WriteMarshallable} value to be hashed. * @return The 64-bit hash value. */ public static long hash64(WriteMarshallable value) { return hash64((Object) value); } /** * Computes a 64-bit hash for the provided object. * * @param value The object to be hashed. * @return The 64-bit hash value. */ public static long hash64(Object value) { @NotNull HashWire hashWire = hwTL.get(); hashWire.getValueOut().object(value); return hashWire.hash64(); } /** * Computes a 32-bit hash for the provided {@link WriteMarshallable} value. * * @param value The {@link WriteMarshallable} value to be hashed. * @return The 32-bit hash value. */ public static int hash32(WriteMarshallable value) { return hash32((Object) value); } /** * Computes a 32-bit hash for the provided object. * * @param value The object to be hashed. * @return The 32-bit hash value. */ public static int hash32(Object value) { @NotNull HashWire hashWire = hwTL.get(); hashWire.getValueOut().object(value); return hashWire.hash32(); } @Override public void classLookup(ClassLookup classLookup) { // Do nothing } @Override public ClassLookup classLookup() { return ClassAliasPool.CLASS_ALIASES; } @Override public void clear() { hash = 0; } @Override public void reset() { clear(); } @Nullable @Override public Object parent() { return null; } @Override public void parent(Object parent) { throw new UnsupportedOperationException(); } @Override public void usePadding(boolean usePadding) { throw new UnsupportedOperationException(); } @Override public boolean usePadding() { return false; } /** * Computes and returns the 64-bit hash value. *

* This method uses the current hash value and applies an agitation function to provide * a consistent and dispersed 64-bit hash result. * * @return The 64-bit agitated hash value. */ public long hash64() { return Maths.agitate(hash); } /** * Computes and returns the 32-bit hash value. *

* This method derives the 32-bit hash from the 64-bit hash value. The derived hash is * the result of XOR-ing the high and low 32-bits of the 64-bit hash. * * @return The derived 32-bit hash value. */ public int hash32() { long h = hash64(); return (int) (h ^ (h >>> 32)); } @NotNull @Override public ValueOut write() { hash += K0; return valueOut; } @NotNull @Override public ValueOut write(@NotNull WireKey key) { return write(key.name()); } @NotNull @Override public ValueOut write(@NotNull CharSequence name) { hash += K0 + name.hashCode() * M0; return valueOut; } @NotNull @Override public ValueOut writeEvent(Class ignored, @NotNull Object eventKey) { hash += K0 + eventKey.hashCode() * M0; return valueOut; } @Override public void writeStartEvent() { // No nothing } @Override public void writeEndEvent() { // No nothing } @NotNull @Override public ValueOut getValueOut() { return valueOut; } @NotNull @Override public ObjectOutput objectOutput() { return new WireObjectOutput(this); } @NotNull @Override public WireOut writeComment(CharSequence s) { return this; } @NotNull @Override public WireOut addPadding(int paddingToAdd) { return this; } @NotNull @Override public WireOut headerNumber(long headerNumber) { throw new UnsupportedOperationException(); } @Override public long headerNumber() { return 0; } @NotNull @Override public DocumentContext writingDocument(boolean metaData) { throw new UnsupportedOperationException("todo"); } @Override public DocumentContext acquireWritingDocument(boolean metaData) { throw new UnsupportedOperationException(); } @Override public long enterHeader(final long safeLength) { throw new UnsupportedOperationException(); } @Override public void updateHeader(long position, boolean metaData, int expectedHeader) { throw new UnsupportedOperationException(); } @Override public boolean writeFirstHeader() { throw new UnsupportedOperationException(); } @Override public void updateFirstHeader() { throw new UnsupportedOperationException(); } @Override public void updateFirstHeader(long headerLen) { throw new UnsupportedOperationException(); } @Override public boolean writeEndOfWire(long timeout, TimeUnit timeUnit, long lastPosition) { throw new UnsupportedOperationException(); } @NotNull @Override public Bytes bytes() { throw new UnsupportedOperationException(); } @Override public HexDumpBytesDescription bytesComment() { return this; } @NotNull @Override public IntValue newIntReference() { throw new UnsupportedOperationException(); } @NotNull @Override public LongValue newLongReference() { throw new UnsupportedOperationException(); } @NotNull @Override public BooleanValue newBooleanReference() { throw new UnsupportedOperationException(); } @Override public boolean useSelfDescribingMessage(@NotNull CommonMarshallable object) { return object.usesSelfDescribingMessage(); } @Override public boolean isBinary() { return true; // text wire is orders of magnitude slower } @NotNull @Override public LongArrayValues newLongArrayReference() { throw new UnsupportedOperationException(); } @Override public @NotNull IntArrayValues newIntArrayReference() { throw new UnsupportedOperationException(); } @NotNull @Override public Pauser pauser() { throw new UnsupportedOperationException(); } @Override public void pauser(Pauser pauser) { throw new UnsupportedOperationException(); } /** * The {@code HashValueOut} class is responsible for updating the hash value of * the {@link HashWire} based on the type of value being processed. *

* The class implements the {@link ValueOut} interface, providing methods to handle * various data types like booleans, text, bytes, etc., and updating the hash * value accordingly. */ class HashValueOut implements ValueOut { @NotNull @Override public WireOut bool(Boolean flag) { hash = hash * M1 + (flag ? M2 : M3); return HashWire.this; } @NotNull @Override public WireOut text(@Nullable CharSequence s) { hash = hash * M1 + (s == null ? 0 : Maths.hash64(s)); return HashWire.this; } @NotNull @Override public WireOut int8(byte i8) { hash = hash * M1 + i8 * M2; return HashWire.this; } @NotNull @Override public WireOut bytes(@Nullable BytesStore fromBytes) { hash = hash * M1 + Maths.hash64(fromBytes); return HashWire.this; } @NotNull @Override public WireOut bytes(@NotNull String type, @Nullable BytesStore fromBytes) { hash = hash * M1 + Maths.hash64(type) ^ Maths.hash64(fromBytes); return HashWire.this; } @NotNull @Override public WireOut rawBytes(@NotNull byte[] value) { hash = hash * M1 + Maths.hash64(Bytes.wrapForRead(value)); return HashWire.this; } @NotNull @Override public ValueOut writeLength(long remaining) { hash = hash * M1 + remaining * M3; return this; } @NotNull @Override public WireOut bytes(@NotNull byte[] fromBytes) { hash = hash * M1 + Maths.hash64(Bytes.wrapForRead(fromBytes)); return HashWire.this; } @NotNull @Override public WireOut bytes(@NotNull String type, @NotNull byte[] fromBytes) { hash = hash * M1 + Maths.hash64(type) ^ Maths.hash64(Bytes.wrapForRead(fromBytes)); return HashWire.this; } @NotNull @Override public WireOut uint8checked(int u8) { hash = hash * M1 + u8 * M2; return HashWire.this; } @NotNull @Override public WireOut int16(short i16) { hash = hash * M1 + i16 * M2; return HashWire.this; } @NotNull @Override public WireOut uint16checked(int u16) { hash = hash * M1 + u16 * M2; return HashWire.this; } @NotNull @Override public WireOut utf8(int codepoint) { hash = hash * M1 + codepoint * M2; return HashWire.this; } @NotNull @Override public WireOut int32(int i32) { hash = hash * M1 + i32 * M2; return HashWire.this; } @NotNull @Override public WireOut uint32checked(long u32) { hash = hash * M1 + u32 * M2; return HashWire.this; } @NotNull @Override public WireOut int64(long i64) { hash = hash * M1 + i64 * M2; return HashWire.this; } @NotNull @Override public WireOut int128forBinding(long i64x0, long i64x1, TwoLongValue longValue) { throw new UnsupportedOperationException("todo"); } @NotNull @Override public WireOut int64_0x(long i64) { return int64(i64); } @NotNull @Override public WireOut int64array(long capacity) { hash = hash * M1 + capacity * M2; return HashWire.this; } @NotNull @Override public WireOut int64array(long capacity, LongArrayValues values) { throw new UnsupportedOperationException(); } @NotNull @Override public WireOut float32(float f) { hash = hash * M1 + Float.floatToRawIntBits(f) * M2; return HashWire.this; } @NotNull @Override public WireOut float64(double d) { hash = hash * M1 + Double.doubleToRawLongBits(d) * M2; return HashWire.this; } @NotNull @Override public WireOut time(@NotNull LocalTime localTime) { hash = hash * M1 + localTime.hashCode() * M2; return HashWire.this; } @NotNull @Override public WireOut zonedDateTime(@NotNull ZonedDateTime zonedDateTime) { hash = hash * M1 + zonedDateTime.hashCode() * M2; return HashWire.this; } @NotNull @Override public WireOut date(@NotNull LocalDate localDate) { hash = hash * M1 + localDate.hashCode() * M2; return HashWire.this; } @NotNull @Override public WireOut dateTime(@NotNull LocalDateTime localDateTime) { hash = hash * M1 + localDateTime.hashCode() * M2; return HashWire.this; } @NotNull @Override public ValueOut typePrefix(@NotNull CharSequence typeName) { hash = hash * M1 + typeName.hashCode() * M2; return this; } @Override public ClassLookup classLookup() { return HashWire.this.classLookup(); } @NotNull @Override public WireOut typeLiteral(@Nullable CharSequence type) { hash = hash * M1 + (type == null ? 0 : type.hashCode() * M2); return HashWire.this; } @NotNull @Override public WireOut typeLiteral(@NotNull BiConsumer> typeTranslator, @Nullable Class type) { hash = hash * M1 + (type == null ? 0 : type.hashCode() * M2); return HashWire.this; } @NotNull @Override public WireOut uuid(@NotNull UUID uuid) { hash = hash * M1 + uuid.hashCode() * M2; return HashWire.this; } @NotNull @Override public WireOut int32forBinding(int value) { throw new UnsupportedOperationException("todo"); } @NotNull @Override public WireOut int32forBinding(int value, @NotNull IntValue intValue) { throw new UnsupportedOperationException("todo"); } @NotNull @Override public WireOut int64forBinding(long value) { throw new UnsupportedOperationException("todo"); } @NotNull @Override public WireOut int64forBinding(long value, @NotNull LongValue longValue) { throw new UnsupportedOperationException("todo"); } @NotNull @Override public WireOut boolForBinding(final boolean value, @NotNull final BooleanValue longValue) { throw new UnsupportedOperationException("todo"); } @NotNull @Override public WireOut sequence(T t, @NotNull BiConsumer writer) { writer.accept(t, this); return HashWire.this; } @NotNull @Override public WireOut sequence(T t, K kls, @NotNull TriConsumer writer) throws InvalidMarshallableException { writer.accept(t, kls, this); return HashWire.this; } @NotNull @Override public WireOut marshallable(@NotNull WriteMarshallable object) throws InvalidMarshallableException { object.writeMarshallable(HashWire.this); return HashWire.this; } @NotNull @Override public WireOut marshallable(@NotNull Serializable object) throws InvalidMarshallableException { Wires.writeMarshallable(object, HashWire.this); return HashWire.this; } @NotNull @Override public WireOut map(@NotNull Map map) { hash = hash * M1 + map.hashCode() * M2; return HashWire.this; } @NotNull @Override public WireOut wireOut() { return HashWire.this; } @Override public void resetState() { // No nothing } @Override public void elementSeparator() { } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy