/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.nifi.controller.swap;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import org.apache.nifi.controller.queue.FlowFileQueue;
import org.apache.nifi.controller.repository.FlowFileRecord;
import org.apache.nifi.controller.repository.claim.ContentClaim;
import org.apache.nifi.controller.repository.claim.ResourceClaim;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @deprecated in favor of using {@link SchemaSwapSerializer}.
*/
@Deprecated
public class SimpleSwapSerializer implements SwapSerializer {
private static final Logger logger = LoggerFactory.getLogger(SimpleSwapSerializer.class);
public static final int SWAP_ENCODING_VERSION = 10;
@Override
public void serializeFlowFiles(final List<FlowFileRecord> toSwap, final FlowFileQueue queue, final String swapLocation, final OutputStream destination) throws IOException {
if (toSwap == null || toSwap.isEmpty()) {
return;
}
long contentSize = 0L;
for (final FlowFileRecord record : toSwap) {
contentSize += record.getSize();
}
// persist record to disk via the swap file
final DataOutputStream out = new DataOutputStream(destination);
try {
out.writeInt(SWAP_ENCODING_VERSION);
out.writeUTF(queue.getIdentifier());
out.writeInt(toSwap.size());
out.writeLong(contentSize);
// get the max record id and write that out so that we know it quickly for restoration
long maxRecordId = 0L;
for (final FlowFileRecord flowFile : toSwap) {
if (flowFile.getId() > maxRecordId) {
maxRecordId = flowFile.getId();
}
}
out.writeLong(maxRecordId);
for (final FlowFileRecord flowFile : toSwap) {
out.writeLong(flowFile.getId());
out.writeLong(flowFile.getEntryDate());
out.writeLong(flowFile.getLineageStartDate());
out.writeLong(flowFile.getLineageStartIndex());
out.writeLong(flowFile.getLastQueueDate());
out.writeLong(flowFile.getQueueDateIndex());
out.writeLong(flowFile.getSize());
final ContentClaim claim = flowFile.getContentClaim();
if (claim == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
final ResourceClaim resourceClaim = claim.getResourceClaim();
out.writeUTF(resourceClaim.getId());
out.writeUTF(resourceClaim.getContainer());
out.writeUTF(resourceClaim.getSection());
out.writeLong(claim.getOffset());
out.writeLong(claim.getLength());
out.writeLong(flowFile.getContentClaimOffset());
out.writeBoolean(resourceClaim.isLossTolerant());
}
final Map<String, String> attributes = flowFile.getAttributes();
out.writeInt(attributes.size());
for (final Map.Entry<String, String> entry : attributes.entrySet()) {
writeString(entry.getKey(), out);
writeString(entry.getValue(), out);
}
}
} finally {
out.flush();
}
logger.info("Successfully swapped out {} FlowFiles from {} to Swap File {}", toSwap.size(), queue, swapLocation);
}
private void writeString(final String toWrite, final OutputStream out) throws IOException {
final byte[] bytes = toWrite.getBytes(StandardCharsets.UTF_8);
final int utflen = bytes.length;
if (utflen < 65535) {
out.write(utflen >>> 8);
out.write(utflen);
out.write(bytes);
} else {
out.write(255);
out.write(255);
out.write(utflen >>> 24);
out.write(utflen >>> 16);
out.write(utflen >>> 8);
out.write(utflen);
out.write(bytes);
}
}
@Override
public String getSerializationName() {
return "Simple Swap Serializer";
}
}