001 /* This file is part of the project "Hilbert II" - http://www.qedeq.org
002 *
003 * Copyright 2000-2013, Michael Meyling <mime@qedeq.org>.
004 *
005 * "Hilbert II" is free software; you can redistribute
006 * it and/or modify it under the terms of the GNU General Public
007 * License as published by the Free Software Foundation; either
008 * version 2 of the License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU General Public License for more details.
014 */
015
016 package org.qedeq.kernel.bo.service;
017
018 import java.util.HashMap;
019 import java.util.Map;
020
021 import org.qedeq.base.utility.StringUtility;
022 import org.qedeq.kernel.bo.common.ServiceProcess;
023 import org.qedeq.kernel.bo.module.InternalServiceProcess;
024 import org.qedeq.kernel.bo.module.KernelQedeqBo;
025 import org.qedeq.kernel.se.common.ModuleContext;
026 import org.qedeq.kernel.se.visitor.InterruptException;
027
028 /**
029 * Get locks for modules.
030 *
031 * @author Michael Meyling
032 */
033 public class ModuleArbiter {
034
035 /** Map blocked QEDEQ modules to service processes. */
036 private final Map blocked;
037
038 /**
039 * Constructor.
040 */
041 public ModuleArbiter() {
042 blocked = new HashMap();
043 }
044
045 /**
046 * Lock QEDEQ module.
047 *
048 * @param process This process acquires the lock.
049 * @param qedeq Lock this module.
050 * @return The process locked this module already, we didn't do anything.
051 * @throws InterruptException Lock acquirement interrupted.
052 */
053 public boolean lockRequiredModule(final InternalServiceProcess process,
054 final KernelQedeqBo qedeq) throws InterruptException {
055 if (isAlreadyLocked(process, qedeq)) {
056 return false;
057 }
058 while (!lock(process, qedeq)) {
059 final Object monitor = new Object();
060 synchronized (monitor) {
061 try {
062 monitor.wait(10000);
063 } catch (InterruptedException e) {
064 process.setFailureState();
065 throw new InterruptException(new ModuleContext(qedeq.getModuleAddress()));
066 }
067 }
068 if (Thread.interrupted()) {
069 process.setFailureState();
070 throw new InterruptException(new ModuleContext(qedeq.getModuleAddress()));
071 }
072 }
073 return true;
074 }
075
076 private synchronized boolean lock(final ServiceProcess process, final KernelQedeqBo qedeq) {
077 System.out.println(getName(process) + " is trying to lock " + qedeq.getName());
078 final ServiceProcess origin = (ServiceProcess) blocked.get(qedeq);
079 if (origin != null) {
080 System.out.println(getName(process) + " failed to lock " + qedeq.getName());
081 System.out.println("\tbecause it is locked by " + getName(origin));
082 return false;
083 }
084 System.out.println(getName(process) + " locked successfuly " + qedeq.getName());
085 blocked.put(qedeq, process);
086 return true;
087 }
088
089 private String getName(final ServiceProcess process) {
090 return StringUtility.format(process.getId(), 3) + " "
091 + (process.getPluginCall() != null ? StringUtility.getLastDotString(
092 process.getPluginCall().getPlugin().getPluginId()) : "");
093 }
094
095 /**
096 * Unlock module again.
097 *
098 * @param process This process must have acquired the lock.
099 * @param qedeq This module was locked before.
100 */
101 public void unlockRequiredModule(final ServiceProcess process, final KernelQedeqBo qedeq) {
102 unlock(process, qedeq);
103 }
104
105 private synchronized void unlock(final ServiceProcess process, final KernelQedeqBo qedeq) {
106 System.out.println(getName(process) + " is trying to unlock " + qedeq.getName());
107 final ServiceProcess origin = (ServiceProcess) blocked.get(qedeq);
108 if (origin != null) {
109 if (origin.equals(process)) {
110 System.out.println(getName(process) + " unlocked " + qedeq.getName());
111 blocked.remove(qedeq);
112 } else {
113 System.out.println(getName(process) + " illegal unlock try " + qedeq.getName());
114 // FIXME 20130324 m31: later on we might handle this differently but for now:
115 throw new IllegalArgumentException("locked by service process " + origin.getId());
116 }
117 } else {
118 System.out.println(getName(process) + " unlock unneccassary " + qedeq.getName());
119 }
120 }
121
122 private synchronized ServiceProcess getProcess(final KernelQedeqBo qedeq) {
123 return (ServiceProcess) blocked.get(qedeq);
124 }
125
126 private synchronized boolean isLocked(final KernelQedeqBo qedeq) {
127 return blocked.containsKey(qedeq);
128 }
129
130 private synchronized boolean isAlreadyLocked(final ServiceProcess process,
131 final KernelQedeqBo qedeq) {
132 return process.equals(blocked.get(qedeq));
133 }
134
135 private synchronized void addLock(final ServiceProcess process, final KernelQedeqBo qedeq) {
136 blocked.put(qedeq, process);
137 }
138
139 private synchronized void removeLock(final KernelQedeqBo qedeq) {
140 blocked.remove(qedeq);
141 }
142
143 }
|