blob: b7605963d58ac83ef0c9ec2e703748ceefb42887 [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* more patents listed at http://www.pivotal.io/patents.
*========================================================================
*/
package com.gemstone.gemfire.internal.cache;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheEvent;
import com.gemstone.gemfire.cache.Operation;
import com.gemstone.gemfire.cache.TransactionEvent;
import com.gemstone.gemfire.cache.TransactionId;
import com.gemstone.gemfire.distributed.DistributedMember;
/**
* <p>
* The internal implementation of the {@link TransactionEvent}interface used by
* the remote commit code.
*
* @author Darrel Schneider
*
* @since 4.0
*
*/
public class TXRmtEvent implements TransactionEvent
{
private final TransactionId txId;
private Cache cache;
private List events;
TXRmtEvent(TransactionId txId, Cache cache) {
this.txId = txId;
this.cache = cache;
this.events = null;
}
public TransactionId getTransactionId()
{
return this.txId;
}
private boolean isEventUserVisible(CacheEvent ce) {
return BucketRegion.FORCE_LOCAL_LISTENERS_INVOCATION || !(ce.getRegion() instanceof PartitionedRegion);
}
public List getEvents()
{
if (this.events == null) {
return Collections.EMPTY_LIST;
}
else {
ArrayList result = new ArrayList(this.events.size());
Iterator it = this.events.iterator();
while (it.hasNext()) {
CacheEvent ce = (CacheEvent)it.next();
if (isEventUserVisible(ce)) {
result.add(ce);
}
}
if (result.isEmpty()) {
return Collections.EMPTY_LIST;
}
else {
return Collections.unmodifiableList(result);
}
}
}
public List getCreateEvents()
{
if (this.events == null) {
return Collections.EMPTY_LIST;
}
else {
ArrayList result = new ArrayList(this.events.size());
Iterator it = this.events.iterator();
while (it.hasNext()) {
CacheEvent ce = (CacheEvent)it.next();
if (ce.getOperation().isCreate() && isEventUserVisible(ce)) {
result.add(ce);
}
}
if (result.isEmpty()) {
return Collections.EMPTY_LIST;
}
else {
return Collections.unmodifiableList(result);
}
}
}
public List getPutEvents()
{
if (this.events == null) {
return Collections.EMPTY_LIST;
}
else {
ArrayList result = new ArrayList(this.events.size());
Iterator it = this.events.iterator();
while (it.hasNext()) {
CacheEvent ce = (CacheEvent)it.next();
if (ce.getOperation().isUpdate() && isEventUserVisible(ce)) {
result.add(ce);
}
}
if (result.isEmpty()) {
return Collections.EMPTY_LIST;
}
else {
return Collections.unmodifiableList(result);
}
}
}
public List getInvalidateEvents()
{
if (this.events == null) {
return Collections.EMPTY_LIST;
}
else {
ArrayList result = new ArrayList(this.events.size());
Iterator it = this.events.iterator();
while (it.hasNext()) {
CacheEvent ce = (CacheEvent)it.next();
if (ce.getOperation().isInvalidate() && isEventUserVisible(ce)) {
result.add(ce);
}
}
if (result.isEmpty()) {
return Collections.EMPTY_LIST;
}
else {
return Collections.unmodifiableList(result);
}
}
}
public List getDestroyEvents()
{
if (this.events == null) {
return Collections.EMPTY_LIST;
}
else {
ArrayList result = new ArrayList(this.events.size());
Iterator it = this.events.iterator();
while (it.hasNext()) {
CacheEvent ce = (CacheEvent)it.next();
if (ce.getOperation().isDestroy() && isEventUserVisible(ce)) {
result.add(ce);
}
}
if (result.isEmpty()) {
return Collections.EMPTY_LIST;
}
else {
return Collections.unmodifiableList(result);
}
}
}
private EntryEventImpl createEvent(LocalRegion r, Operation op,
RegionEntry re, Object key, Object newValue,Object aCallbackArgument)
{
DistributedMember originator = ((TXId)this.txId).getMemberId();
//TODO:ASIF :EventID will not be generated with this constructor . Check if
// this is correct
LocalRegion eventRegion = r;
if (r.isUsedForPartitionedRegionBucket()) {
eventRegion = r.getPartitionedRegion();
}
EntryEventImpl event = EntryEventImpl.create(
eventRegion, op, key, newValue,
aCallbackArgument, // callbackArg
true, // originRemote
originator);
event.setOldValue(re.getValueInVM(r)); // OFFHEAP: copy into heap cd
event.setTransactionId(getTransactionId());
return event;
}
/**
* Add an event to our internal list
*/
private void addEvent(EntryEventImpl e)
{
synchronized (this) {
if (this.events == null) {
this.events = new ArrayList();
}
this.events.add(e);
}
}
void addDestroy(LocalRegion r, RegionEntry re, Object key,Object aCallbackArgument)
{
addEvent(createEvent(r, Operation.DESTROY, re, key, null,aCallbackArgument));
}
void addInvalidate(LocalRegion r, RegionEntry re, Object key, Object newValue,Object aCallbackArgument)
{
addEvent(createEvent(r, Operation.INVALIDATE, re, key, newValue,aCallbackArgument));
}
void addPut(Operation putOp, LocalRegion r, RegionEntry re, Object key,
Object newValue,Object aCallbackArgument)
{
addEvent(createEvent(r, putOp, re, key, newValue,aCallbackArgument));
}
public Cache getCache()
{
return this.cache;
}
public void freeOffHeapResources() {
if (this.events != null) {
for (EntryEventImpl e: (List<EntryEventImpl>)this.events) {
e.release();
}
}
// TODO Auto-generated method stub
}
}