Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
*
* 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. See accompanying
* LICENSE file.
*/
package com.gemstone.gemfire.internal.cache.snapshot;
import static com.gemstone.gemfire.distributed.internal.InternalDistributedSystem.getLoggerI18n;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import com.gemstone.gemfire.cache.EntryDestroyedException;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionContext;
import com.gemstone.gemfire.cache.execute.FunctionException;
import com.gemstone.gemfire.cache.execute.FunctionService;
import com.gemstone.gemfire.cache.execute.RegionFunctionContext;
import com.gemstone.gemfire.cache.execute.ResultCollector;
import com.gemstone.gemfire.cache.execute.ResultSender;
import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
import com.gemstone.gemfire.cache.snapshot.SnapshotOptions;
import com.gemstone.gemfire.distributed.DistributedMember;
import com.gemstone.gemfire.distributed.internal.ReplyProcessor21;
import com.gemstone.gemfire.internal.cache.LocalRegion;
import com.gemstone.gemfire.internal.cache.execute.InternalExecution;
import com.gemstone.gemfire.internal.cache.execute.LocalResultCollector;
import com.gemstone.gemfire.internal.cache.snapshot.FlowController.Window;
import com.gemstone.gemfire.internal.cache.snapshot.RegionSnapshotServiceImpl.ExportSink;
import com.gemstone.gemfire.internal.cache.snapshot.RegionSnapshotServiceImpl.Exporter;
import com.gemstone.gemfire.internal.cache.snapshot.SnapshotPacket.SnapshotRecord;
/**
* Exports snapshot data using a sliding window to prevent the nodes in a
* partitioned region from overrunning the exporter. When a {@link SnapshotPacket}
* is written to the {@link ExportSink}, an ACK is sent back to the source
* node. The source node will continue to send data until it runs out of permits;
* it must then wait for ACK's to resume.
*
* @author bakera
*
* @param the key type
* @param the value type
*/
public class WindowedExporter implements Exporter {
private static final int WINDOW_SIZE = Integer.getInteger("gemfire.WindowedExporter.WINDOW_SIZE", 10);
@Override
public long export(Region region, ExportSink sink, SnapshotOptions options) throws IOException {
long count = 0;
boolean error = true;
LocalRegion local = RegionSnapshotServiceImpl.getLocalRegion(region);
SnapshotPacket last = new SnapshotPacket();
DistributedMember me = region.getCache().getDistributedSystem().getDistributedMember();
WindowedArgs args = new WindowedArgs(me, options);
WindowedExportCollector results = new WindowedExportCollector(local, last);
try {
// Since the ExportCollector already is a LocalResultsCollector it's ok not
// to keep the reference to the ResultsCollector returned from execute().
// Normally discarding the reference can cause issues if GC causes the
// weak ref in ProcessorKeeper21 to be collected!!
InternalExecution exec = (InternalExecution) FunctionService.onRegion(region)
.withArgs(args)
.withCollector(results);
// Ensure that our collector gets all exceptions so we can shut down the
// queue properly.
exec.setForwardExceptions(true);
exec.execute(new WindowedExportFunction());
BlockingQueue queue = results.getResult();
SnapshotPacket packet;
while ((packet = queue.take()) != last) {
results.ack(packet);
sink.write(packet.getRecords());
count += packet.getRecords().length;
}
error = false;
FunctionException ex = results.getException();
if (ex != null) {
throw new IOException(ex);
}
} catch (FunctionException e) {
throw new IOException(e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw (IOException) new InterruptedIOException().initCause(e);
} finally {
if (error) {
results.abort();
}
}
return count;
}
/**
* Carries the arguments to the export function.
*
* @param the key type
* @param the value type
*/
private static class WindowedArgs implements Serializable {
private static final long serialVersionUID = 1;
private final DistributedMember exporter;
private final SnapshotOptions options;
public WindowedArgs(DistributedMember exporter, SnapshotOptions options) {
this.exporter = exporter;
this.options = options;
}
public DistributedMember getExporter() {
return exporter;
}
public SnapshotOptions getOptions() {
return options;
}
}
/**
* Gathers the local data on the region and sends it back to the
* {@link ResultCollector} in serialized form as {@link SnapshotPacket}s. Uses
* a sliding window provided by the {@link FlowController} to avoid over-running
* the exporting member.
*
* @param the key type
* @param the value type
*
* @see FlowController
*/
private static class WindowedExportFunction implements Function {
private static final long serialVersionUID = 1L;
// We must keep a ref here since the ProcessorKeeper only has a weak ref. If
// this object is GC'd it could cause a hang since we will no longer receive
// ACK's for every packet.
private transient volatile Window window;
@Override
public boolean hasResult() {
return true;
}
@Override
public void execute(FunctionContext context) {
RegionFunctionContext ctx = (RegionFunctionContext) context;
final WindowedArgs args = (WindowedArgs) ctx.getArguments();
ResultSender rs = ctx.getResultSender();
Region region = ctx.getDataSet();
if (PartitionRegionHelper.isPartitionedRegion(region)) {
region = PartitionRegionHelper.getLocalDataForContext(ctx);
}
LocalRegion local = RegionSnapshotServiceImpl.getLocalRegion(region);
window = FlowController.getInstance().create(region, args.getExporter(), WINDOW_SIZE);
try {
int bufferSize = 0;
List buffer = new ArrayList();
DistributedMember me = region.getCache().getDistributedSystem().getDistributedMember();
for (Iterator> iter = region.entrySet().iterator(); iter.hasNext() && !window.isAborted(); ) {
Entry entry = iter.next();
try {
SnapshotOptions options = args.getOptions();
if (options.getFilter() == null || options.getFilter().accept(entry)) {
SnapshotRecord rec = new SnapshotRecord(local, entry);
buffer.add(rec);
bufferSize += rec.getSize();
}
} catch (EntryDestroyedException e) {
// continue to next entry
} catch (IOException e) {
throw new FunctionException(e);
}
if (bufferSize > RegionSnapshotServiceImpl.BUFFER_SIZE) {
window.waitForOpening();
rs.sendResult(new SnapshotPacket(window.getWindowId(), me, buffer));
buffer.clear();
bufferSize = 0;
}
}
window.waitForOpening();
rs.lastResult(new SnapshotPacket(window.getWindowId(), me, buffer));
if (getLoggerI18n().fineEnabled())
getLoggerI18n().fine("SNP: Sent all entries in region " + region.getName());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new FunctionException(e);
} finally {
window.close();
}
}
@Override
public String getId() {
return "com.gemstone.gemfire.cache.snapshot.WindowedExport";
}
@Override
public boolean optimizeForWrite() {
return false;
}
@Override
public boolean isHA() {
return false;
}
}
/**
* Collects export results and places them in a queue for processing by the
* function invoker.
*/
private static class WindowedExportCollector implements LocalResultCollector