浏览代码

BETA: Reworking quest's reentrant lock usage:
* Fixing reload quest (scripts) problem, thanks DareStrike for report.
* Minor improvements in quest timers.

Zoey76 13 年之前
父节点
当前提交
28978e6114

+ 14 - 12
L2J_Server_BETA/java/com/l2jserver/gameserver/instancemanager/QuestManager.java

@@ -17,6 +17,7 @@ package com.l2jserver.gameserver.instancemanager;
 import java.io.File;
 import java.io.IOException;
 import java.util.Map;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javolution.util.FastMap;
@@ -69,25 +70,26 @@ public class QuestManager extends ScriptManager<Quest>
 	
 	public final void reloadAllQuests()
 	{
-		_log.info("Reloading Server Scripts");
-		try
+		_log.info("Reloading all server scripts.");
+		// unload all scripts
+		for (Quest quest : _quests.values())
 		{
-			// unload all scripts
-			for (Quest quest : _quests.values())
+			if (quest != null)
 			{
-				if (quest != null)
-					quest.unload(false);
+				quest.unload(false);
 			}
-			
-			_quests.clear();
+		}
+		_quests.clear();
+		
+		try
+		{
 			// now load all scripts
-			File scripts = new File(Config.DATAPACK_ROOT + "/data/scripts.cfg");
-			L2ScriptEngineManager.getInstance().executeScriptList(scripts);
+			L2ScriptEngineManager.getInstance().executeScriptList(new File(Config.DATAPACK_ROOT, "data/scripts.cfg"));
 			QuestManager.getInstance().report();
 		}
-		catch (IOException ioe)
+		catch (IOException e)
 		{
-			_log.severe("Failed loading scripts.cfg, no script going to be loaded");
+			_log.log(Level.SEVERE, "Failed loading scripts.cfg, no script going to be loaded!", e);
 		}
 	}
 	

+ 65 - 64
L2J_Server_BETA/java/com/l2jserver/gameserver/model/quest/Quest.java

@@ -19,9 +19,12 @@ import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -80,7 +83,7 @@ public class Quest extends ManagedScript
 	/**
 	 * Map containing events from String value of the event.
 	 */
-	private static Map<String, Quest> _allEventsS = new FastMap<>();
+	private static Map<String, Quest> _allEventsS = new HashMap<>();
 	
 	/**
 	 * Map containing lists of timers from the name of the timer.
@@ -89,6 +92,8 @@ public class Quest extends ManagedScript
 	private final List<Integer> _questInvolvedNpcs = new ArrayList<>();
 	
 	private final ReentrantReadWriteLock _rwLock = new ReentrantReadWriteLock();
+	private final WriteLock _writeLock = _rwLock.writeLock();
+	private final ReadLock _readLock = _rwLock.readLock();
 	
 	private final int _questId;
 	private final String _name;
@@ -299,7 +304,7 @@ public class Quest extends ManagedScript
 	 */
 	public void startQuestTimer(String name, long time, L2Npc npc, L2PcInstance player, boolean repeating)
 	{
-		List<QuestTimer> timers = getQuestTimers(name);
+		List<QuestTimer> timers = _allEventTimers.get(name);
 		// Add quest timer if timer doesn't already exist
 		if (timers == null)
 		{
@@ -314,14 +319,14 @@ public class Quest extends ManagedScript
 			// nulls act as wildcards
 			if (getQuestTimer(name, npc, player) == null)
 			{
+				_writeLock.lock();
 				try
 				{
-					_rwLock.writeLock().lock();
 					timers.add(new QuestTimer(this, name, time, npc, player, repeating));
 				}
 				finally
 				{
-					_rwLock.writeLock().unlock();
+					_writeLock.unlock();
 				}
 			}
 		}
@@ -336,67 +341,56 @@ public class Quest extends ManagedScript
 	 */
 	public QuestTimer getQuestTimer(String name, L2Npc npc, L2PcInstance player)
 	{
-		final List<QuestTimer> qt = getQuestTimers(name);
-		if ((qt == null) || qt.isEmpty())
+		final List<QuestTimer> timers = _allEventTimers.get(name);
+		if (timers != null)
 		{
-			return null;
-		}
-		try
-		{
-			_rwLock.readLock().lock();
-			for (QuestTimer timer : qt)
+			_readLock.lock();
+			try
 			{
-				if (timer != null)
+				for (QuestTimer timer : timers)
 				{
-					if (timer.isMatch(this, name, npc, player))
+					if (timer != null)
 					{
-						return timer;
+						if (timer.isMatch(this, name, npc, player))
+						{
+							return timer;
+						}
 					}
 				}
 			}
-		}
-		finally
-		{
-			_rwLock.readLock().unlock();
+			finally
+			{
+				_readLock.unlock();
+			}
 		}
 		return null;
 	}
 	
-	/**
-	 * Get all quest timers with the specified name.
-	 * @param name the name of the quest timers to get
-	 * @return a list of all quest timers matching the given name or {@code null} if none were found
-	 */
-	private List<QuestTimer> getQuestTimers(String name)
-	{
-		return _allEventTimers.get(name);
-	}
-	
 	/**
 	 * Cancel all quest timers with the specified name.
 	 * @param name the name of the quest timers to cancel
 	 */
 	public void cancelQuestTimers(String name)
 	{
-		List<QuestTimer> timers = getQuestTimers(name);
-		if (timers == null)
+		final List<QuestTimer> timers = _allEventTimers.get(name);
+		if (timers != null)
 		{
-			return;
-		}
-		try
-		{
-			_rwLock.writeLock().lock();
-			for (QuestTimer timer : timers)
+			_writeLock.lock();
+			try
 			{
-				if (timer != null)
+				for (QuestTimer timer : timers)
 				{
-					timer.cancel();
+					if (timer != null)
+					{
+						timer.cancel();
+					}
 				}
+				timers.clear();
+			}
+			finally
+			{
+				_writeLock.unlock();
 			}
-		}
-		finally
-		{
-			_rwLock.writeLock().unlock();
 		}
 	}
 	
@@ -408,10 +402,10 @@ public class Quest extends ManagedScript
 	 */
 	public void cancelQuestTimer(String name, L2Npc npc, L2PcInstance player)
 	{
-		QuestTimer timer = getQuestTimer(name, npc, player);
+		final QuestTimer timer = getQuestTimer(name, npc, player);
 		if (timer != null)
 		{
-			timer.cancel();
+			timer.cancelAndRemove();
 		}
 	}
 	
@@ -422,23 +416,21 @@ public class Quest extends ManagedScript
 	 */
 	public void removeQuestTimer(QuestTimer timer)
 	{
-		if (timer == null)
-		{
-			return;
-		}
-		final List<QuestTimer> timers = getQuestTimers(timer.getName());
-		if (timers == null)
-		{
-			return;
-		}
-		try
-		{
-			_rwLock.writeLock().lock();
-			timers.remove(timer);
-		}
-		finally
+		if (timer != null)
 		{
-			_rwLock.writeLock().unlock();
+			final List<QuestTimer> timers = _allEventTimers.get(timer.getName());
+			if (timers != null)
+			{
+				_writeLock.lock();
+				try
+				{
+					timers.remove(timer);
+				}
+				finally
+				{
+					_writeLock.unlock();
+				}
+			}
 		}
 	}
 	
@@ -2631,16 +2623,25 @@ public class Quest extends ManagedScript
 		// be restarted).
 		for (List<QuestTimer> timers : _allEventTimers.values())
 		{
-			for (QuestTimer timer : timers)
+			_readLock.lock();
+			try
 			{
-				timer.cancel();
+				for (QuestTimer timer : timers)
+				{
+					timer.cancel();
+				}
 			}
+			finally
+			{
+				_readLock.unlock();
+			}
+			timers.clear();
 		}
 		_allEventTimers.clear();
 		
 		for (Integer npcId : _questInvolvedNpcs)
 		{
-			L2NpcTemplate template = NpcTable.getInstance().getTemplate(npcId);
+			L2NpcTemplate template = NpcTable.getInstance().getTemplate(npcId.intValue());
 			if (template != null)
 			{
 				template.removeQuest(this);

+ 16 - 7
L2J_Server_BETA/java/com/l2jserver/gameserver/model/quest/QuestTimer.java

@@ -31,7 +31,7 @@ public class QuestTimer
 		@Override
 		public void run()
 		{
-			if ((this == null) || !getIsActive())
+			if (!getIsActive())
 			{
 				return;
 			}
@@ -40,7 +40,7 @@ public class QuestTimer
 			{
 				if (!getIsRepeating())
 				{
-					cancel();
+					cancelAndRemove();
 				}
 				getQuest().notifyEvent(getName(), getNpc(), getPlayer());
 			}
@@ -86,16 +86,25 @@ public class QuestTimer
 		this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
 	}
 	
+	/**
+	 * Cancel this quest timer.
+	 */
 	public void cancel()
 	{
 		_isActive = false;
-		
 		if (_schedular != null)
 		{
 			_schedular.cancel(false);
 		}
-		
-		getQuest().removeQuestTimer(this);
+	}
+	
+	/**
+	 * Cancel this quest timer and remove it from the associated quest.
+	 */
+	public void cancelAndRemove()
+	{
+		cancel();
+		_quest.removeQuestTimer(this);
 	}
 	
 	/**
@@ -112,11 +121,11 @@ public class QuestTimer
 		{
 			return false;
 		}
-		if ((quest != getQuest()) || (name.compareToIgnoreCase(getName()) != 0))
+		if ((quest != _quest) || !name.equalsIgnoreCase(getName()))
 		{
 			return false;
 		}
-		return ((npc == getNpc()) && (player == getPlayer()));
+		return ((npc == _npc) && (player == _player));
 	}
 	
 	public final boolean getIsActive()