/*
* 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.repository;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.nifi.controller.queue.FlowFileQueue;
import org.apache.nifi.controller.repository.claim.ContentClaim;
import org.apache.nifi.controller.repository.claim.ResourceClaim;
import org.apache.nifi.controller.repository.claim.ResourceClaimManager;
/**
* <p>
* An in-memory implementation of the {@link FlowFileRepository}. Upon restart, all FlowFiles will be discarded, including those that have been swapped out by a {@link FlowFileSwapManager}.
* </p>
*/
public class VolatileFlowFileRepository implements FlowFileRepository {
private final AtomicLong idGenerator = new AtomicLong(0L);
private ResourceClaimManager claimManager; // effectively final
@Override
public void initialize(final ResourceClaimManager claimManager) {
this.claimManager = claimManager;
}
@Override
public boolean isVolatile() {
return true;
}
@Override
public long getStorageCapacity() throws IOException {
return 1L;
}
@Override
public long getUsableStorageSpace() throws IOException {
return 0L;
}
@Override
public void close() throws IOException {
}
private void markDestructable(final ContentClaim contentClaim) {
if (contentClaim == null) {
return;
}
final ResourceClaim resourceClaim = contentClaim.getResourceClaim();
if (resourceClaim == null) {
return;
}
claimManager.markDestructable(resourceClaim);
}
private int getClaimantCount(final ContentClaim claim) {
if (claim == null) {
return 0;
}
final ResourceClaim resourceClaim = claim.getResourceClaim();
if (resourceClaim == null) {
return 0;
}
return claimManager.getClaimantCount(resourceClaim);
}
@Override
public void updateRepository(final Collection<RepositoryRecord> records) throws IOException {
for (final RepositoryRecord record : records) {
if (record.getType() == RepositoryRecordType.DELETE) {
// For any DELETE record that we have, if current claim's claimant count <= 0, mark it as destructable
if (record.getCurrentClaim() != null && getClaimantCount(record.getCurrentClaim()) <= 0) {
markDestructable(record.getCurrentClaim());
}
// If the original claim is different than the current claim and the original claim has a claimant count <= 0, mark it as destructable.
if (record.getOriginalClaim() != null && !record.getOriginalClaim().equals(record.getCurrentClaim()) && getClaimantCount(record.getOriginalClaim()) <= 0) {
markDestructable(record.getOriginalClaim());
}
} else if (record.getType() == RepositoryRecordType.UPDATE) {
// if we have an update, and the original is no longer needed, mark original as destructable
if (record.getOriginalClaim() != null && record.getCurrentClaim() != record.getOriginalClaim() && getClaimantCount(record.getOriginalClaim()) <= 0) {
markDestructable(record.getOriginalClaim());
}
}
}
}
@Override
public long loadFlowFiles(final QueueProvider queueProvider, final long minimumSequenceNumber) throws IOException {
idGenerator.set(minimumSequenceNumber);
return 0;
}
@Override
public long getNextFlowFileSequence() {
return idGenerator.getAndIncrement();
}
@Override
public long getMaxFlowFileIdentifier() throws IOException {
return idGenerator.get() - 1;
}
@Override
public void swapFlowFilesIn(String swapLocation, List<FlowFileRecord> flowFileRecords, FlowFileQueue queue) throws IOException {
}
@Override
public void swapFlowFilesOut(List<FlowFileRecord> swappedOut, FlowFileQueue queue, String swapLocation) throws IOException {
}
}