diff --git a/OpenSim/Framework/Console/CommandConsole.cs b/OpenSim/Framework/Console/CommandConsole.cs index 52bcd5599b..be36cf2c10 100644 --- a/OpenSim/Framework/Console/CommandConsole.cs +++ b/OpenSim/Framework/Console/CommandConsole.cs @@ -592,9 +592,7 @@ namespace OpenSim.Framework.Console string line = ReadLine(m_defaultPrompt + "# ", true, true); if (line != String.Empty) - { - m_log.Info("[CONSOLE] Invalid command"); - } + Output("Invalid command"); } public void RunCommand(string cmd) diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index daf0a256d6..239ce3d067 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -369,6 +369,7 @@ namespace OpenSim.Framework private int m_physPrimMax = 0; private bool m_clampPrimSize = false; private int m_objectCapacity = 0; + private int m_agentCapacity = 0; private string m_regionType = String.Empty; private RegionLightShareData m_windlight = new RegionLightShareData(); protected uint m_httpPort; @@ -547,6 +548,11 @@ namespace OpenSim.Framework get { return m_objectCapacity; } } + public int AgentCapacity + { + get { return m_agentCapacity; } + } + public byte AccessLevel { get { return (byte)Util.ConvertMaturityToAccessLevel((uint)RegionSettings.Maturity); } @@ -821,6 +827,8 @@ namespace OpenSim.Framework m_objectCapacity = config.GetInt("MaxPrims", 15000); + m_agentCapacity = config.GetInt("MaxAgents", 100); + // Multi-tenancy // @@ -857,6 +865,9 @@ namespace OpenSim.Framework if (m_objectCapacity != 0) config.Set("MaxPrims", m_objectCapacity); + if (m_agentCapacity != 0) + config.Set("MaxAgents", m_agentCapacity); + if (ScopeID != UUID.Zero) config.Set("ScopeID", ScopeID.ToString()); @@ -943,6 +954,9 @@ namespace OpenSim.Framework configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, "Max objects this sim will hold", m_objectCapacity.ToString(), true); + configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, + "Max avatars this sim will hold", m_agentCapacity.ToString(), true); + configMember.addConfigurationOption("scope_id", ConfigurationOption.ConfigurationTypes.TYPE_UUID, "Scope ID for this region", ScopeID.ToString(), true); @@ -1055,6 +1069,9 @@ namespace OpenSim.Framework case "object_capacity": m_objectCapacity = (int)configuration_result; break; + case "agent_capacity": + m_agentCapacity = (int)configuration_result; + break; case "scope_id": ScopeID = (UUID)configuration_result; break; diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index c9d4c93d49..53a3f17b86 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -29,7 +29,7 @@ namespace OpenSim { public class VersionInfo { - private const string VERSION_NUMBER = "0.7.1"; + private const string VERSION_NUMBER = "0.7.2"; private const Flavour VERSION_FLAVOUR = Flavour.Dev; public enum Flavour diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs index deec444e8b..fc1ddef38c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs @@ -70,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets if (meshConfig == null) return; - m_enabled = meshConfig.GetBoolean("ColladaMesh", true); + m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true); } public void AddRegion(Scene pScene) diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs index d651cb26f8..3d4c7b7527 100644 --- a/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs @@ -72,7 +72,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets if (meshConfig == null) return; - m_enabled = meshConfig.GetBoolean("ColladaMesh", true); + m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true); } public void AddRegion(Scene pScene) diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index ab90e90b78..3aed6bac8d 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -125,7 +125,10 @@ namespace OpenSim.Region.CoreModules.World.Estate else Scene.RegionInfo.RegionSettings.AllowLandResell = true; - Scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents; + if((byte)maxAgents <= Scene.RegionInfo.AgentCapacity) + Scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents; + else + Scene.RegionInfo.RegionSettings.AgentLimit = Scene.RegionInfo.AgentCapacity; Scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index fdd5205de8..01de82451f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3665,6 +3665,15 @@ namespace OpenSim.Region.Framework.Scenes return false; } + int num = m_sceneGraph.GetNumberOfScenePresences(); + + if (num >= RegionInfo.RegionSettings.AgentLimit) + { + if (!Permissions.IsAdministrator(cAgentData.AgentID)) + return false; + } + + ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); if (childAgentUpdate != null) @@ -4966,6 +4975,17 @@ namespace OpenSim.Region.Framework.Scenes // child agent creation, thereby emulating the SL behavior. public bool QueryAccess(UUID agentID, Vector3 position, out string reason) { + int num = m_sceneGraph.GetNumberOfScenePresences(); + + if (num >= RegionInfo.RegionSettings.AgentLimit) + { + if (!Permissions.IsAdministrator(agentID)) + { + reason = "The region is full"; + return false; + } + } + reason = String.Empty; return true; } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 72f040252f..fc31b65ec6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -800,6 +800,11 @@ namespace OpenSim.Region.Framework.Scenes return m_scenePresenceArray; } + public int GetNumberOfScenePresences() + { + return m_scenePresenceArray.Count; + } + /// /// Request a scene presence by UUID. Fast, indexed lookup. /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index e8095c0831..4bca3d0099 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -81,16 +81,20 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Add an inventory item to a prim in this group. + /// Add an inventory item from a user's inventory to a prim in this scene object. /// - /// - /// - /// + /// The client adding the item. + /// The local ID of the part receiving the add. + /// The user inventory item being added. /// The item UUID that should be used by the new item. /// public bool AddInventoryItem(IClientAPI remoteClient, uint localID, InventoryItemBase item, UUID copyItemID) { +// m_log.DebugFormat( +// "[PRIM INVENTORY]: Adding inventory item {0} from {1} to part with local ID {2}", +// item.Name, remoteClient.Name, localID); + UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID; SceneObjectPart part = GetChildPart(localID); @@ -132,15 +136,20 @@ namespace OpenSim.Region.Framework.Scenes taskItem.GroupPermissions = item.GroupPermissions; taskItem.NextPermissions = item.NextPermissions; } - + taskItem.Flags = item.Flags; + +// m_log.DebugFormat( +// "[PRIM INVENTORY]: Flags are 0x{0:X} for item {1} added to part {2} by {3}", +// taskItem.Flags, taskItem.Name, localID, remoteClient.Name); + // TODO: These are pending addition of those fields to TaskInventoryItem // taskItem.SalePrice = item.SalePrice; // taskItem.SaleType = item.SaleType; taskItem.CreationDate = (uint)item.CreationDate; bool addFromAllowedDrop = false; - if (remoteClient!=null) + if (remoteClient != null) { addFromAllowedDrop = remoteClient.AgentId != part.OwnerID; } diff --git a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs index babcb54ae9..55455cc434 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs @@ -117,29 +117,40 @@ namespace OpenSim.Region.Framework.Scenes.Serialization { using (XmlTextReader reader = new XmlTextReader(sr)) { - reader.Read(); - if (reader.Name != "CoalescedObject") + try { -// m_log.DebugFormat( -// "[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() root element was {0} so returning false", -// reader.Name); + reader.Read(); + if (reader.Name != "CoalescedObject") + { + // m_log.DebugFormat( + // "[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() root element was {0} so returning false", + // reader.Name); + + return false; + } + + coa = new CoalescedSceneObjects(UUID.Zero); + reader.Read(); + + while (reader.NodeType != XmlNodeType.EndElement && reader.Name != "CoalescedObject") + { + if (reader.Name == "SceneObjectGroup") + { + string soXml = reader.ReadOuterXml(); + coa.Add(SceneObjectSerializer.FromOriginalXmlFormat(soXml)); + } + } + + reader.ReadEndElement(); // CoalescedObject + } + catch (Exception e) + { + m_log.ErrorFormat( + "[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml failed with {0} {1}", + e.Message, e.StackTrace); return false; - } - - coa = new CoalescedSceneObjects(UUID.Zero); - reader.Read(); - - while (reader.NodeType != XmlNodeType.EndElement && reader.Name != "CoalescedObject") - { - if (reader.Name == "SceneObjectGroup") - { - string soXml = reader.ReadOuterXml(); - coa.Add(SceneObjectSerializer.FromOriginalXmlFormat(soXml)); - } - } - - reader.ReadEndElement(); // CoalescedObject + } } } diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 83906d745f..77b1535563 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -298,10 +298,20 @@ namespace OpenSim.Region.Framework.Scenes if (null != objectAsset) { string xml = Utils.BytesToString(objectAsset.Data); - SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml); - - if (null != sog) - GatherAssetUuids(sog, assetUuids); + + CoalescedSceneObjects coa; + if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa)) + { + foreach (SceneObjectGroup sog in coa.Objects) + GatherAssetUuids(sog, assetUuids); + } + else + { + SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml); + + if (null != sog) + GatherAssetUuids(sog, assetUuids); + } } } diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index 373ffeb00b..42efd67d53 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs @@ -391,7 +391,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse); - m_log.DebugFormat("[FreeSwitchVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r); +// m_log.DebugFormat("[FreeSwitchVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r); return r; } @@ -458,8 +458,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice if ((land.Flags & (uint)ParcelFlags.AllowVoiceChat) == 0) { - m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel", - scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName); +// m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel", +// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName); channelUri = String.Empty; } else @@ -474,8 +474,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds); string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); - m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}", - scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r); +// m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}", +// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r); return r; } catch (Exception e) @@ -850,16 +850,25 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice Hashtable requestBody = ParseRequestBody((string)request["body"]); - string section = (string) requestBody["section"]; - - m_log.DebugFormat("[FreeSwitchVoice]: Received request for config section {0}", section); + string section = (string) requestBody["section"]; if (section == "directory") + { + string eventCallingFunction = (string)requestBody["Event-Calling-Function"]; + m_log.DebugFormat( + "[FreeSwitchVoice]: Received request for config section directory, event calling function '{0}'", + eventCallingFunction); + response = m_FreeswitchService.HandleDirectoryRequest(requestBody); + } else if (section == "dialplan") + { + m_log.DebugFormat("[FreeSwitchVoice]: Received request for config section dialplan"); + response = m_FreeswitchService.HandleDialplanRequest(requestBody); + } else - m_log.WarnFormat("[FreeSwitchVoice]: Unknown section {0} was requested.", section); + m_log.WarnFormat("[FreeSwitchVoice]: Unknown section {0} was requested from config.", section); return response; } diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 211a0a787f..64774d8ee5 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -84,10 +84,11 @@ namespace OpenSim.Region.Physics.Meshing public Meshmerizer(IConfigSource config) { IConfig start_config = config.Configs["Startup"]; + IConfig mesh_config = config.Configs["Mesh"]; decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); - useMeshiesPhysicsMesh = start_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); + useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); try { diff --git a/OpenSim/Services/FreeswitchService/FreeswitchService.cs b/OpenSim/Services/FreeswitchService/FreeswitchService.cs index 1ec89da5f7..c3f10560d7 100644 --- a/OpenSim/Services/FreeswitchService/FreeswitchService.cs +++ b/OpenSim/Services/FreeswitchService/FreeswitchService.cs @@ -56,7 +56,7 @@ namespace OpenSim.Services.FreeswitchService foreach (DictionaryEntry item in request) { - m_log.InfoFormat("[FreeSwitchDirectory]: requestBody item {0} {1}",item.Key, item.Value); +// m_log.InfoFormat("[FreeSwitchDirectory]: requestBody item {0} {1}",item.Key, item.Value); } string requestcontext = (string) request["Hunt-Context"]; @@ -146,10 +146,8 @@ namespace OpenSim.Services.FreeswitchService //domain=9.20.151.43 //ip=9.167.220.137 // this is the correct IP rather than sip_contact_host above when through a vpn or NAT setup - foreach (DictionaryEntry item in request) - { - m_log.DebugFormat("[FreeSwitchDirectory]: requestBody item {0} {1}", item.Key, item.Value); - } +// foreach (DictionaryEntry item in request) +// m_log.DebugFormat("[FreeSwitchDirectory]: requestBody item {0} {1}", item.Key, item.Value); string eventCallingFunction = (string) request["Event-Calling-Function"]; if (eventCallingFunction == null) diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index e602412be1..0af35c84ac 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -244,7 +244,7 @@ namespace OpenSim.Services.InventoryService // connector. So we disregard the principal and look // by ID. // - m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString()); + //m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString()); InventoryCollection inventory = new InventoryCollection(); inventory.UserID = principalID; inventory.Folders = new List(); diff --git a/bin/Castle.Core.dll b/bin/Castle.Core.dll deleted file mode 100644 index 2464e66160..0000000000 Binary files a/bin/Castle.Core.dll and /dev/null differ diff --git a/bin/Castle.DynamicProxy.dll b/bin/Castle.DynamicProxy.dll deleted file mode 100644 index 8540495107..0000000000 Binary files a/bin/Castle.DynamicProxy.dll and /dev/null differ diff --git a/bin/Castle.DynamicProxy2.dll b/bin/Castle.DynamicProxy2.dll deleted file mode 100644 index 83e192e901..0000000000 Binary files a/bin/Castle.DynamicProxy2.dll and /dev/null differ diff --git a/bin/DotSets.dll b/bin/DotSets.dll deleted file mode 100644 index 5225651409..0000000000 Binary files a/bin/DotSets.dll and /dev/null differ diff --git a/bin/Mono.PEToolkit.dll b/bin/Mono.PEToolkit.dll deleted file mode 100644 index b4c3e70e67..0000000000 Binary files a/bin/Mono.PEToolkit.dll and /dev/null differ diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 30ebf84dcc..7ea98d49e8 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -149,12 +149,6 @@ ; to false if you have compatibility problems. ;CacheSculptMaps = true - ; if you use Meshmerizer and want collisions for meshies, setting this to true - ; will cause OpenSim to attempt to decode meshies assets, extract the physics - ; mesh, and use it for collisions. This is currently experimental code and enabling - ; it may cause unexpected physics problems. - ;UseMeshiesPhysicsMesh = false - ; Choose one of the physics engines below ; OpenDynamicsEngine is by some distance the most developed physics engine ; basicphysics effectively does not model physics at all, making all objects phantom @@ -459,7 +453,13 @@ [Mesh] ; enable / disable Collada mesh support ; default is true - ColladaMesh = true + ; AllowMeshUpload = true + + ; if you use Meshmerizer and want collisions for meshies, setting this to true + ; will cause OpenSim to attempt to decode meshies assets, extract the physics + ; mesh, and use it for collisions. This is currently experimental code and enabling + ; it may cause unexpected physics problems. + ;UseMeshiesPhysicsMesh = false [ODEPhysicsSettings] diff --git a/bin/RAIL.dll b/bin/RAIL.dll deleted file mode 100644 index f2632d71b6..0000000000 Binary files a/bin/RAIL.dll and /dev/null differ diff --git a/bin/RegionConfig.ini.example b/bin/RegionConfig.ini.example index d45fe9de2e..ff00ddf022 100644 --- a/bin/RegionConfig.ini.example +++ b/bin/RegionConfig.ini.example @@ -28,6 +28,7 @@ ExternalHostName = "SYSTEMIP" ; PhysicalPrimMax = 10 ; ClampPrimSize = False ; MaxPrims = 15000 +; MaxAgents = 100 ; * ; * Multi-Tenancy. Only set if needed diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index ced2857331..e2e9624831 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -117,10 +117,6 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 ; EchoPort = 50505 ; AttemptSTUN = false - LocalServiceModule = "OpenSim.Services.FreeswitchService.dll:FreeswitchService" - ;; IP of your FS server - ; ServerAddress = 127.0.0.1 - ; * This is the new style authentication service. Currently, only MySQL ; * is implemented. ; * diff --git a/prebuild.xml b/prebuild.xml index 49063daa57..33a6b5005b 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2163,7 +2163,6 @@ - @@ -2201,8 +2200,6 @@ - - @@ -2235,8 +2232,6 @@ - - @@ -2274,8 +2269,6 @@ - - @@ -2304,7 +2297,6 @@ - @@ -2346,7 +2338,6 @@ - @@ -2385,7 +2376,6 @@ -