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

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

The 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.core.annotation.DontChain;
import net.openhft.chronicle.core.io.InvalidMarshallableException;
import org.jetbrains.annotations.NotNull;

import java.io.ObjectOutput;
import java.io.StreamCorruptedException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Defines the standard interface for sequential writing to a Bytes stream.
 */
@DontChain
public interface WireOut extends WireCommon, MarshallableOut {
    /**
     * Writes an empty field marker to the stream.
     *
     * @return An interface to further define the output for the written value.
     */
    @NotNull
    ValueOut write();

    /**
     * Writes a key to the stream. For RAW types, the label will be in text.
     * This can be read using readEventName().
     *
     * @param key The key to write to the stream.
     * @return An interface to further define the output for the written value.
     */
    @NotNull
    default ValueOut writeEventName(WireKey key) {
        return write(key);
    }

    /**
     * Writes a CharSequence key to the stream.
     *
     * @param key The CharSequence key to write to the stream.
     * @return An interface to further define the output for the written value.
     */
    default ValueOut writeEventName(CharSequence key) {
        return write(key);
    }

    /**
     * Writes an event to the stream based on the type and event key.
     *
     * @param expectedType The expected type of the event to write.
     * @param eventKey The key of the event.
     * @return An interface to further define the output for the written value.
     * @throws InvalidMarshallableException if there's an error marshalling the event.
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    default ValueOut writeEvent(Class expectedType, Object eventKey) throws InvalidMarshallableException {
        if (eventKey instanceof WireKey)
            return writeEventName((WireKey) eventKey);
        if (eventKey instanceof CharSequence)
            return writeEventName((CharSequence) eventKey);
        writeStartEvent();
        getValueOut().object(expectedType, eventKey);
        writeEndEvent();
        return getValueOut();
    }

    /**
     * Writes an event identifier to the stream.
     *
     * @param methodId The ID of the method representing the event.
     * @return An interface to further define the output for the written value.
     */
    default ValueOut writeEventId(int methodId) {
        return write(new MethodWireKey(null, methodId));
    }

    /**
     * Writes an event identifier with a name to the stream.
     *
     * @param name The name of the event.
     * @param methodId The ID of the method representing the event.
     * @return An interface to further define the output for the written value.
     */
    default ValueOut writeEventId(String name, int methodId) {
        return write(new MethodWireKey(name, methodId));
    }

    /**
     * Writes a WireKey to the stream. This method is typically used for
     * wires that support fields with structured keys.
     *
     * @param key The WireKey to write to the stream.
     * @return An interface to further define the output for the written value.
     */
    @NotNull
    ValueOut write(WireKey key);

    /**
     * Writes a CharSequence key to the stream. This provides flexibility
     * to write non-standard keys to the wire.
     *
     * @param key The CharSequence key to write to the stream.
     * @return An interface to further define the output for the written value.
     */
    ValueOut write(CharSequence key);

    /**
     * Retrieves the interface for defining the output of a value
     * that will be written to the stream.
     *
     * @return The interface to further define the output for the written value.
     */
    @NotNull
    ValueOut getValueOut();

    /**
     * Get the ObjectOutput associated with this WireOut.
     *
     * @return The ObjectOutput associated with this WireOut.
     */
    ObjectOutput objectOutput();

    /**
     * Writes a comment to the wire. Comments may be useful for debugging
     * or providing context within the wire stream.
     *
     * @param s The comment to be written to the stream.
     * @return This WireOut instance for method chaining.
     */
    @NotNull
    WireOut writeComment(CharSequence s);

    /**
     * Adds padding to the wire. This is particularly useful for aligning data.
     *
     * @param paddingToAdd The amount of padding to add.
     * @return This WireOut instance for method chaining.
     */
    @NotNull
    WireOut addPadding(int paddingToAdd);

    /**
     * Ensures that the wire's output aligns with cache boundaries. If the current write position
     * is close to the end of a cache line, this method will pad the wire such that a subsequent
     * 4-byte integer won't span across cache lines, optimizing cache performance.
     *
     * @return This WireOut instance for method chaining.
     */
    @NotNull
    default WireOut padToCacheAlign() {
        @NotNull Bytes bytes = bytes();

        long offset = bytes.writePosition();
        if (bytes.start() != 0)
            offset = bytes.addressForRead(offset);
        int mod = (int) (offset & 63);
        if (mod > 60)
            addPadding(64 - mod);

        return this;
    }

    /**
     * Aligns the write position to the provided alignment boundary, taking into account
     * the specified offset (plus). Padding will be added as necessary.
     *
     * @param alignment The alignment boundary.
     * @param plus Additional offset to the write position.
     * @return This WireOut instance for method chaining.
     */
    @NotNull
    default WireOut writeAlignTo(int alignment, int plus) {
        assert Integer.bitCount(alignment) == 1;
        long mod = (bytes().writePosition() + plus) & (alignment - 1);
        if (mod != 0)
            addPadding((int) (alignment - mod));
        return this;
    }

    /**
     * Resets both the positions in the wire and the header number.
     */
    @Override
    void clear();

    /**
     * Writes a document to the wire. This will automatically handle header numbering.
     *
     * @param metaData Indicates if metadata should be written.
     * @param writer The logic for writing the content of the document.
     */
    default void writeDocument(boolean metaData, @NotNull WriteMarshallable writer) throws InvalidMarshallableException {
        WireInternal.writeData(this, metaData, false, writer);
    }

    /**
     * Starts the process of writing a document to the wire with an option for metadata.
     *
     * @param metaData If true, the returned document context will be used for writing metadata.
     * @return A context for the document being written.
     */
    @Override
    DocumentContext writingDocument(boolean metaData);

    /**
     * Starts the process of writing a data document (not metadata) to the wire.
     *
     * @return A context for the document being written.
     */
    @Override
    @NotNull
    default DocumentContext writingDocument() {
        return writingDocument(false);
    }

    /**
     * Retrieves a context for writing either data or metadata, reusing an existing context if available.
     *
     * @param metaData If true, the returned context will be used for writing metadata.
     * @return A context for the document being written.
     */
    DocumentContext acquireWritingDocument(boolean metaData);

    /**
     * Writes a document to the wire without marking its completion. This is primarily used in
     * networking scenarios, but no longer used for queues.
     *
     * @param metaData If true, metadata will be written instead of regular data.
     * @param writer Logic for writing the content of the document.
     */
    default void writeNotCompleteDocument(boolean metaData, @NotNull WriteMarshallable writer) throws InvalidMarshallableException {
        WireInternal.writeData(this, metaData, true, writer);
    }

    /**
     * INTERNAL METHOD, call writingDocument instead
     * 

* Update/end a header for a document */ void updateHeader(long position, boolean metaData, int expectedHeader) throws StreamCorruptedException; /** * INTERNAL METHOD, call writingDocument instead *

* Start a header for a document * * @param safeLength ensure there is at least this much space * @return the position of the header * @throws WriteAfterEOFException if you attempt to append an excerpt after an EOF has been written */ long enterHeader(long safeLength); /** * INTERNAL METHOD, call writingDocument instead *

* Start the first header, if there is none This will increment the headerNumber as appropriate * if successful

Note: the file might contain other data and the caller has to check this. * * @return true if the header needs to be written, false if there is a data already */ boolean writeFirstHeader(); /** * INTERNAL METHOD, call writingDocument instead *

* update the first header after writing. */ void updateFirstHeader(); /** * INTERNAL METHOD, call writingDocument instead *

* update the first header after writing {@code headerEndPos} bytes. */ void updateFirstHeader(long headerLen); /** * Write the end of wire marker, unless one is already written. This will increment the * headerNumber as appropriate if successful * * @param timeout throw TimeoutException if it could not write the marker in time. * @param timeUnit of the timeout * @param lastPosition the end of the wire * @return {code true} if did this method wrote EOF, {@code false} if it was already there. */ boolean writeEndOfWire(long timeout, TimeUnit timeUnit, long lastPosition); /** * Check if end of wire marker is present, optionally writing it unless one is already written. * This will increment the headerNumber as appropriate if successful * * @param writeEOF if {@code true}, write end of wire marker unless already exists * @param timeout throw TimeoutException if it could not write the marker in time. * @param timeUnit of the timeout * @param lastPosition the end of the wire * @return {@link EndOfWire} enum corresponding to EOF presence */ default EndOfWire endOfWire(boolean writeEOF, long timeout, TimeUnit timeUnit, long lastPosition) { throw new UnsupportedOperationException("Optional operation, please use writeEndOfWire"); } /** * Start an event object, mostly for internal use. */ void writeStartEvent(); void writeEndEvent(); default void writeAllAsMap(Class kClass, Class vClass, @NotNull Map map) { map.forEach((k, v) -> writeEvent(kClass, k).object(vClass, v)); } @NotNull default WireOut dropDefault(boolean dropDefault) { return this; } /** * @return true unless there is an incomplete/chained message */ default boolean writingIsComplete() { return true; } enum EndOfWire { /** * EOF marker is not present and was not written */ NOT_PRESENT, /** * EOF marker was not present have been written and now in place */ PRESENT_AFTER_UPDATE, /** * EOF marker is present */ PRESENT } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy