From c268e342d19b6cc5969b1c1d94f20a3f4eb844ef Mon Sep 17 00:00:00 2001
From: Diva Canto
Date: Sun, 3 Jan 2010 09:35:12 -0800
Subject: * Changed ISimulation interface to take a GridRegion as input arg
instead of a regionHandle. * Added the RemoteSimulationConnectorModule, which
is the replacement for RESTComms. Scenes is not using this yet, only
(standalone) Login uses these region modules for now. * Completed
SimulationServiceConnector and corresponding handlers.
---
.../Resources/CoreModulePlugin.addin.xml | 2 +
.../SimulationServiceInConnectorModule.cs | 9 +-
.../Simulation/LocalSimulationConnector.cs | 129 +++++---
.../Simulation/RemoteSimulationConnector.cs | 356 +++++++++++++++++++++
4 files changed, 447 insertions(+), 49 deletions(-)
create mode 100644 OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
(limited to 'OpenSim/Region')
diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
index 8b831a5..7b9fdee 100644
--- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
+++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
@@ -56,6 +56,7 @@
+
@@ -63,6 +64,7 @@
\
\
\
+ \
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs
index f28a318..03a5124 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs
@@ -58,11 +58,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Simulation
IConfig moduleConfig = config.Configs["Modules"];
if (moduleConfig != null)
{
- string name = moduleConfig.GetString("SimulationService", "");
- if (name == Name)
+ m_Enabled = moduleConfig.GetBoolean("SimulationServiceInConnector", false);
+ if (m_Enabled)
{
- m_Enabled = true;
- m_log.Info("[SIM SERVICE]: SimulationService enabled");
+ m_log.Info("[SIM SERVICE]: SimulationService IN connector enabled");
}
}
@@ -84,7 +83,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Simulation
public string Name
{
- get { return "SimulationService"; }
+ get { return "SimulationServiceInConnectorModule"; }
}
public void AddRegion(Scene scene)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index 430cc6e..074bfb5 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -34,6 +34,7 @@ using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
+using GridRegion = OpenSim.Services.Interfaces.GridRegion;
namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
{
@@ -42,13 +43,30 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private List m_sceneList = new List();
+ private bool m_ModuleEnabled = false;
#region IRegionModule
public void Initialise(IConfigSource config)
{
- // This module is always on
- m_log.Debug("[LOCAL SIMULATION]: Enabling LocalSimulation module");
+ IConfig moduleConfig = config.Configs["Modules"];
+ if (moduleConfig != null)
+ {
+ string name = moduleConfig.GetString("SimulationServices", "");
+ if (name == Name)
+ {
+ //IConfig userConfig = config.Configs["SimulationService"];
+ //if (userConfig == null)
+ //{
+ // m_log.Error("[AVATAR CONNECTOR]: SimulationService missing from OpanSim.ini");
+ // return;
+ //}
+
+ m_ModuleEnabled = true;
+
+ m_log.Info("[SIMULATION CONNECTOR]: Local simulation enabled");
+ }
+ }
}
public void PostInitialise()
@@ -57,16 +75,24 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
public void AddRegion(Scene scene)
{
+ if (!m_ModuleEnabled)
+ return;
+
+ Init(scene);
+ scene.RegisterModuleInterface(this);
}
public void RemoveRegion(Scene scene)
{
+ if (!m_ModuleEnabled)
+ return;
+
RemoveScene(scene);
+ scene.UnregisterModuleInterface(this);
}
public void RegionLoaded(Scene scene)
{
- Init(scene);
}
public void Close()
@@ -109,7 +135,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
lock (m_sceneList)
{
m_sceneList.Add(scene);
- scene.RegisterModuleInterface(this);
}
}
@@ -119,16 +144,33 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
#region ISimulation
+ public IScene GetScene(ulong regionhandle)
+ {
+ foreach (Scene s in m_sceneList)
+ {
+ if (s.RegionInfo.RegionHandle == regionhandle)
+ return s;
+ }
+ // ? weird. should not happen
+ return m_sceneList[0];
+ }
+
/**
* Agent-related communications
*/
- public bool CreateAgent(ulong regionHandle, AgentCircuitData aCircuit, uint teleportFlags, out string reason)
+ public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason)
{
+ if (destination == null)
+ {
+ reason = "Given destination was null";
+ m_log.DebugFormat("[LOCAL SIMULATION CONNECTOR]: CreateAgent was given a null destination");
+ return false;
+ }
foreach (Scene s in m_sceneList)
{
- if (s.RegionInfo.RegionHandle == regionHandle)
+ if (s.RegionInfo.RegionHandle == destination.RegionHandle)
{
// m_log.DebugFormat("[LOCAL COMMS]: Found region {0} to send SendCreateChildAgent", regionHandle);
return s.NewUserConnection(aCircuit, teleportFlags, out reason);
@@ -136,17 +178,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
}
// m_log.DebugFormat("[LOCAL COMMS]: Did not find region {0} for SendCreateChildAgent", regionHandle);
- uint x = 0, y = 0;
- Utils.LongToUInts(regionHandle, out x, out y);
- reason = "Did not find region " + x + "-" + y;
+ reason = "Did not find region " + destination.RegionName;
return false;
}
- public bool UpdateAgent(ulong regionHandle, AgentData cAgentData)
+ public bool UpdateAgent(GridRegion destination, AgentData cAgentData)
{
+ if (destination == null)
+ return false;
+
foreach (Scene s in m_sceneList)
{
- if (s.RegionInfo.RegionHandle == regionHandle)
+ if (s.RegionInfo.RegionHandle == destination.RegionHandle)
{
//m_log.DebugFormat(
// "[LOCAL COMMS]: Found region {0} {1} to send ChildAgentUpdate",
@@ -161,11 +204,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return false;
}
- public bool UpdateAgent(ulong regionHandle, AgentPosition cAgentData)
+ public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData)
{
+ if (destination == null)
+ return false;
+
foreach (Scene s in m_sceneList)
{
- if (s.RegionInfo.RegionHandle == regionHandle)
+ if (s.RegionInfo.RegionHandle == destination.RegionHandle)
{
//m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate");
s.IncomingChildAgentDataUpdate(cAgentData);
@@ -176,12 +222,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return false;
}
- public bool RetrieveAgent(ulong regionHandle, UUID id, out IAgentData agent)
+ public bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent)
{
agent = null;
+
+ if (destination == null)
+ return false;
+
foreach (Scene s in m_sceneList)
{
- if (s.RegionInfo.RegionHandle == regionHandle)
+ if (s.RegionInfo.RegionHandle == destination.RegionHandle)
{
//m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate");
return s.IncomingRetrieveRootAgent(id, out agent);
@@ -191,16 +241,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return false;
}
- public bool ReleaseAgent(ulong regionHandle, UUID id, string uri)
+ public bool ReleaseAgent(GridRegion destination, UUID id, string uri)
{
- //uint x, y;
- //Utils.LongToUInts(regionHandle, out x, out y);
- //x = x / Constants.RegionSize;
- //y = y / Constants.RegionSize;
- //m_log.Debug("\n >>> Local SendReleaseAgent " + x + "-" + y);
+ if (destination == null)
+ return false;
+
foreach (Scene s in m_sceneList)
{
- if (s.RegionInfo.RegionHandle == regionHandle)
+ if (s.RegionInfo.RegionHandle == destination.RegionHandle)
{
//m_log.Debug("[LOCAL COMMS]: Found region to SendReleaseAgent");
return s.IncomingReleaseAgent(id);
@@ -210,16 +258,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return false;
}
- public bool CloseAgent(ulong regionHandle, UUID id)
+ public bool CloseAgent(GridRegion destination, UUID id)
{
- //uint x, y;
- //Utils.LongToUInts(regionHandle, out x, out y);
- //x = x / Constants.RegionSize;
- //y = y / Constants.RegionSize;
- //m_log.Debug("\n >>> Local SendCloseAgent " + x + "-" + y);
+ if (destination == null)
+ return false;
+
foreach (Scene s in m_sceneList)
{
- if (s.RegionInfo.RegionHandle == regionHandle)
+ if (s.RegionInfo.RegionHandle == destination.RegionHandle)
{
//m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent");
return s.IncomingCloseAgent(id);
@@ -233,11 +279,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
* Object-related communications
*/
- public bool CreateObject(ulong regionHandle, ISceneObject sog, bool isLocalCall)
+ public bool CreateObject(GridRegion destination, ISceneObject sog, bool isLocalCall)
{
+ if (destination == null)
+ return false;
+
foreach (Scene s in m_sceneList)
{
- if (s.RegionInfo.RegionHandle == regionHandle)
+ if (s.RegionInfo.RegionHandle == destination.RegionHandle)
{
//m_log.Debug("[LOCAL COMMS]: Found region to SendCreateObject");
if (isLocalCall)
@@ -257,11 +306,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return false;
}
- public bool CreateObject(ulong regionHandle, UUID userID, UUID itemID)
+ public bool CreateObject(GridRegion destination, UUID userID, UUID itemID)
{
+ if (destination == null)
+ return false;
+
foreach (Scene s in m_sceneList)
{
- if (s.RegionInfo.RegionHandle == regionHandle)
+ if (s.RegionInfo.RegionHandle == destination.RegionHandle)
{
return s.IncomingCreateObject(userID, itemID);
}
@@ -274,17 +326,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
#region Misc
- public IScene GetScene(ulong regionhandle)
- {
- foreach (Scene s in m_sceneList)
- {
- if (s.RegionInfo.RegionHandle == regionhandle)
- return s;
- }
- // ? weird. should not happen
- return m_sceneList[0];
- }
-
public bool IsLocalRegion(ulong regionhandle)
{
foreach (Scene s in m_sceneList)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
new file mode 100644
index 0000000..b7dc283
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Net;
+using System.Reflection;
+using System.Text;
+using log4net;
+using Nini.Config;
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+using OpenSim.Framework;
+using OpenSim.Framework.Communications;
+using OpenSim.Framework.Communications.Clients;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes;
+using OpenSim.Region.Framework.Scenes.Hypergrid;
+using OpenSim.Region.Framework.Scenes.Serialization;
+using OpenSim.Services.Interfaces;
+using OpenSim.Services.Connectors.Simulation;
+using GridRegion = OpenSim.Services.Interfaces.GridRegion;
+
+namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
+{
+ public class RemoteSimulationConnectorModule : ISharedRegionModule, ISimulationService
+ {
+ private bool initialized = false;
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ protected bool m_enabled = false;
+ protected Scene m_aScene;
+ // RemoteSimulationConnector does not care about local regions; it delegates that to the Local module
+ protected LocalSimulationConnectorModule m_localBackend;
+ protected SimulationServiceConnector m_remoteConnector;
+
+ protected CommunicationsManager m_commsManager;
+
+ protected IHyperlinkService m_hyperlinkService;
+
+ protected bool m_safemode;
+ protected IPAddress m_thisIP;
+
+ #region IRegionModule
+
+ public virtual void Initialise(IConfigSource config)
+ {
+
+ IConfig moduleConfig = config.Configs["Modules"];
+ if (moduleConfig != null)
+ {
+ string name = moduleConfig.GetString("SimulationServices", "");
+ if (name == Name)
+ {
+ //IConfig userConfig = config.Configs["SimulationService"];
+ //if (userConfig == null)
+ //{
+ // m_log.Error("[AVATAR CONNECTOR]: SimulationService missing from OpanSim.ini");
+ // return;
+ //}
+
+ m_remoteConnector = new SimulationServiceConnector();
+
+ m_enabled = true;
+
+ m_log.Info("[SIMULATION CONNECTOR]: Remote simulation enabled");
+ }
+ }
+ }
+
+ public virtual void PostInitialise()
+ {
+ }
+
+ public virtual void Close()
+ {
+ }
+
+ public void AddRegion(Scene scene)
+ {
+ }
+
+ public void RemoveRegion(Scene scene)
+ {
+ if (m_enabled)
+ {
+ m_localBackend.RemoveScene(scene);
+ scene.UnregisterModuleInterface(this);
+ }
+ }
+
+ public void RegionLoaded(Scene scene)
+ {
+ if (m_enabled)
+ {
+ if (!initialized)
+ {
+ InitOnce(scene);
+ initialized = true;
+ }
+ InitEach(scene);
+ }
+ }
+
+ public Type ReplaceableInterface
+ {
+ get { return null; }
+ }
+
+ public virtual string Name
+ {
+ get { return "RemoteSimulationConnectorModule"; }
+ }
+
+ protected virtual void InitEach(Scene scene)
+ {
+ m_localBackend.Init(scene);
+ scene.RegisterModuleInterface(this);
+ }
+
+ protected virtual void InitOnce(Scene scene)
+ {
+ m_localBackend = new LocalSimulationConnectorModule();
+ m_commsManager = scene.CommsManager;
+ m_aScene = scene;
+ m_hyperlinkService = m_aScene.RequestModuleInterface();
+ //m_regionClient = new RegionToRegionClient(m_aScene, m_hyperlinkService);
+ m_thisIP = Util.GetHostFromDNS(scene.RegionInfo.ExternalHostName);
+ }
+
+ #endregion /* IRegionModule */
+
+ #region IInterregionComms
+
+ public IScene GetScene(ulong handle)
+ {
+ return m_localBackend.GetScene(handle);
+ }
+
+ /**
+ * Agent-related communications
+ */
+
+ public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason)
+ {
+ if (destination == null)
+ {
+ reason = "Given destination was null";
+ m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CreateAgent was given a null destination");
+ return false;
+ }
+
+ // Try local first
+ if (m_localBackend.CreateAgent(destination, aCircuit, teleportFlags, out reason))
+ return true;
+
+ // else do the remote thing
+ if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
+ {
+ //m_regionClient.SendUserInformation(regInfo, aCircuit);
+ return m_remoteConnector.CreateAgent(destination, aCircuit, teleportFlags, out reason);
+ }
+ return false;
+ }
+
+ public bool UpdateAgent(GridRegion destination, AgentData cAgentData)
+ {
+ if (destination == null)
+ return false;
+
+ // Try local first
+ if (m_localBackend.UpdateAgent(destination, cAgentData))
+ return true;
+
+ // else do the remote thing
+ if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
+ return m_remoteConnector.UpdateAgent(destination, cAgentData);
+
+ return false;
+
+ }
+
+ public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData)
+ {
+ if (destination == null)
+ return false;
+
+ // Try local first
+ if (m_localBackend.UpdateAgent(destination, cAgentData))
+ return true;
+
+ // else do the remote thing
+ if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
+ return m_remoteConnector.UpdateAgent(destination, cAgentData);
+
+ return false;
+
+ }
+
+ public bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent)
+ {
+ agent = null;
+
+ if (destination == null)
+ return false;
+
+ // Try local first
+ if (m_localBackend.RetrieveAgent(destination, id, out agent))
+ return true;
+
+ // else do the remote thing
+ if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
+ return m_remoteConnector.RetrieveAgent(destination, id, out agent);
+
+ return false;
+
+ }
+
+ public bool ReleaseAgent(GridRegion destination, UUID id, string uri)
+ {
+ if (destination == null)
+ return false;
+
+ // Try local first
+ if (m_localBackend.ReleaseAgent(destination, id, uri))
+ return true;
+
+ // else do the remote thing
+ if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
+ return m_remoteConnector.ReleaseAgent(destination, id, uri);
+
+ return false;
+ }
+
+
+ public bool CloseAgent(GridRegion destination, UUID id)
+ {
+ if (destination == null)
+ return false;
+
+ // Try local first
+ if (m_localBackend.CloseAgent(destination, id))
+ return true;
+
+ // else do the remote thing
+ if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
+ return m_remoteConnector.CloseAgent(destination, id);
+
+ return false;
+ }
+
+ /**
+ * Object-related communications
+ */
+
+ public bool CreateObject(GridRegion destination, ISceneObject sog, bool isLocalCall)
+ {
+ if (destination == null)
+ return false;
+
+ // Try local first
+ if (m_localBackend.CreateObject(destination, sog, true))
+ {
+ //m_log.Debug("[REST COMMS]: LocalBackEnd SendCreateObject succeeded");
+ return true;
+ }
+
+ // else do the remote thing
+ if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
+ return m_remoteConnector.CreateObject(destination, sog, isLocalCall);
+
+ return false;
+ }
+
+ public bool CreateObject(GridRegion destination, UUID userID, UUID itemID)
+ {
+ // Not Implemented
+ return false;
+ }
+
+ #endregion /* IInterregionComms */
+
+
+ protected class RegionToRegionClient : RegionClient
+ {
+ Scene m_aScene = null;
+ IHyperlinkService m_hyperlinkService;
+
+ public RegionToRegionClient(Scene s, IHyperlinkService hyperService)
+ {
+ m_aScene = s;
+ m_hyperlinkService = hyperService;
+ }
+
+ public override ulong GetRegionHandle(ulong handle)
+ {
+ if (m_aScene.SceneGridService is HGSceneCommunicationService)
+ {
+ if (m_hyperlinkService != null)
+ return m_hyperlinkService.FindRegionHandle(handle);
+ }
+
+ return handle;
+ }
+
+ public override bool IsHyperlink(ulong handle)
+ {
+ if (m_aScene.SceneGridService is HGSceneCommunicationService)
+ {
+ if ((m_hyperlinkService != null) && (m_hyperlinkService.GetHyperlinkRegion(handle) != null))
+ return true;
+ }
+ return false;
+ }
+
+ public override void SendUserInformation(GridRegion regInfo, AgentCircuitData aCircuit)
+ {
+ if (m_hyperlinkService != null)
+ m_hyperlinkService.SendUserInformation(regInfo, aCircuit);
+
+ }
+
+ public override void AdjustUserInformation(AgentCircuitData aCircuit)
+ {
+ if (m_hyperlinkService != null)
+ m_hyperlinkService.AdjustUserInformation(aCircuit);
+ }
+ }
+
+ }
+}
--
cgit v1.1