/* * Copyright (c) 2011, 2012, 2015, 2016 Eike Stepper (Berlin, Germany) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Eike Stepper - initial API and implementation */ package org.eclipse.emf.cdo.common.lock; import org.eclipse.emf.cdo.common.CDOCommonRepository; import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; import java.util.Map; /** * Manages all persistent aspects of durable CDO views such as {@link CDOBranchPoint branch point} and acquired locks. * * @author Eike Stepper * @since 4.0 * @apiviz.uses {@link IDurableLockingManager.LockArea} - - manages */ public interface IDurableLockingManager { public LockArea createLockArea(String userID, CDOBranchPoint branchPoint, boolean readOnly, Map<CDOID, LockGrade> locks) throws LockAreaAlreadyExistsException; /** * Returns the {@link LockArea lock area} specified by the given durableLockingID, never <code>null</code>. * * @throws LockAreaNotFoundException * if the given durableLockingID is unknown. */ public LockArea getLockArea(String durableLockingID) throws LockAreaNotFoundException; public void getLockAreas(String userIDPrefix, LockArea.Handler handler); public void deleteLockArea(String durableLockingID); /** * Encapsulates the persistable information about a single durable CDO view like {@link CDOBranchPoint branch point} * and acquired locks. * * @author Eike Stepper * @noextend This interface is not intended to be extended by clients. * @noimplement This interface is not intended to be implemented by clients. * @apiviz.composedOf {@link IDurableLockingManager.LockGrade} - - locks */ public interface LockArea extends CDOBranchPoint { /** * @since 4.1 */ public static final int DEFAULT_DURABLE_LOCKING_ID_BYTES = 32; public String getDurableLockingID(); public String getUserID(); public boolean isReadOnly(); public Map<CDOID, LockGrade> getLocks(); /** * Returns <code>true</code> if this instance represents a lock area that is known to be missing (not present) on a * master server. (Relevant only in a replicating configuration.) * * @since 4.1 */ public boolean isMissing(); /** * A call-back interface for <em>handling</em> {@link LockArea lock area} objects. * * @author Eike Stepper * @apiviz.uses {@link IDurableLockingManager.LockArea} - - handles */ public interface Handler { public boolean handleLockArea(LockArea area); } } /** * Thrown if a {@link LockArea lock area} is spcified that does not exist in a CDO {@link CDOCommonRepository * repository}. * * @author Eike Stepper */ public static class LockAreaNotFoundException extends IllegalStateException { private static final long serialVersionUID = 1L; private String durableLockingID; public LockAreaNotFoundException(String durableLockingID) { super("No lock area for ID=" + durableLockingID); this.durableLockingID = durableLockingID; } public LockAreaNotFoundException(String message, Throwable cause, String durableLockingID) { super(message, cause); this.durableLockingID = durableLockingID; } public String getDurableLockingID() { return durableLockingID; } } /** * Exception occurs when attempting to create a durable {@link LockArea} that already exists. * * @author Caspar De Groot * @since 4.1 */ public static class LockAreaAlreadyExistsException extends IllegalStateException { private static final long serialVersionUID = 1L; private String durableLockingID; public LockAreaAlreadyExistsException(String durableLockingID) { super("A lock area with ID=" + durableLockingID + " already exists"); this.durableLockingID = durableLockingID; } public String getDurableLockingID() { return durableLockingID; } } /** * Enumerates the possible combinations of read and write locks on a single CDO object. * * @author Eike Stepper * @noextend This interface is not intended to be extended by clients. */ public enum LockGrade { NONE(0), READ(1), WRITE(2), READ_WRITE(READ.getValue() | WRITE.getValue()), /** * @since 4.1 */ OPTION(4), /** * @since 4.1 */ READ_OPTION(READ.getValue() | OPTION.getValue()), /** * @since 4.1 */ WRITE_OPTION(WRITE.getValue() | OPTION.getValue()), /** * @since 4.1 */ READ_WRITE_OPTION(READ.getValue() | WRITE.getValue() | OPTION.getValue()); private final int value; private LockGrade(int value) { this.value = value; } public int getValue() { return value; } public boolean isRead() { return (value & 1) != 0; } public boolean isWrite() { return (value & 2) != 0; } /** * @since 4.1 */ public boolean isOption() { return (value & 4) != 0; } public LockGrade getUpdated(LockType type, boolean on) { int mask = getMask(type); if (on) { return get(value | mask); } return get(value & ~mask); } private int getMask(LockType type) { switch (type) { case READ: return 1; case WRITE: return 2; case OPTION: return 4; } return 0; } public static LockGrade get(LockType type) { if (type == LockType.READ) { return READ; } if (type == LockType.WRITE) { return WRITE; } if (type == LockType.OPTION) { return OPTION; } return NONE; } /** * @deprecated Use {@link #get(boolean, boolean, boolean)} */ @Deprecated public static LockGrade get(boolean read, boolean write) { return get((read ? 1 : 0) | (write ? 2 : 0)); } /** * @since 4.1 */ public static LockGrade get(boolean read, boolean write, boolean option) { return get((read ? 1 : 0) | (write ? 2 : 0) | (option ? 4 : 0)); } public static LockGrade get(int value) { switch (value) { case 0: return NONE; case 1: return READ; case 2: return WRITE; case 3: return READ_WRITE; case 4: return OPTION; case 1 | 4: return READ_OPTION; case 2 | 4: return WRITE_OPTION; case 1 | 2 | 4: return READ_WRITE_OPTION; default: throw new IllegalArgumentException("Invalid lock grade: " + value); } } } }