All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.geode.internal.cache.TXReservationMgr Maven / Gradle / Ivy

Go to download

Apache Geode provides a database-like consistency model, reliable transaction processing and a shared-nothing architecture to maintain very low latency performance with high concurrency processing

There is a newer version: 1.15.1
Show newest version
/*
 * 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 org.apache.geode.cache.*;
import org.apache.geode.internal.i18n.LocalizedStrings;
// import org.apache.geode.internal.cache.locks.*;
// import java.io.*;
import java.util.*;

/**
 * Used to reserve region entries, during a transaction commit, for modification by the transaction.
 *
 * 
 * @since GemFire 4.0
 * 
 */
public class TXReservationMgr {
  /**
   * keys are LocalRegion; values are ArrayList of Sets of held locks.
   */
  private final Map regionLocks;
  private final boolean local;

  public TXReservationMgr(boolean local) {
    Map m;
    if (local) {
      m = new IdentityHashMap();
    } else {
      m = new HashMap();
    }
    this.regionLocks = m;
    this.local = local;
  }

  public void makeReservation(IdentityArrayList localLocks) throws CommitConflictException {
    final int llSize = localLocks.size();
    final Object[] llArray = localLocks.getArrayRef();
    synchronized (this.regionLocks) {
      for (int i = 0; i < llSize; i++) {
        checkForConflict((TXRegionLockRequestImpl) llArray[i], localLocks);
      }
    }
  }

  public void releaseReservation(IdentityArrayList localLocks) {
    synchronized (this.regionLocks) {
      release(localLocks, false);
    }
  }

  private void checkForConflict(TXRegionLockRequestImpl rr, IdentityArrayList localLocks)
      throws CommitConflictException {
    Object r = getRegionObject(rr);
    Set keys = rr.getKeys();
    Object oldValue = this.regionLocks.put(r, keys);
    if (oldValue != null) {
      try {
        // we may have a conflict
        Object[] keysArray = keys.toArray();
        if (oldValue instanceof Set) {
          checkSetForConflict(rr, (Set) oldValue, keysArray, localLocks);
          IdentityArrayList newValue = new IdentityArrayList(2);
          newValue.add(oldValue);
          newValue.add(keys);
          this.regionLocks.put(r, newValue);
        } else {
          IdentityArrayList al = (IdentityArrayList) oldValue;
          int alSize = al.size();
          Object[] alArray = al.getArrayRef();
          for (int i = 0; i < alSize; i++) {
            checkSetForConflict(rr, (Set) alArray[i], keysArray, localLocks);
          }
          al.add(keys);
          this.regionLocks.put(r, al); // fix for bug 36689
        }
      } catch (CommitConflictException ex) {
        // fix for bug 36689
        this.regionLocks.put(r, oldValue);
        throw ex;
      }
    }
  }

  private void checkSetForConflict(TXRegionLockRequestImpl rr, Set s, Object[] keys,
      IdentityArrayList localLocks) throws CommitConflictException {
    for (int i = 0; i < keys.length; i++) {
      if (s.contains(keys[i])) {
        release(localLocks, true);
        throw new CommitConflictException(
            LocalizedStrings.TXReservationMgr_THE_KEY_0_IN_REGION_1_WAS_BEING_MODIFIED_BY_ANOTHER_TRANSACTION_LOCALLY
                .toLocalizedString(new Object[] {keys[i], rr.getRegionFullPath()}));
      }
    }
  }

  private final Object getRegionObject(TXRegionLockRequestImpl lr) {
    if (local) {
      return lr.getLocalRegion();
    } else {
      return lr.getRegionFullPath();
    }
  }

  private void release(IdentityArrayList localLocks, boolean conflictDetected) {
    final int llSize = localLocks.size();
    final Object[] llArray = localLocks.getArrayRef();
    for (int i = 0; i < llSize; i++) {
      TXRegionLockRequestImpl rr = (TXRegionLockRequestImpl) llArray[i];
      Object r = getRegionObject(rr);
      Set keys = rr.getKeys();
      Object curValue = this.regionLocks.get(r);
      boolean foundIt = false;
      if (curValue != null) {
        if (curValue == keys) {
          foundIt = true;
          this.regionLocks.remove(r);
        } else if (curValue instanceof IdentityArrayList) {
          IdentityArrayList al = (IdentityArrayList) curValue;
          int idx = al.indexOf(keys);
          if (idx != -1) {
            foundIt = true;
            al.remove(idx);
            if (al.isEmpty()) {
              this.regionLocks.remove(r);
            }
          }
        }
      }
      if (!foundIt && conflictDetected) {
        // No need to process the rest since the will not be found either
        // All we need to do is release the ones obtained before the
        // conflict was detected.
        break;
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy