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

com.netflix.zeno.fastblob.io.FastBlobWriter Maven / Gradle / Ivy

/*
 *
 *  Copyright 2013 Netflix, Inc.
 *
 *     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 com.netflix.zeno.fastblob.io;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import com.netflix.zeno.fastblob.FastBlobStateEngine;
import com.netflix.zeno.fastblob.record.VarInt;
import com.netflix.zeno.fastblob.state.FastBlobTypeDeserializationState;
import com.netflix.zeno.fastblob.state.FastBlobTypeSerializationState;
import com.netflix.zeno.fastblob.state.ThreadSafeBitSet;

/**
 * Writes FastBlob images to streams.
 */
public class FastBlobWriter {

    private final FastBlobStateEngine stateEngine;
    private final int imageIndex;
    private FastBlobHeaderWriter headerWriter;

    public FastBlobWriter(FastBlobStateEngine stateEngine) {
        this(stateEngine, 0);
    }

    public FastBlobWriter(FastBlobStateEngine stateEngine, int imageIndex) {
        this(stateEngine, imageIndex, new ZenoFastBlobHeaderWriter());
    }

    public void setFastBlobHeaderWriter(FastBlobHeaderWriter headerWriter) {
        this.headerWriter = headerWriter;
    }

    /**
     * This FastBlobWriter will write a single image to a stream, as either a snapshot or delta.

* * The configuration for the image which this will write is contained in the list returned by stateEngine.getImageConfigurations() * at the index specified by imageIndex * * @param stateEngine * @param imageIndex */ public FastBlobWriter(FastBlobStateEngine stateEngine, int imageIndex, FastBlobHeaderWriter headerWriter) { this.stateEngine = stateEngine; this.imageIndex = imageIndex; this.headerWriter = headerWriter; } /** * Write a snapshot to the specified stream. */ public void writeSnapshot(OutputStream os) throws Exception { writeSnapshot(new DataOutputStream(os)); } public void writeSnapshot(DataOutputStream os) throws IOException { writeHeader(os); for(FastBlobTypeSerializationState typeState : stateEngine.getOrderedSerializationStates()) { if(!typeState.isReadyForWriting()) throw new RuntimeException("This state engine is not ready for writing! Have you remembered to call stateEngine.prepareForWrite()?"); /// type flags byte -- reserved for later use os.write(0); /// write the schema typeState.getSchema().writeTo(os); ThreadSafeBitSet imageMembershipBitSet = typeState.getImageMembershipBitSet(imageIndex); serializeTypeStateObjects(os, typeState, imageMembershipBitSet); } } public void writeNonImageSpecificSnapshot(DataOutputStream os) throws IOException { writeHeader(os); for(FastBlobTypeSerializationState typeState : stateEngine.getOrderedSerializationStates()) { if(!typeState.isReadyForWriting()) throw new RuntimeException("This state engine is not ready for writing! Have you remembered to call stateEngine.prepareForWrite()?"); FastBlobTypeDeserializationState typeDeserializationState = stateEngine.getTypeDeserializationState(typeState.getSchema().getName()); /// type flags byte -- reserved for later use os.write(0); /// write the schema typeState.getSchema().writeTo(os); serializeTypeStateObjects(os, typeState, typeDeserializationState); } } /** * Write a delta to the specified stream. */ public void writeDelta(OutputStream os) throws IOException { writeDelta(new DataOutputStream(os)); } public void writeDelta(DataOutputStream os) throws IOException { writeHeader(os); for(FastBlobTypeSerializationState typeState : stateEngine.getOrderedSerializationStates()) { if(!typeState.isReadyForWriting()) throw new RuntimeException("This state engine is not ready for writing! Have you remembered to call stateEngine.prepareForWrite()?"); /// type flags byte -- reserved for later use os.write(0); /// write the schema typeState.getSchema().writeTo(os); ThreadSafeBitSet currentImageMembershipBitSet = typeState.getImageMembershipBitSet(imageIndex); ThreadSafeBitSet previousImageMembershipBitSet = typeState.getPreviousCycleImageMembershipBitSet(imageIndex); serializeDelta(os, typeState, currentImageMembershipBitSet, previousImageMembershipBitSet); } } /** * Write a reverse delta to the specified stream. * * A reverse delta is the opposite of a delta. A delta removes all unused objects from the previous state and adds all * new objects in the current state. A reverse delta removes all new objects in the current state and adds all unused * objects from the previous state. */ public void writeReverseDelta(OutputStream os, String previousVersion) throws IOException { writeReverseDelta(new DataOutputStream(os), previousVersion); } public void writeReverseDelta(DataOutputStream os, String previousVersion) throws IOException { writeHeader(os, previousVersion); for(FastBlobTypeSerializationState typeState : stateEngine.getOrderedSerializationStates()) { if(!typeState.isReadyForWriting()) throw new RuntimeException("This state engine is not ready for writing! Have you remembered to call stateEngine.prepareForWrite()?"); if(typeState.getPreviousStateSchema() != null) { /// type flags byte -- reserved for later use os.write(0); /// write the schema typeState.getPreviousStateSchema().writeTo(os); ThreadSafeBitSet currentImageMembershipBitSet = typeState.getImageMembershipBitSet(imageIndex); ThreadSafeBitSet previousImageMembershipBitSet = typeState.getPreviousCycleImageMembershipBitSet(imageIndex); serializeDelta(os, typeState, previousImageMembershipBitSet, currentImageMembershipBitSet); } } } private void serializeDelta(DataOutputStream os, FastBlobTypeSerializationState typeState, ThreadSafeBitSet currentStateOrdinals, ThreadSafeBitSet prevStateOrdinals) throws IOException { /// get all of the ordinals contained in the previous cycle, which are no longer contained in this cycle. These all need to be removed. ThreadSafeBitSet removedTypeStateObjectsBitSet = prevStateOrdinals.andNot(currentStateOrdinals); serializeTypeStateRemovals(os, removedTypeStateObjectsBitSet); /// get all of the ordinals contained in this cycle, which were not contained in the previous cycle. These all need to be added. ThreadSafeBitSet addedTypeStateObjectsBitSet = currentStateOrdinals.andNot(prevStateOrdinals); serializeTypeStateObjects(os, typeState, addedTypeStateObjectsBitSet); } private void writeHeader(DataOutputStream os) throws IOException { String version = stateEngine.getLatestVersion() != null ? stateEngine.getLatestVersion() : ""; writeHeader(os, version); } private void writeHeader(DataOutputStream os, String version) throws IOException { FastBlobHeader header = new FastBlobHeader(); header.setVersion(version); header.setHeaderTags(stateEngine.getHeaderTags()); /// The deserialization StreamingByteData buffer size needs to accommodate the largest single object. /// write the ceil(log2(maxSize)) as a single byte at the beginning of the stream. /// upon deserialization, this byte will be read and the StreamingByteData buffer can be sized appropriately. int deserializationBufferSizeHint = 32 - Integer.numberOfLeadingZeros(stateEngine.getMaxSingleObjectLength() - 1); header.setDeserializationBufferSizeHint(deserializationBufferSizeHint); header.setNumberOfTypes(stateEngine.getOrderedSerializationStates().size()); headerWriter.writeHeader(header,stateEngine,os); } private void serializeTypeStateObjects(DataOutputStream os, FastBlobTypeSerializationState typeState, ThreadSafeBitSet includeOrdinals) throws IOException { int currentBitSetCapacity = includeOrdinals.currentCapacity(); int currentOrdinal = 0; /// write the number of objects VarInt.writeVInt(os, includeOrdinals.cardinality()); for(int i=0;i typeState, FastBlobTypeDeserializationState typeDeserializationState) throws IOException { /// write the number of objects VarInt.writeVInt(os, typeDeserializationState.countObjects()); int currentOrdinal = 0; for(int i=0;i<=typeDeserializationState.maxOrdinal();i++) { Object obj = typeDeserializationState.get(i); if(obj != null) { /// gap-encoded ordinals VarInt.writeVInt(os, i - currentOrdinal); currentOrdinal = i; /// typeState will use the ByteArrayOrdinalMap to write the length and /// serialized representation of the object. typeState.writeObjectTo(os, i); } } } private void serializeTypeStateRemovals(DataOutputStream os, ThreadSafeBitSet removals) throws IOException { int bitSetCapacity = removals.currentCapacity(); int currentRemoval = 0; /// write the number of removals VarInt.writeVInt(os, removals.cardinality()); for(int i=0;i





© 2015 - 2024 Weber Informatics LLC | Privacy Policy