/*
 * 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.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;

import org.apache.geode.cache.CommitConflictException;

/**
 * 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);
    Map keys = rr.getKeys();

    Object oldValue = this.regionLocks.put(r, keys);
    if (oldValue != null) {
      try {
        // we may have a conflict
        if (oldValue instanceof Map) {

          checkSetForConflict(rr, (Map) oldValue, keys, 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, (Map) alArray[i], keys, 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, Map<Object, Boolean> oldValue,
      Map<Object, Boolean> keys, IdentityArrayList localLocks) throws CommitConflictException {
    for (Map.Entry<Object, Boolean> e : keys.entrySet()) {
      if (oldValue.containsKey(e.getKey())) {
        if (oldValue.get(e.getKey()) || e.getValue()) {
          release(localLocks, true);
          throw new CommitConflictException(
              String.format(
                  "The key %s in region %s was being modified by another transaction locally.",
                  new Object[] {e.getKey(), rr.getRegionFullPath()}));
        }
      }
    }
  }

  private 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);
      Map<Object, Boolean> 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);
            } else {
              this.regionLocks.put(r, al);
            }
          }
        }
      }
      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;
      }
    }
  }
}
