| /* |
| * Copyright (c) 2011, 2012, 2016 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: |
| * Caspar De Groot - initial API and implementation |
| */ |
| package org.eclipse.emf.cdo.server.internal.db4o; |
| |
| import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; |
| import org.eclipse.emf.cdo.common.id.CDOID; |
| import org.eclipse.emf.cdo.common.lock.CDOLockUtil; |
| import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea; |
| import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea.Handler; |
| import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockAreaNotFoundException; |
| import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade; |
| import org.eclipse.emf.cdo.spi.server.InternalLockManager; |
| |
| import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; |
| import org.eclipse.net4j.util.lifecycle.Lifecycle; |
| |
| import com.db4o.ObjectContainer; |
| import com.db4o.ObjectSet; |
| import com.db4o.query.Query; |
| |
| import java.util.Collection; |
| import java.util.Map; |
| |
| /** |
| * @author Caspar De Groot |
| */ |
| public class DB4ODurableLockingManager extends Lifecycle |
| { |
| public DB4ODurableLockingManager() |
| { |
| } |
| |
| public LockArea createLockArea(DB4OStoreAccessor accessor, String userID, CDOBranchPoint branchPoint, boolean readOnly, Map<CDOID, LockGrade> locks) |
| { |
| String durableLockingID = getNextDurableLockingID(accessor); |
| LockArea lockArea = CDOLockUtil.createLockArea(durableLockingID, userID, branchPoint, readOnly, locks); |
| storeLockArea(accessor, lockArea); |
| return lockArea; |
| } |
| |
| private void storeLockArea(DB4OStoreAccessor accessor, LockArea area) |
| { |
| ObjectContainer objectContainer = accessor.getObjectContainer(); |
| DB4OLockArea primitiveLockArea = DB4OLockArea.getPrimitiveLockArea(area); |
| objectContainer.store(primitiveLockArea); |
| objectContainer.commit(); |
| } |
| |
| public LockArea getLockArea(DB4OStoreAccessor accessor, String durableLockingID) throws LockAreaNotFoundException |
| { |
| DB4OLockArea primitive = getPrimitiveLockArea(accessor, durableLockingID); |
| return DB4OLockArea.getLockArea(accessor.getStore(), primitive); |
| } |
| |
| private DB4OLockArea getPrimitiveLockArea(DB4OStoreAccessor accessor, String durableLockingID) throws LockAreaNotFoundException |
| { |
| ObjectContainer container = accessor.getObjectContainer(); |
| Query query = container.query(); |
| query.constrain(DB4OLockArea.class); |
| query.descend("id").constrain(durableLockingID); |
| |
| ObjectSet<?> lockAreas = query.execute(); |
| if (lockAreas.isEmpty()) |
| { |
| throw new LockAreaNotFoundException(durableLockingID); |
| } |
| |
| if (lockAreas.size() > 1) |
| { |
| throw new AssertionError("Lockarea stored more than once in object database"); |
| } |
| |
| return (DB4OLockArea)lockAreas.get(0); |
| } |
| |
| public void getLockAreas(DB4OStoreAccessor accessor, String userIDPrefix, Handler handler) |
| { |
| ObjectContainer container = accessor.getObjectContainer(); |
| Query query = container.query(); |
| query.constrain(DB4OLockArea.class); |
| |
| if (userIDPrefix.length() > 0) |
| { |
| query.descend("userID").constrain(userIDPrefix).startsWith(true); |
| } |
| |
| ObjectSet<?> primitives = query.execute(); |
| for (Object primitive : primitives) |
| { |
| LockArea area = DB4OLockArea.getLockArea(accessor.getStore(), (DB4OLockArea)primitive); |
| if (!handler.handleLockArea(area)) |
| { |
| break; |
| } |
| } |
| } |
| |
| public void deleteLockArea(DB4OStoreAccessor accessor, String durableLockingID) |
| { |
| DB4OLockArea primitive = getPrimitiveLockArea(accessor, durableLockingID); |
| ObjectContainer container = accessor.getObjectContainer(); |
| container.delete(primitive); |
| container.commit(); |
| } |
| |
| public void lock(DB4OStoreAccessor accessor, String durableLockingID, LockType type, Collection<? extends Object> objectsToLock) |
| { |
| // TODO (CD) Refactor? Next chunk of code copied verbatim from MEMStore.lock |
| LockArea area = getLockArea(accessor, durableLockingID); |
| Map<CDOID, LockGrade> locks = area.getLocks(); |
| |
| InternalLockManager lockManager = accessor.getStore().getRepository().getLockingManager(); |
| for (Object objectToLock : objectsToLock) |
| { |
| CDOID id = lockManager.getLockKeyID(objectToLock); |
| LockGrade grade = locks.get(id); |
| if (grade != null) |
| { |
| grade = grade.getUpdated(type, true); |
| } |
| else |
| { |
| grade = LockGrade.get(type); |
| } |
| |
| locks.put(id, grade); |
| } |
| |
| storeLockArea(accessor, area); |
| } |
| |
| public void unlock(DB4OStoreAccessor accessor, String durableLockingID, LockType type, Collection<? extends Object> objectsToUnlock) |
| { |
| // TODO (CD) Refactor? Next chunk of code copied verbatim from MEMStore.lock |
| LockArea area = getLockArea(accessor, durableLockingID); |
| Map<CDOID, LockGrade> locks = area.getLocks(); |
| |
| InternalLockManager lockManager = accessor.getStore().getRepository().getLockingManager(); |
| for (Object objectToUnlock : objectsToUnlock) |
| { |
| CDOID id = lockManager.getLockKeyID(objectToUnlock); |
| LockGrade grade = locks.get(id); |
| if (grade != null) |
| { |
| grade = grade.getUpdated(type, false); |
| if (grade == LockGrade.NONE) |
| { |
| locks.remove(id); |
| } |
| else |
| { |
| locks.put(id, grade); |
| } |
| } |
| } |
| |
| storeLockArea(accessor, area); |
| } |
| |
| public void unlock(DB4OStoreAccessor accessor, String durableLockingID) |
| { |
| LockArea area = getLockArea(accessor, durableLockingID); |
| Map<CDOID, LockGrade> locks = area.getLocks(); |
| locks.clear(); |
| |
| storeLockArea(accessor, area); |
| } |
| |
| // TODO: Refactor -- this was copied verbatim from DurableLockingManager |
| private String getNextDurableLockingID(DB4OStoreAccessor accessor) |
| { |
| for (;;) |
| { |
| String durableLockingID = CDOLockUtil.createDurableLockingID(); |
| |
| try |
| { |
| getLockArea(accessor, durableLockingID); // Check uniqueness |
| // Not unique; try once more... |
| } |
| catch (LockAreaNotFoundException ex) |
| { |
| return durableLockingID; |
| } |
| } |
| } |
| } |