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.
*/
/*
* Changes for SnappyData data platform.
*
* Portions Copyright (c) 2018 SnappyData, 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;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import com.gemstone.gemfire.CancelException;
import com.gemstone.gemfire.SystemFailure;
import com.gemstone.gemfire.cache.util.ObjectSizer;
import com.gemstone.gemfire.i18n.LogWriterI18n;
import com.gemstone.gemfire.internal.GemFireVersion;
import com.gemstone.gemfire.internal.LogWriterImpl;
import com.gemstone.gemfire.internal.cache.control.MemoryEvent;
import com.gemstone.gemfire.internal.cache.control.ResourceListener;
import com.gemstone.gemfire.internal.cache.versions.CompactVersionHolder;
import com.gemstone.gemfire.internal.cache.versions.VersionSource;
import com.gemstone.gemfire.internal.cache.versions.VersionTag;
import com.gemstone.gemfire.internal.concurrent.ConcurrentTHashSet;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
import com.gemstone.gemfire.internal.size.ReflectionSingleObjectSizer;
import com.gemstone.gemfire.internal.util.concurrent.StoppableReentrantLock;
import static com.gemstone.gemfire.internal.shared.SystemProperties.getServerInstance;
/**
* Tombstones are region entries that have been destroyed but are held
* for future concurrency checks. They are timed out after a reasonable
* period of time when there is no longer the possibility of concurrent
* modification conflicts.
*
* The cache holds a tombstone service that is responsible for tracking
* and timing out tombstones.
*
* @author bruce
*/
public class TombstoneService implements ResourceListener {
/**
* The default tombstone expiration period, in milliseconds for replicated
* regions.
This is the period over which the destroy operation may
* conflict with another operation. After this timeout elapses the tombstone
* is put into a GC set for removal. Removal is typically triggered by
* the size of the GC set, but could be influenced by resource managers.
*
* The default is 600,000 milliseconds (10 minutes).
*/
public static long REPLICATED_TOMBSTONE_TIMEOUT = getServerInstance().getLong(
"tombstone-timeout", 600000L);
/**
* The default tombstone expiration period in millis for non-replicated
* regions. This tombstone timeout should be shorter than the one for
* replicated regions and need not be excessively long. Making it longer
* than the replicated timeout can cause non-replicated regions to issue
* revisions based on the tombstone that could overwrite modifications made
* by others that no longer have the tombstone.
* The default is 480,000 milliseconds (8 minutes)
*/
public static long CLIENT_TOMBSTONE_TIMEOUT = getServerInstance().getLong(
"non-replicated-tombstone-timeout", 480000);
/**
* The max number of tombstones in an expired batch. This covers
* all replicated regions, including PR buckets. The default is
* 100,000 expired tombstones.
*/
public static long EXPIRED_TOMBSTONE_LIMIT = getServerInstance().getLong(
"tombstone-gc-threshold", 100000);
/**
* The interval to scan for expired tombstones in the queues
*/
public static long DEFUNCT_TOMBSTONE_SCAN_INTERVAL = getServerInstance().getLong(
"tombstone-scan-interval", 60000);
/**
* The threshold percentage of free max memory that will trigger tombstone GCs.
* The default percentage is somewhat less than the LRU Heap evictor so that
* we evict tombstones before we start evicting cache data.
*/
public static double GC_MEMORY_THRESHOLD = getServerInstance().getInteger("tombstone-gc-memory-threshold",
30 /*100-HeapLRUCapacityController.DEFAULT_HEAP_PERCENTAGE*/) * 0.01;
/** this is a test hook for causing the tombstone service to act as though free memory is low */
public static boolean FORCE_GC_MEMORY_EVENTS = false;
/** verbose tombstone logging for diagnosing tombstone problems */
public static boolean VERBOSE = getServerInstance().getBoolean(
"TombstoneService.VERBOSE", false);
public final static Object debugSync = new Object();
public final static boolean DEBUG_TOMBSTONE_COUNT = getServerInstance().getBoolean(
"TombstoneService.DEBUG_TOMBSTONE_COUNT", false);
public static boolean IDLE_EXPIRATION = false; // dunit test hook for forced batch expiration
/**
* tasks for cleaning up tombstones
*/
private TombstoneSweeper replicatedTombstoneSweeper;
private TombstoneSweeper nonReplicatedTombstoneSweeper;
/** a tombstone service is tied to a cache */
private GemFireCacheImpl cache;
/**
* two queues, one for replicated regions (including PR buckets) and one for
* other regions. They have different timeout intervals.
*/
private Queue replicatedTombstones = new ConcurrentLinkedQueue();
private Queue nonReplicatedTombstones = new ConcurrentLinkedQueue();
private AtomicLong replicatedTombstoneQueueSize = new AtomicLong();
private AtomicLong nonReplicatedTombstoneQueueSize = new AtomicLong();
public Object blockGCLock = new Object();
private int progressingDeltaGIICount;
public static TombstoneService initialize(GemFireCacheImpl cache) {
TombstoneService instance = new TombstoneService(cache);
// cache.getResourceManager().addResourceListener(instance); experimental
return instance;
}
private TombstoneService(GemFireCacheImpl cache) {
this.cache = cache;
this.replicatedTombstoneSweeper = new TombstoneSweeper(cache, this.replicatedTombstones,
REPLICATED_TOMBSTONE_TIMEOUT, true, this.replicatedTombstoneQueueSize);
this.nonReplicatedTombstoneSweeper = new TombstoneSweeper(cache, this.nonReplicatedTombstones,
CLIENT_TOMBSTONE_TIMEOUT, false, this.nonReplicatedTombstoneQueueSize);
startSweeper(this.replicatedTombstoneSweeper);
startSweeper(this.nonReplicatedTombstoneSweeper);
}
private void startSweeper(TombstoneSweeper tombstoneSweeper) {
synchronized(tombstoneSweeper) {
if (tombstoneSweeper.sweeperThread == null) {
tombstoneSweeper.sweeperThread = new Thread(LogWriterImpl.createThreadGroup("Destroyed Entries Processors",
cache.getLoggerI18n()), tombstoneSweeper);
tombstoneSweeper.sweeperThread.setDaemon(true);
String product = GemFireVersion.getProductName();
if (tombstoneSweeper == this.replicatedTombstoneSweeper) {
tombstoneSweeper.sweeperThread.setName(product + " Garbage Collection Thread 1");
} else {
tombstoneSweeper.sweeperThread.setName(product + " Garbage Collection Thread 2");
}
tombstoneSweeper.sweeperThread.start();
}
}
}
/**
* this ensures that the background sweeper thread is stopped
*/
public void stop() {
stopSweeper(this.replicatedTombstoneSweeper);
stopSweeper(this.nonReplicatedTombstoneSweeper);
}
private void stopSweeper(TombstoneSweeper t) {
Thread sweeperThread;
synchronized(t) {
sweeperThread = t.sweeperThread;
t.isStopped = true;
if (sweeperThread != null) {
t.notifyAll();
}
}
try {
sweeperThread.join(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
t.tombstones.clear();
}
/**
* Tombstones are markers placed in destroyed entries in order to keep the
* entry around for a while so that it's available for concurrent modification
* detection.
*
* @param r the region holding the entry
* @param entry the region entry that holds the tombstone
* @param destroyedVersion the version that was destroyed
*/
public void scheduleTombstone(LocalRegion r, RegionEntry entry, VersionTag destroyedVersion) {
boolean useReplicated = useReplicatedQueue(r);
Tombstone ts = new Tombstone(entry, r, destroyedVersion);
if (useReplicated) {
this.replicatedTombstones.add(ts);
this.replicatedTombstoneQueueSize.addAndGet(ts.getSize());
} else {
this.nonReplicatedTombstones.add(ts);
this.nonReplicatedTombstoneQueueSize.addAndGet(ts.getSize());
}
}
private boolean useReplicatedQueue(LocalRegion r) {
return (r.getServerProxy() == null) && r.dataPolicy.withReplication();
}
/**
* remove all tombstones for the given region. Do this when the region is
* cleared or destroyed.
* @param r
*/
public void unscheduleTombstones(LocalRegion r) {
// long start = 0;
// if (cache.getLoggerI18n().fineEnabled()) {
// start = System.currentTimeMillis();
// }
Queue queue =
r.getAttributes().getDataPolicy().withReplication() ? replicatedTombstones : nonReplicatedTombstones;
long removalSize = 0;
for (Iterator it=queue.iterator(); it.hasNext(); ) {
Tombstone t = it.next();
if (t.region == r) {
it.remove();
removalSize += t.getSize();
}
}
if (queue == replicatedTombstones) {
replicatedTombstoneQueueSize.addAndGet(-removalSize);
} else {
nonReplicatedTombstoneQueueSize.addAndGet(-removalSize);
}
// if (cache.getLoggerI18n().fineEnabled()) {
// long end = System.currentTimeMillis();
// if ( (end-start) > 10000 ) {
// cache.getLoggerI18n().fine("Tombstone removal for " + r.getName() + " took " + (end-start) + " ms");
// }
// }
}
public int getGCBlockCount() {
synchronized(this.blockGCLock) {
return this.progressingDeltaGIICount;
}
}
public int incrementGCBlockCount() {
synchronized(this.blockGCLock) {
return ++this.progressingDeltaGIICount;
}
}
public int decrementGCBlockCount() {
synchronized(this.blockGCLock) {
return --this.progressingDeltaGIICount;
}
}
/**
* remove tombstones from the given region that have region-versions <= those in the given removal map
* @return a collection of keys removed (only if the region is a bucket - empty otherwise)
*/
public Set