blob: 2b579421ccb69a0f452e384583d4d66627ac0a22 [file] [log] [blame]
/*
* Copyright (c) 2011, 2012, 2015, 2016, 2019 Eike Stepper (Loehne, 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
*/
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.
*/
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
*/
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);
}
}
}
}