| /* |
| * 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.geode.internal.cache; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.Set; |
| |
| import org.apache.geode.annotations.internal.MakeNotStatic; |
| import org.apache.geode.cache.CommitConflictException; |
| import org.apache.geode.distributed.internal.InternalDistributedSystem; |
| import org.apache.geode.internal.cache.locks.TXLockId; |
| import org.apache.geode.internal.cache.locks.TXLockService; |
| import org.apache.geode.internal.cache.locks.TXRegionLockRequest; |
| |
| /** |
| * TXLockRequest represents all the locks that need to be made for a single transaction. |
| * |
| * |
| * @since GemFire 4.0 |
| * |
| */ |
| public class TXLockRequest { |
| private boolean localLockHeld; |
| private TXLockId distLockId; |
| private IdentityArrayList localLocks; // of TXRegionLockRequest |
| private ArrayList<TXRegionLockRequest> distLocks; // of TXRegionLockRequest |
| private Set otherMembers; |
| |
| public TXLockRequest() { |
| this.localLockHeld = false; |
| this.distLockId = null; |
| this.localLocks = null; |
| this.distLocks = null; |
| this.otherMembers = null; |
| } |
| |
| void setOtherMembers(Set s) { |
| this.otherMembers = s; |
| } |
| |
| public void addLocalRequest(TXRegionLockRequest req) { |
| if (this.localLocks == null) { |
| this.localLocks = new IdentityArrayList(); |
| } |
| this.localLocks.add(req); |
| } |
| |
| public TXRegionLockRequest getRegionLockRequest(String regionFullPath) { |
| if (this.localLocks == null || regionFullPath == null) { |
| return null; |
| } |
| Iterator<TXRegionLockRequestImpl> it = this.localLocks.iterator(); |
| while (it.hasNext()) { |
| TXRegionLockRequestImpl rlr = it.next(); |
| if (rlr.getRegionFullPath().equals(regionFullPath)) { |
| return rlr; |
| } |
| } |
| return null; |
| } |
| |
| void addDistributedRequest(TXRegionLockRequest req) { |
| if (this.distLocks == null) { |
| this.distLocks = new ArrayList<TXRegionLockRequest>(); |
| } |
| this.distLocks.add(req); |
| } |
| |
| public void obtain(InternalDistributedSystem system) throws CommitConflictException { |
| if (this.localLocks != null && !this.localLocks.isEmpty()) { |
| txLocalLock(this.localLocks); |
| this.localLockHeld = true; |
| } |
| if (this.distLocks != null && !this.distLocks.isEmpty()) { |
| this.distLockId = TXLockService.createDTLS(system).txLock(this.distLocks, this.otherMembers); |
| } |
| } |
| |
| /** |
| * Release any local locks obtained by this request |
| */ |
| public void releaseLocal() { |
| if (this.localLockHeld) { |
| txLocalRelease(this.localLocks); |
| this.localLockHeld = false; |
| } |
| } |
| |
| /** |
| * Release any distributed locks obtained by this request |
| */ |
| public void releaseDistributed(InternalDistributedSystem system) { |
| if (this.distLockId != null) { |
| try { |
| TXLockService txls = TXLockService.createDTLS(system); |
| txls.release(this.distLockId); |
| } catch (IllegalStateException ignore) { |
| // IllegalStateException: TXLockService cannot be created |
| // until connected to distributed system |
| // could be thrown if a jvm is disconnected from the ds, |
| // and tries to createDTLS() during clean up |
| } |
| this.distLockId = null; |
| } |
| } |
| |
| public TXLockId getDistributedLockId() { |
| return this.distLockId; |
| } |
| |
| @Override |
| public String toString() { |
| StringBuilder sb = new StringBuilder(); |
| sb.append(getClass().getCanonicalName()).append("@").append(System.identityHashCode(this)); |
| sb.append(" RegionLockRequests:"); |
| if (this.localLocks != null) { |
| Iterator it = this.localLocks.iterator(); |
| while (it.hasNext()) { |
| TXRegionLockRequest rlr = (TXRegionLockRequest) it.next(); |
| sb.append(" TXRegionLockRequest:"); |
| sb.append(rlr.getRegionFullPath()).append(" keys:").append(rlr.getKeys()); |
| } |
| } |
| return sb.toString(); |
| } |
| |
| public void cleanup(InternalDistributedSystem system) { |
| releaseLocal(); |
| releaseDistributed(system); |
| } |
| |
| @MakeNotStatic |
| private static final TXReservationMgr resMgr = new TXReservationMgr(true); |
| |
| /** |
| * @param localLocks is a list of TXRegionLockRequest instances |
| */ |
| private static void txLocalLock(IdentityArrayList localLocks) throws CommitConflictException { |
| resMgr.makeReservation(localLocks); |
| } |
| |
| private static void txLocalRelease(IdentityArrayList localLocks) { |
| resMgr.releaseReservation(localLocks); |
| } |
| } |