diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
index 7529e01450..ee3d7c58bc 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
@@ -2304,6 +2304,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController
/// UUID of the region
/// - region_name
/// region name
+ /// - merge
+ /// true if oar should be merged
+ /// - skip-assets
+ /// true if assets should be skiped
///
///
/// region_uuid takes precedence over
@@ -2362,10 +2366,22 @@ namespace OpenSim.ApplicationPlugins.RemoteController
throw new Exception(String.Format("failed to switch to region {0}", region_name));
}
else throw new Exception("neither region_name nor region_uuid given");
+
+ bool mergeOar = false;
+ bool skipAssets = false;
+
+ if ((string)requestData["merge"] == "true")
+ {
+ mergeOar = true;
+ }
+ if ((string)requestData["skip-assets"] == "true")
+ {
+ skipAssets = true;
+ }
IRegionArchiverModule archiver = scene.RequestModuleInterface();
if (archiver != null)
- archiver.DearchiveRegion(filename);
+ archiver.DearchiveRegion(filename, mergeOar, skipAssets, Guid.Empty);
else
throw new Exception("Archiver module not present for scene");
@@ -2405,6 +2421,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController
/// UUID of the region
/// - region_name
/// region name
+ /// - profile
+ /// profile url
+ /// - noassets
+ /// true if no assets should be saved
///
///
/// region_uuid takes precedence over
@@ -2462,12 +2482,29 @@ namespace OpenSim.ApplicationPlugins.RemoteController
}
else throw new Exception("neither region_name nor region_uuid given");
+ Dictionary options = new Dictionary();
+
+ //if (requestData.Contains("version"))
+ //{
+ // options["version"] = (string)requestData["version"];
+ //}
+
+ if (requestData.Contains("profile"))
+ {
+ options["profile"] = (string)requestData["profile"];
+ }
+
+ if (requestData["noassets"] == "true")
+ {
+ options["noassets"] = (string)requestData["noassets"] ;
+ }
+
IRegionArchiverModule archiver = scene.RequestModuleInterface();
if (archiver != null)
{
scene.EventManager.OnOarFileSaved += RemoteAdminOarSaveCompleted;
- archiver.ArchiveRegion(filename, new Dictionary());
+ archiver.ArchiveRegion(filename, options);
lock (m_saveOarLock) Monitor.Wait(m_saveOarLock,5000);
scene.EventManager.OnOarFileSaved -= RemoteAdminOarSaveCompleted;
}
diff --git a/OpenSim/Framework/AssetBase.cs b/OpenSim/Framework/AssetBase.cs
index 8e24f911c4..06e040fc11 100644
--- a/OpenSim/Framework/AssetBase.cs
+++ b/OpenSim/Framework/AssetBase.cs
@@ -281,6 +281,7 @@ namespace OpenSim.Framework
return m_id;
}
+
set
{
UUID uuid = UUID.Zero;
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 31a45e2372..0a4dcacf90 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -741,7 +741,7 @@ namespace OpenSim.Framework
bool IsActive { get; set; }
///
- /// Determines whether the client is logging out or not.
+ /// Determines whether the client is or has been removed from a given scene
///
bool IsLoggingOut { get; set; }
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 5c3cad4e69..64b9c3ed17 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -31,6 +31,7 @@ using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
+using System.Text.RegularExpressions;
using System.Threading;
using System.Timers;
using log4net;
@@ -124,7 +125,6 @@ namespace OpenSim.Framework.Servers
m_logFileAppender = appender;
}
}
-
}
///
@@ -443,45 +443,68 @@ namespace OpenSim.Framework.Servers
{
string buildVersion = string.Empty;
- // Add commit hash and date information if available
- // The commit hash and date are stored in a file bin/.version
- // This file can automatically created by a post
- // commit script in the opensim git master repository or
- // by issuing the follwoing command from the top level
- // directory of the opensim repository
- // git log -n 1 --pretty="format:%h: %ci" >bin/.version
- // For the full git commit hash use %H instead of %h
- //
// The subversion information is deprecated and will be removed at a later date
// Add subversion revision information if available
// Try file "svn_revision" in the current directory first, then the .svn info.
// This allows to make the revision available in simulators not running from the source tree.
// FIXME: Making an assumption about the directory we're currently in - we do this all over the place
// elsewhere as well
+ string gitDir = "../.git/";
+ string gitRefPointerPath = gitDir + "HEAD";
+
string svnRevisionFileName = "svn_revision";
string svnFileName = ".svn/entries";
- string gitCommitFileName = ".version";
+ string manualVersionFileName = ".version";
string inputLine;
int strcmp;
- if (File.Exists(gitCommitFileName))
+ if (File.Exists(manualVersionFileName))
{
- StreamReader CommitFile = File.OpenText(gitCommitFileName);
- buildVersion = CommitFile.ReadLine();
- CommitFile.Close();
+ using (StreamReader CommitFile = File.OpenText(manualVersionFileName))
+ buildVersion = CommitFile.ReadLine();
+
m_version += buildVersion ?? "";
}
+ else if (File.Exists(gitRefPointerPath))
+ {
+// m_log.DebugFormat("[OPENSIM]: Found {0}", gitRefPointerPath);
- // Remove the else logic when subversion mirror is no longer used
+ string rawPointer = "";
+
+ using (StreamReader pointerFile = File.OpenText(gitRefPointerPath))
+ rawPointer = pointerFile.ReadLine();
+
+// m_log.DebugFormat("[OPENSIM]: rawPointer [{0}]", rawPointer);
+
+ Match m = Regex.Match(rawPointer, "^ref: (.+)$");
+
+ if (m.Success)
+ {
+// m_log.DebugFormat("[OPENSIM]: Matched [{0}]", m.Groups[1].Value);
+
+ string gitRef = m.Groups[1].Value;
+ string gitRefPath = gitDir + gitRef;
+ if (File.Exists(gitRefPath))
+ {
+// m_log.DebugFormat("[OPENSIM]: Found gitRefPath [{0}]", gitRefPath);
+
+ using (StreamReader refFile = File.OpenText(gitRefPath))
+ {
+ string gitHash = refFile.ReadLine();
+ m_version += gitHash.Substring(0, 7);
+ }
+ }
+ }
+ }
else
{
+ // Remove the else logic when subversion mirror is no longer used
if (File.Exists(svnRevisionFileName))
{
StreamReader RevisionFile = File.OpenText(svnRevisionFileName);
buildVersion = RevisionFile.ReadLine();
buildVersion.Trim();
RevisionFile.Close();
-
}
if (string.IsNullOrEmpty(buildVersion) && File.Exists(svnFileName))
diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs
index 2d81ea8432..d19852b1ee 100644
--- a/OpenSim/Region/Application/ConfigurationLoader.cs
+++ b/OpenSim/Region/Application/ConfigurationLoader.cs
@@ -328,7 +328,7 @@ namespace OpenSim
config.Set("meshing", "Meshmerizer");
config.Set("physical_prim", true);
config.Set("see_into_this_sim_from_neighbor", true);
- config.Set("serverside_object_permissions", false);
+ config.Set("serverside_object_permissions", true);
config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");
config.Set("storage_prim_inventories", true);
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 9ef5bc95c3..d85d727986 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -86,6 +86,8 @@ namespace Flotsam.RegionModules.AssetCache
private List m_CurrentlyWriting = new List();
#endif
+ private bool m_FileCacheEnabled = true;
+
private ExpiringCache m_MemoryCache;
private bool m_MemoryCacheEnabled = false;
@@ -146,6 +148,7 @@ namespace Flotsam.RegionModules.AssetCache
}
else
{
+ m_FileCacheEnabled = assetConfig.GetBoolean("FileCacheEnabled", m_FileCacheEnabled);
m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory);
m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled);
@@ -173,7 +176,7 @@ namespace Flotsam.RegionModules.AssetCache
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory);
- if ((m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero))
+ if (m_FileCacheEnabled && (m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero))
{
m_CacheCleanTimer = new System.Timers.Timer(m_FileExpirationCleanupTimer.TotalMilliseconds);
m_CacheCleanTimer.AutoReset = true;
@@ -226,7 +229,6 @@ namespace Flotsam.RegionModules.AssetCache
if (m_AssetService == null)
{
m_AssetService = scene.RequestModuleInterface();
-
}
}
}
@@ -250,18 +252,15 @@ namespace Flotsam.RegionModules.AssetCache
private void UpdateMemoryCache(string key, AssetBase asset)
{
- if (m_MemoryCacheEnabled)
- m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration);
+ m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration);
}
- public void Cache(AssetBase asset)
+ private void UpdateFileCache(string key, AssetBase asset)
{
// TODO: Spawn this off to some seperate thread to do the actual writing
if (asset != null)
{
- UpdateMemoryCache(asset.ID, asset);
-
- string filename = GetFileName(asset.ID);
+ string filename = GetFileName(key);
try
{
@@ -278,8 +277,8 @@ namespace Flotsam.RegionModules.AssetCache
catch
{
}
- } else {
-
+ } else {
+
// Once we start writing, make sure we flag that we're writing
// that object to the cache so that we don't try to write the
// same file multiple times.
@@ -319,78 +318,118 @@ namespace Flotsam.RegionModules.AssetCache
}
}
+ public void Cache(AssetBase asset)
+ {
+ // TODO: Spawn this off to some seperate thread to do the actual writing
+ if (asset != null)
+ {
+ //m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID);
+
+ if (m_MemoryCacheEnabled)
+ UpdateMemoryCache(asset.ID, asset);
+
+ if (m_FileCacheEnabled)
+ UpdateFileCache(asset.ID, asset);
+ }
+ }
+
+ ///
+ /// Try to get an asset from the in-memory cache.
+ ///
+ ///
+ ///
+ private AssetBase GetFromMemoryCache(string id)
+ {
+ AssetBase asset = null;
+
+ if (m_MemoryCache.TryGetValue(id, out asset))
+ m_MemoryHits++;
+
+ return asset;
+ }
+
+ ///
+ /// Try to get an asset from the file cache.
+ ///
+ ///
+ ///
+ private AssetBase GetFromFileCache(string id)
+ {
+ AssetBase asset = null;
+
+ string filename = GetFileName(id);
+ if (File.Exists(filename))
+ {
+ FileStream stream = null;
+ try
+ {
+ stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
+ BinaryFormatter bformatter = new BinaryFormatter();
+
+ asset = (AssetBase)bformatter.Deserialize(stream);
+
+ UpdateMemoryCache(id, asset);
+
+ m_DiskHits++;
+ }
+ catch (System.Runtime.Serialization.SerializationException e)
+ {
+ LogException(e);
+
+ // If there was a problem deserializing the asset, the asset may
+ // either be corrupted OR was serialized under an old format
+ // {different version of AssetBase} -- we should attempt to
+ // delete it and re-cache
+ File.Delete(filename);
+ }
+ catch (Exception e)
+ {
+ LogException(e);
+ }
+ finally
+ {
+ if (stream != null)
+ stream.Close();
+ }
+ }
+
+
+#if WAIT_ON_INPROGRESS_REQUESTS
+ // Check if we're already downloading this asset. If so, try to wait for it to
+ // download.
+ if (m_WaitOnInprogressTimeout > 0)
+ {
+ m_RequestsForInprogress++;
+
+ ManualResetEvent waitEvent;
+ if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent))
+ {
+ waitEvent.WaitOne(m_WaitOnInprogressTimeout);
+ return Get(id);
+ }
+ }
+#else
+ // Track how often we have the problem that an asset is requested while
+ // it is still being downloaded by a previous request.
+ if (m_CurrentlyWriting.Contains(filename))
+ {
+ m_RequestsForInprogress++;
+ }
+#endif
+
+ return asset;
+ }
+
public AssetBase Get(string id)
{
m_Requests++;
AssetBase asset = null;
- if (m_MemoryCacheEnabled && m_MemoryCache.TryGetValue(id, out asset))
- {
- m_MemoryHits++;
- }
- else
- {
- string filename = GetFileName(id);
- if (File.Exists(filename))
- {
- FileStream stream = null;
- try
- {
- stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
- BinaryFormatter bformatter = new BinaryFormatter();
-
- asset = (AssetBase)bformatter.Deserialize(stream);
-
- UpdateMemoryCache(id, asset);
-
- m_DiskHits++;
- }
- catch (System.Runtime.Serialization.SerializationException e)
- {
- LogException(e);
-
- // If there was a problem deserializing the asset, the asset may
- // either be corrupted OR was serialized under an old format
- // {different version of AssetBase} -- we should attempt to
- // delete it and re-cache
- File.Delete(filename);
- }
- catch (Exception e)
- {
- LogException(e);
- }
- finally
- {
- if (stream != null)
- stream.Close();
- }
- }
-
-
-#if WAIT_ON_INPROGRESS_REQUESTS
- // Check if we're already downloading this asset. If so, try to wait for it to
- // download.
- if (m_WaitOnInprogressTimeout > 0)
- {
- m_RequestsForInprogress++;
-
- ManualResetEvent waitEvent;
- if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent))
- {
- waitEvent.WaitOne(m_WaitOnInprogressTimeout);
- return Get(id);
- }
- }
-#else
- // Track how often we have the problem that an asset is requested while
- // it is still being downloaded by a previous request.
- if (m_CurrentlyWriting.Contains(filename))
- {
- m_RequestsForInprogress++;
- }
-#endif
- }
+ if (m_MemoryCacheEnabled)
+ asset = GetFromMemoryCache(id);
+ else if (m_FileCacheEnabled)
+ asset = GetFromFileCache(id);
if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0))
{
@@ -424,10 +463,13 @@ namespace Flotsam.RegionModules.AssetCache
try
{
- string filename = GetFileName(id);
- if (File.Exists(filename))
+ if (m_FileCacheEnabled)
{
- File.Delete(filename);
+ string filename = GetFileName(id);
+ if (File.Exists(filename))
+ {
+ File.Delete(filename);
+ }
}
if (m_MemoryCacheEnabled)
@@ -442,11 +484,14 @@ namespace Flotsam.RegionModules.AssetCache
public void Clear()
{
if (m_LogLevel >= 2)
- m_log.Debug("[FLOTSAM ASSET CACHE]: Clearing Cache.");
+ m_log.Debug("[FLOTSAM ASSET CACHE]: Clearing caches.");
- foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
+ if (m_FileCacheEnabled)
{
- Directory.Delete(dir);
+ foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
+ {
+ Directory.Delete(dir);
+ }
}
if (m_MemoryCacheEnabled)
@@ -481,9 +526,9 @@ namespace Flotsam.RegionModules.AssetCache
/// removes empty tier directories.
///
///
+ ///
private void CleanExpiredFiles(string dir, DateTime purgeLine)
{
-
foreach (string file in Directory.GetFiles(dir))
{
if (File.GetLastAccessTime(file) < purgeLine)
@@ -721,18 +766,28 @@ namespace Flotsam.RegionModules.AssetCache
switch (cmd)
{
case "status":
- m_log.InfoFormat("[FLOTSAM ASSET CACHE] Memory Cache : {0} assets", m_MemoryCache.Count);
+ if (m_MemoryCacheEnabled)
+ m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Cache : {0} assets", m_MemoryCache.Count);
+ else
+ m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory cache disabled");
- int fileCount = GetFileCacheCount(m_CacheDirectory);
- m_log.InfoFormat("[FLOTSAM ASSET CACHE] File Cache : {0} assets", fileCount);
-
- foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac"))
+ if (m_FileCacheEnabled)
{
- m_log.Info("[FLOTSAM ASSET CACHE] Deep Scans were performed on the following regions:");
-
- string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac","");
- DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s);
- m_log.InfoFormat("[FLOTSAM ASSET CACHE] Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss"));
+ int fileCount = GetFileCacheCount(m_CacheDirectory);
+ m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Cache : {0} assets", fileCount);
+
+ foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac"))
+ {
+ m_log.Info("[FLOTSAM ASSET CACHE]: Deep Scans were performed on the following regions:");
+
+ string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac","");
+ DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s);
+ m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss"));
+ }
+ }
+ else
+ {
+ m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache disabled");
}
break;
@@ -740,7 +795,7 @@ namespace Flotsam.RegionModules.AssetCache
case "clear":
if (cmdparams.Length < 2)
{
- m_log.Warn("[FLOTSAM ASSET CACHE] Usage is fcache clear [file] [memory]");
+ m_log.Warn("[FLOTSAM ASSET CACHE]: Usage is fcache clear [file] [memory]");
break;
}
@@ -761,36 +816,48 @@ namespace Flotsam.RegionModules.AssetCache
if (clearMemory)
{
- m_MemoryCache.Clear();
- m_log.Info("[FLOTSAM ASSET CACHE] Memory cache cleared.");
+ if (m_MemoryCacheEnabled)
+ {
+ m_MemoryCache.Clear();
+ m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache cleared.");
+ }
+ else
+ {
+ m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache not enabled.");
+ }
}
if (clearFile)
{
- ClearFileCache();
- m_log.Info("[FLOTSAM ASSET CACHE] File cache cleared.");
+ if (m_FileCacheEnabled)
+ {
+ ClearFileCache();
+ m_log.Info("[FLOTSAM ASSET CACHE]: File cache cleared.");
+ }
+ else
+ {
+ m_log.Info("[FLOTSAM ASSET CACHE]: File cache not enabled.");
+ }
}
break;
case "assets":
- m_log.Info("[FLOTSAM ASSET CACHE] Caching all assets, in all scenes.");
+ m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes.");
Util.FireAndForget(delegate {
int assetsCached = CacheScenes();
- m_log.InfoFormat("[FLOTSAM ASSET CACHE] Completed Scene Caching, {0} assets found.", assetsCached);
+ m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached);
});
break;
case "expire":
-
-
if (cmdparams.Length < 3)
{
- m_log.InfoFormat("[FLOTSAM ASSET CACHE] Invalid parameters for Expire, please specify a valid date & time", cmd);
+ m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Invalid parameters for Expire, please specify a valid date & time", cmd);
break;
}
@@ -808,26 +875,28 @@ namespace Flotsam.RegionModules.AssetCache
if (!DateTime.TryParse(s_expirationDate, out expirationDate))
{
- m_log.InfoFormat("[FLOTSAM ASSET CACHE] {0} is not a valid date & time", cmd);
+ m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} is not a valid date & time", cmd);
break;
}
- CleanExpiredFiles(m_CacheDirectory, expirationDate);
+ if (m_FileCacheEnabled)
+ CleanExpiredFiles(m_CacheDirectory, expirationDate);
+ else
+ m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache not active, not clearing.");
break;
default:
- m_log.InfoFormat("[FLOTSAM ASSET CACHE] Unknown command {0}", cmd);
+ m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Unknown command {0}", cmd);
break;
}
}
else if (cmdparams.Length == 1)
{
- m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache status - Display cache status");
- m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache clearmem - Remove all assets cached in memory");
- m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache clearfile - Remove all assets cached on disk");
- m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache cachescenes - Attempt a deep cache of all assets in all scenes");
- m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache - Purge assets older then the specified date & time");
-
+ m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache status - Display cache status");
+ m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearmem - Remove all assets cached in memory");
+ m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearfile - Remove all assets cached on disk");
+ m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache cachescenes - Attempt a deep cache of all assets in all scenes");
+ m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache - Purge assets older then the specified date & time");
}
}
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
new file mode 100644
index 0000000000..63b0c311f1
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
@@ -0,0 +1,127 @@
+/*
+ * 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.Generic;
+using System.IO;
+using System.Reflection;
+using System.Threading;
+using log4net.Config;
+using Nini.Config;
+using NUnit.Framework;
+using OpenMetaverse;
+using OpenMetaverse.Assets;
+using Flotsam.RegionModules.AssetCache;
+using OpenSim.Framework;
+using OpenSim.Region.Framework.Scenes;
+using OpenSim.Region.Framework.Scenes.Serialization;
+using OpenSim.Tests.Common;
+using OpenSim.Tests.Common.Mock;
+
+namespace OpenSim.Region.CoreModules.Asset.Tests
+{
+ ///
+ /// At the moment we're only test the in-memory part of the FlotsamAssetCache. This is a considerable weakness.
+ ///
+ [TestFixture]
+ public class FlotsamAssetCacheTests
+ {
+ protected TestScene m_scene;
+ protected FlotsamAssetCache m_cache;
+
+ [SetUp]
+ public void SetUp()
+ {
+ IConfigSource config = new IniConfigSource();
+
+ config.AddConfig("Modules");
+ config.Configs["Modules"].Set("AssetCaching", "FlotsamAssetCache");
+ config.AddConfig("AssetCache");
+ config.Configs["AssetCache"].Set("FileCacheEnabled", "false");
+ config.Configs["AssetCache"].Set("MemoryCacheEnabled", "true");
+
+ m_cache = new FlotsamAssetCache();
+ m_scene = SceneSetupHelpers.SetupScene();
+ SceneSetupHelpers.SetupSceneModules(m_scene, config, m_cache);
+ }
+
+ [Test]
+ public void TestCacheAsset()
+ {
+ TestHelper.InMethod();
+// log4net.Config.XmlConfigurator.Configure();
+
+ AssetBase asset = AssetHelpers.CreateAsset();
+ asset.ID = TestHelper.ParseTail(0x1).ToString();
+
+ // Check we don't get anything before the asset is put in the cache
+ AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString());
+ Assert.That(retrievedAsset, Is.Null);
+
+ m_cache.Store(asset);
+
+ // Check that asset is now in cache
+ retrievedAsset = m_cache.Get(asset.ID.ToString());
+ Assert.That(retrievedAsset, Is.Not.Null);
+ Assert.That(retrievedAsset.ID, Is.EqualTo(asset.ID));
+ }
+
+ [Test]
+ public void TestExpireAsset()
+ {
+ TestHelper.InMethod();
+// log4net.Config.XmlConfigurator.Configure();
+
+ AssetBase asset = AssetHelpers.CreateAsset();
+ asset.ID = TestHelper.ParseTail(0x2).ToString();
+
+ m_cache.Store(asset);
+
+ m_cache.Expire(asset.ID);
+
+ AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString());
+ Assert.That(retrievedAsset, Is.Null);
+ }
+
+ [Test]
+ public void TestClearCache()
+ {
+ TestHelper.InMethod();
+// log4net.Config.XmlConfigurator.Configure();
+
+ AssetBase asset = AssetHelpers.CreateAsset();
+ asset.ID = TestHelper.ParseTail(0x2).ToString();
+
+ m_cache.Store(asset);
+
+ m_cache.Clear();
+
+ AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString());
+ Assert.That(retrievedAsset, Is.Null);
+ }
+ }
+}
\ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 2a6d362833..04b20d44df 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -449,7 +449,7 @@ namespace OpenSim.Region.CoreModules.World.Land
public bool IsBannedFromLand(UUID avatar)
{
- if (m_scene.Permissions.IsAdministrator(avatar))
+ if (m_scene.Permissions.CanEditParcelProperties(avatar, this, 0))
return false;
if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar))
@@ -463,7 +463,7 @@ namespace OpenSim.Region.CoreModules.World.Land
if (e.AgentID == avatar && e.Flags == AccessList.Ban)
return true;
return false;
- }) != -1 && LandData.OwnerID != avatar)
+ }) != -1)
{
return true;
}
@@ -473,7 +473,7 @@ namespace OpenSim.Region.CoreModules.World.Land
public bool IsRestrictedFromLand(UUID avatar)
{
- if (m_scene.Permissions.IsAdministrator(avatar))
+ if (m_scene.Permissions.CanEditParcelProperties(avatar, this, 0))
return false;
if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar))
@@ -487,7 +487,7 @@ namespace OpenSim.Region.CoreModules.World.Land
if (e.AgentID == avatar && e.Flags == AccessList.Access)
return true;
return false;
- }) == -1 && LandData.OwnerID != avatar)
+ }) == -1)
{
if (!HasGroupAccess(avatar))
{
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 43b37c7d35..2c7843f9ff 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -134,7 +134,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
return;
m_allowGridGods = myConfig.GetBoolean("allow_grid_gods", false);
- m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", false);
+ m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", true);
m_propagatePermissions = myConfig.GetBoolean("propagate_permissions", true);
m_RegionOwnerIsGod = myConfig.GetBoolean("region_owner_is_god", true);
m_RegionManagerIsGod = myConfig.GetBoolean("region_manager_is_god", false);
diff --git a/OpenSim/Region/CoreModules/Avatar/NPC/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
similarity index 97%
rename from OpenSim/Region/CoreModules/Avatar/NPC/INPCModule.cs
rename to OpenSim/Region/Framework/Interfaces/INPCModule.cs
index cd2fe4fc85..21a755f29a 100644
--- a/OpenSim/Region/CoreModules/Avatar/NPC/INPCModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
@@ -28,7 +28,7 @@
using OpenMetaverse;
using OpenSim.Region.Framework.Scenes;
-namespace OpenSim.Region.CoreModules.Avatar.NPC
+namespace OpenSim.Region.Framework.Interfaces
{
public interface INPCModule
{
diff --git a/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs
new file mode 100644
index 0000000000..06cd14b553
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs
@@ -0,0 +1,156 @@
+/*
+ * 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.Generic;
+using System.Reflection;
+using System.Threading;
+using log4net;
+using OpenMetaverse;
+using OpenSim.Framework;
+using OpenSim.Region.Framework.Interfaces;
+
+namespace OpenSim.Region.Framework.Scenes
+{
+ class FetchHolder
+ {
+ public IClientAPI Client { get; private set; }
+ public UUID ItemID { get; private set; }
+
+ public FetchHolder(IClientAPI client, UUID itemID)
+ {
+ Client = client;
+ ItemID = itemID;
+ }
+ }
+
+ ///
+ /// Send FetchInventoryReply information to clients asynchronously on a single thread rather than asynchronously via
+ /// multiple threads.
+ ///
+ ///
+ /// If the main root inventory is right-clicked on a version 1 viewer for a user with a large inventory, a very
+ /// very large number of FetchInventory requests are sent to the simulator. Each is handled on a separate thread
+ /// by the IClientAPI, but the sheer number of requests overwhelms the number of threads available and ends up
+ /// freezing the inbound packet handling.
+ ///
+ /// This class makes the first FetchInventory packet thread process the queue. If new requests come
+ /// in while it is processing, then the subsequent threads just add the requests and leave it to the original
+ /// thread to process them.
+ ///
+ /// This might slow down outbound packets but these are limited by the IClientAPI outbound queues
+ /// anyway.
+ ///
+ /// It might be possible to ignore FetchInventory requests altogether, particularly as they are redundant wrt to
+ /// FetchInventoryDescendents requests, but this would require more investigation.
+ ///
+ public class AsyncInventorySender
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ protected Scene m_scene;
+
+ ///
+ /// Queues fetch requests
+ ///
+ Queue m_fetchHolder = new Queue();
+
+ ///
+ /// Signal whether a queue is currently being processed or not.
+ ///
+ protected volatile bool m_processing;
+
+ public AsyncInventorySender(Scene scene)
+ {
+ m_processing = false;
+ m_scene = scene;
+ }
+
+ ///
+ /// Handle a fetch inventory request from the client
+ ///
+ ///
+ ///
+ ///
+ public void HandleFetchInventory(IClientAPI remoteClient, UUID itemID, UUID ownerID)
+ {
+ lock (m_fetchHolder)
+ {
+// m_log.DebugFormat(
+// "[ASYNC INVENTORY SENDER]: Putting request from {0} for {1} on queue", remoteClient.Name, itemID);
+
+ m_fetchHolder.Enqueue(new FetchHolder(remoteClient, itemID));
+ }
+
+ if (!m_processing)
+ {
+ m_processing = true;
+ ProcessQueue();
+ }
+ }
+
+ ///
+ /// Process the queue of fetches
+ ///
+ protected void ProcessQueue()
+ {
+ FetchHolder fh = null;
+
+ while (true)
+ {
+ lock (m_fetchHolder)
+ {
+// m_log.DebugFormat("[ASYNC INVENTORY SENDER]: {0} items left to process", m_fetchHolder.Count);
+
+ if (m_fetchHolder.Count == 0)
+ {
+ m_processing = false;
+ return;
+ }
+ else
+ {
+ fh = m_fetchHolder.Dequeue();
+ }
+ }
+
+ if (fh.Client.IsLoggingOut)
+ continue;
+
+// m_log.DebugFormat(
+// "[ASYNC INVENTORY SENDER]: Handling request from {0} for {1} on queue", fh.Client.Name, fh.ItemID);
+
+ InventoryItemBase item = new InventoryItemBase(fh.ItemID, fh.Client.AgentId);
+ item = m_scene.InventoryService.GetItem(item);
+
+ if (item != null)
+ fh.Client.SendInventoryItemDetails(item.Owner, item);
+
+ // TODO: Possibly log any failure
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 28c0276a40..dbefb4a0a3 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -51,6 +51,11 @@ namespace OpenSim.Region.Framework.Scenes
///
protected AsyncSceneObjectGroupDeleter m_asyncSceneObjectDeleter;
+ ///
+ /// Allows inventory details to be sent to clients asynchronously
+ ///
+ protected AsyncInventorySender m_asyncInventorySender;
+
///
/// Start all the scripts in the scene which should be started.
///
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index e2d7208ff7..44472b2cb7 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -461,31 +461,6 @@ namespace OpenSim.Region.Framework.Scenes
}
);
}
-
-
- ///
- /// Handle a fetch inventory request from the client
- ///
- ///
- ///
- ///
- public void HandleFetchInventory(IClientAPI remoteClient, UUID itemID, UUID ownerID)
- {
- if (LibraryService != null && LibraryService.LibraryRootFolder != null && ownerID == LibraryService.LibraryRootFolder.Owner)
- {
- //m_log.Debug("request info for library item");
- return;
- }
-
- InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
- item = InventoryService.GetItem(item);
-
- if (item != null)
- {
- remoteClient.SendInventoryItemDetails(ownerID, item);
- }
- // else shouldn't we send an alert message?
- }
///
/// Tell the client about the various child items and folders contained in the requested folder.
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 253adae92d..e02a866c4a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -604,6 +604,8 @@ namespace OpenSim.Region.Framework.Scenes
m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
m_asyncSceneObjectDeleter.Enabled = true;
+ m_asyncInventorySender = new AsyncInventorySender(this);
+
#region Region Settings
// Load region settings
@@ -2866,14 +2868,13 @@ namespace OpenSim.Region.Framework.Scenes
public virtual void SubscribeToClientInventoryEvents(IClientAPI client)
{
-
client.OnLinkInventoryItem += HandleLinkInventoryItem;
client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder;
client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder;
client.OnMoveInventoryFolder += HandleMoveInventoryFolder; // 2; //!!
client.OnFetchInventoryDescendents += HandleFetchInventoryDescendents;
client.OnPurgeInventoryDescendents += HandlePurgeInventoryDescendents; // 2; //!!
- client.OnFetchInventory += HandleFetchInventory;
+ client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
client.OnCopyInventoryItem += CopyInventoryItem;
client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
@@ -2993,13 +2994,12 @@ namespace OpenSim.Region.Framework.Scenes
public virtual void UnSubscribeToClientInventoryEvents(IClientAPI client)
{
-
client.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder;
client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder;
client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!!
client.OnFetchInventoryDescendents -= HandleFetchInventoryDescendents;
client.OnPurgeInventoryDescendents -= HandlePurgeInventoryDescendents; // 2; //!!
- client.OnFetchInventory -= HandleFetchInventory;
+ client.OnFetchInventory -= m_asyncInventorySender.HandleFetchInventory;
client.OnUpdateInventoryItem -= UpdateInventoryItemAsset;
client.OnCopyInventoryItem -= CopyInventoryItem;
client.OnMoveInventoryItem -= MoveInventoryItem;
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index 48d236fc58..3cdd06d52c 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -34,7 +34,6 @@ using Nini.Config;
using OpenMetaverse;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
-using OpenSim.Region.CoreModules.Avatar.NPC;
using OpenSim.Framework;
using Timer=System.Timers.Timer;
using OpenSim.Services.Interfaces;
@@ -47,31 +46,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
// private const bool m_enabled = false;
- private Mutex m_createMutex;
- private Timer m_timer;
-
private Dictionary m_avatars = new Dictionary();
private Dictionary m_appearanceCache = new Dictionary();
- // Timer vars.
- private bool p_inUse = false;
- private readonly object p_lock = new object();
- // Private Temporary Variables.
- private string p_firstname;
- private string p_lastname;
- private Vector3 p_position;
- private Scene p_scene;
- private UUID p_cloneAppearanceFrom;
- private UUID p_returnUuid;
-
public void Initialise(Scene scene, IConfigSource source)
{
- m_createMutex = new Mutex(false);
-
- m_timer = new Timer(500);
- m_timer.Elapsed += m_timer_Elapsed;
- m_timer.Start();
-
scene.RegisterModuleInterface(this);
}
@@ -90,35 +69,53 @@ namespace OpenSim.Region.OptionalModules.World.NPC
return new AvatarAppearance();
}
- public UUID CreateNPC(string firstname, string lastname,Vector3 position, Scene scene, UUID cloneAppearanceFrom)
+ public UUID CreateNPC(string firstname, string lastname, Vector3 position, Scene scene, UUID cloneAppearanceFrom)
{
+ NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position, scene);
+ npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0, int.MaxValue);
+
m_log.DebugFormat(
- "[NPC MODULE]: Queueing request to create NPC {0} {1} at {2} in {3} cloning appearance of {4}",
- firstname, lastname, position, scene.RegionInfo.RegionName, cloneAppearanceFrom);
+ "[NPC MODULE]: Creating NPC {0} {1} {2} at {3} in {4}",
+ firstname, lastname, npcAvatar.AgentId, position, scene.RegionInfo.RegionName);
- // Block.
- m_createMutex.WaitOne();
+ AgentCircuitData acd = new AgentCircuitData();
+ acd.AgentID = npcAvatar.AgentId;
+ acd.firstname = firstname;
+ acd.lastname = lastname;
+ acd.ServiceURLs = new Dictionary();
- // Copy Temp Variables for Timer to pick up.
- lock (p_lock)
+ AvatarAppearance originalAppearance = GetAppearance(cloneAppearanceFrom, scene);
+ AvatarAppearance npcAppearance = new AvatarAppearance(originalAppearance, true);
+ acd.Appearance = npcAppearance;
+
+ scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd);
+ scene.AddNewClient(npcAvatar);
+
+ ScenePresence sp;
+ if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
{
- p_firstname = firstname;
- p_lastname = lastname;
- p_position = position;
- p_scene = scene;
- p_cloneAppearanceFrom = cloneAppearanceFrom;
- p_inUse = true;
- p_returnUuid = UUID.Zero;
+ m_log.DebugFormat(
+ "[NPC MODULE]: Successfully retrieved scene presence for NPC {0} {1}", sp.Name, sp.UUID);
+
+ // Shouldn't call this - temporary.
+ sp.CompleteMovement(npcAvatar);
+
+// sp.SendAppearanceToAllOtherAgents();
+//
+// // Send animations back to the avatar as well
+// sp.Animator.SendAnimPack();
+ }
+ else
+ {
+ m_log.WarnFormat("[NPC MODULE]: Could not find scene presence for NPC {0} {1}", sp.Name, sp.UUID);
}
- while (p_returnUuid == UUID.Zero)
- {
- Thread.Sleep(250);
- }
+ lock (m_avatars)
+ m_avatars.Add(npcAvatar.AgentId, npcAvatar);
- m_createMutex.ReleaseMutex();
+ m_log.DebugFormat("[NPC MODULE]: Created NPC with id {0}", npcAvatar.AgentId);
- return p_returnUuid;
+ return npcAvatar.AgentId;
}
public void Autopilot(UUID agentID, Scene scene, Vector3 pos)
@@ -157,69 +154,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
}
}
- void m_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
- {
- try
- {
- lock (p_lock)
- {
- if (p_inUse)
- {
- p_inUse = false;
-
- NPCAvatar npcAvatar = new NPCAvatar(p_firstname, p_lastname, p_position, p_scene);
- npcAvatar.CircuitCode = (uint) Util.RandomClass.Next(0, int.MaxValue);
-
- m_log.DebugFormat(
- "[NPC MODULE]: Creating NPC {0} {1} {2} at {3} in {4}",
- p_firstname, p_lastname, npcAvatar.AgentId, p_position, p_scene.RegionInfo.RegionName);
-
- AgentCircuitData acd = new AgentCircuitData();
- acd.AgentID = npcAvatar.AgentId;
- acd.firstname = p_firstname;
- acd.lastname = p_lastname;
- acd.ServiceURLs = new Dictionary();
-
- AvatarAppearance originalAppearance = GetAppearance(p_cloneAppearanceFrom, p_scene);
- AvatarAppearance npcAppearance = new AvatarAppearance(originalAppearance, true);
- acd.Appearance = npcAppearance;
-
- p_scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd);
- p_scene.AddNewClient(npcAvatar);
-
- ScenePresence sp;
- if (p_scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
- {
- m_log.DebugFormat(
- "[NPC MODULE]: Successfully retrieved scene presence for NPC {0} {1}", sp.Name, sp.UUID);
-
- // Shouldn't call this - temporary.
- sp.CompleteMovement(npcAvatar);
-
- // sp.SendAppearanceToAllOtherAgents();
- //
- // // Send animations back to the avatar as well
- // sp.Animator.SendAnimPack();
- }
- else
- {
- m_log.WarnFormat("[NPC MODULE]: Could not find scene presence for NPC {0} {1}", sp.Name, sp.UUID);
- }
-
- m_avatars.Add(npcAvatar.AgentId, npcAvatar);
-
- p_returnUuid = npcAvatar.AgentId;
-
- m_log.DebugFormat("[NPC MODULE]: Created NPC with id {0}", p_returnUuid);
- }
- }
- }
- catch (Exception ex)
- {
- m_log.ErrorFormat("[NPC MODULE]: NPC creation failed with exception {0} {1}", ex.Message, ex.StackTrace);
- }
- }
-
public void PostInitialise()
{
}
@@ -238,4 +172,4 @@ namespace OpenSim.Region.OptionalModules.World.NPC
get { return true; }
}
}
-}
+}
\ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
new file mode 100644
index 0000000000..899e721767
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -0,0 +1,71 @@
+/*
+ * 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.Reflection;
+using Nini.Config;
+using NUnit.Framework;
+using OpenMetaverse;
+using OpenSim.Framework;
+using OpenSim.Framework.Communications;
+using OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes;
+using OpenSim.Services.AvatarService;
+using OpenSim.Tests.Common;
+using OpenSim.Tests.Common.Mock;
+
+namespace OpenSim.Region.OptionalModules.World.NPC.Tests
+{
+ [TestFixture]
+ public class NPCModuleTests
+ {
+ [Test]
+ public void TestCreate()
+ {
+ TestHelper.InMethod();
+// log4net.Config.XmlConfigurator.Configure();
+
+ IConfigSource config = new IniConfigSource();
+
+ config.AddConfig("Modules");
+ config.Configs["Modules"].Set("AvatarServices", "LocalAvatarServicesConnector");
+ config.AddConfig("AvatarService");
+ config.Configs["AvatarService"].Set("LocalServiceModule", "OpenSim.Services.AvatarService.dll:AvatarService");
+ config.Configs["AvatarService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
+
+ TestScene scene = SceneSetupHelpers.SetupScene();
+ SceneSetupHelpers.SetupSceneModules(scene, config, new NPCModule(), new LocalAvatarServicesConnector());
+
+ INPCModule npcModule = scene.RequestModuleInterface();
+ UUID npcId = npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), scene, UUID.Zero);
+
+ ScenePresence npc = scene.GetScenePresence(npcId);
+ Assert.That(npc, Is.Not.Null);
+ }
+ }
+}
\ No newline at end of file
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index 99b2d8477a..a5fe45b216 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -291,7 +291,14 @@ namespace OpenSim.Region.Physics.Meshing
{
try
{
- meshOsd = (OSDMap)OSDParser.DeserializeLLSDBinary(data);
+ OSD osd = OSDParser.DeserializeLLSDBinary(data);
+ if (osd is OSDMap)
+ meshOsd = (OSDMap)osd;
+ else
+ {
+ m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap");
+ return null;
+ }
}
catch (Exception e)
{
@@ -302,11 +309,17 @@ namespace OpenSim.Region.Physics.Meshing
if (meshOsd is OSDMap)
{
+ OSDMap physicsParms = null;
OSDMap map = (OSDMap)meshOsd;
- OSDMap physicsParms = (OSDMap)map["physics_shape"]; // old asset format
-
- if (physicsParms.Count == 0)
+ if (map.ContainsKey("physics_shape"))
+ physicsParms = (OSDMap)map["physics_shape"]; // old asset format
+ else if (map.ContainsKey("physics_mesh"))
physicsParms = (OSDMap)map["physics_mesh"]; // new asset format
+ if (physicsParms == null)
+ {
+ m_log.Warn("[Mesh]: no recognized physics mesh found in mesh asset");
+ return null;
+ }
int physOffset = physicsParms["offset"].AsInteger() + (int)start;
int physSize = physicsParms["size"].AsInteger();
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index a0101af2bb..8d9f5f14d6 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -2502,7 +2502,7 @@ namespace OpenSim.Region.Physics.OdePlugin
}
// if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
- if (!forceSimplePrimMeshing)
+ if (!forceSimplePrimMeshing && !pbs.SculptEntry)
{
if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
|| (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
@@ -2592,6 +2592,9 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
+ if (pbs.SculptEntry && meshSculptedPrim)
+ iPropertiesNotSupportedDefault++;
+
if (iPropertiesNotSupportedDefault == 0)
{
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 2b8155fbd0..31222fff54 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -38,7 +38,6 @@ using OpenSim;
using OpenSim.Framework;
using OpenSim.Framework.Console;
-using OpenSim.Region.CoreModules.Avatar.NPC;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.ScriptEngine.Shared;
diff --git a/OpenSim/Tests/Common/Helpers/AssetHelpers.cs b/OpenSim/Tests/Common/Helpers/AssetHelpers.cs
index aa55bcdc69..9b68331038 100644
--- a/OpenSim/Tests/Common/Helpers/AssetHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/AssetHelpers.cs
@@ -36,6 +36,15 @@ namespace OpenSim.Tests.Common
{
public class AssetHelpers
{
+ ///
+ /// Create a notecard asset with a random uuids and dummy text.
+ ///
+ ///
+ public static AssetBase CreateAsset()
+ {
+ return CreateAsset(UUID.Random(), AssetType.Notecard, "hello", UUID.Random());
+ }
+
///
/// Create a notecard asset with a random uuid and dummy text.
///
diff --git a/OpenSim/Tests/Common/TestHelper.cs b/OpenSim/Tests/Common/TestHelper.cs
index 1722e59864..86bd10766b 100644
--- a/OpenSim/Tests/Common/TestHelper.cs
+++ b/OpenSim/Tests/Common/TestHelper.cs
@@ -28,6 +28,7 @@
using System;
using System.Diagnostics;
using NUnit.Framework;
+using OpenMetaverse;
namespace OpenSim.Tests.Common
{
@@ -56,5 +57,15 @@ namespace OpenSim.Tests.Common
Console.WriteLine();
Console.WriteLine("===> In Test Method : {0} <===", stackTrace.GetFrame(1).GetMethod().Name);
}
+
+ ///
+ /// Parse tail section into full UUID.
+ ///
+ ///
+ ///
+ public static UUID ParseTail(int tail)
+ {
+ return new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", tail));
+ }
}
}
diff --git a/OpenSim/Tools/Configger/ConfigurationLoader.cs b/OpenSim/Tools/Configger/ConfigurationLoader.cs
index 8e71b42bca..39146527b8 100644
--- a/OpenSim/Tools/Configger/ConfigurationLoader.cs
+++ b/OpenSim/Tools/Configger/ConfigurationLoader.cs
@@ -239,7 +239,7 @@ namespace OpenSim.Tools.Configger
config.Set("meshing", "Meshmerizer");
config.Set("physical_prim", true);
config.Set("see_into_this_sim_from_neighbor", true);
- config.Set("serverside_object_permissions", false);
+ config.Set("serverside_object_permissions", true);
config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");
config.Set("storage_prim_inventories", true);
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index 98bb355d7a..60d37fbcec 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -78,20 +78,19 @@
; DrawPrimOnMapTile = true
;# {NonPhysicalPrimMax} {} {Maximum size of nonphysical prims?} {} 256
- ;; Maximum size for non-physical prims
+ ;; Maximum size for non-physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonphysicalPrimMax!).
; NonPhysicalPrimMax = 256
;# {PhysicalPrimMax} {} {Maximum size of physical prims?} {} 10
- ;; Maximum size where a prim can be physical
+ ;; Maximum size where a prim can be physical. Affects resizing of existing prims. This can be overriden in the region config file.
; PhysicalPrimMax = 10
- ;; Prevent the creation, import and rez of prims that exceed the
- ;; maximum size.
+ ;; If a viewer attempts to rez a prim larger than the non-physical or physical prim max, clamp the dimensions to the appropriate maximum
+ ;; This can be overriden in the region config file.
; ClampPrimSize = false
;# {AllowScriptCrossing} {} {Allow scripts to cross into this region} {true false} false
- ;; Allow scripts to cross region boundaries. These are recompiled on the
- ;; new region.
+ ;; Allow scripts to keep running when they cross region boundaries, rather than being restarted. Script code is recompiled on the destination region and the state reloaded.
; AllowScriptCrossing = false
;# {TrustBinaries} {AllowScriptCrossing:true} {Accept compiled binary script code? (DANGEROUS!)} {true false} false
@@ -173,7 +172,7 @@
;; permission checks (allowing anybody to copy
;; any item, etc. This may not yet be implemented uniformally.
;; If set to true, then all permissions checks are carried out
- ; serverside_object_permissions = false
+ ; serverside_object_permissions = true
;; This allows users with a UserLevel of 200 or more to assume god
;; powers in the regions in this simulator.
@@ -292,28 +291,31 @@
;; building's lights to possibly not be rendered.
; DisableFacelights = "false"
+
[ClientStack.LindenCaps]
- ;; For the long list of capabilities, see OpenSimDefaults.ini
- ;; Here are the few ones you may want to change. Possible values
- ;; are:
- ;; "" -- empty, capability disabled
- ;; "localhost" -- capability enabled and served by the simulator
- ;; "" -- capability enabled and served by some other server
- ;;
- ; These are enabled by default to localhost. Change if you see fit.
- Cap_GetTexture = "localhost"
- Cap_GetMesh = "localhost"
- ; This is disabled by default. Change if you see fit. Note that
- ; serving this cap from the simulators may lead to poor performace.
- Cap_WebFetchInventoryDescendents = ""
+ ;; For the long list of capabilities, see OpenSimDefaults.ini
+ ;; Here are the few ones you may want to change. Possible values
+ ;; are:
+ ;; "" -- empty, capability disabled
+ ;; "localhost" -- capability enabled and served by the simulator
+ ;; "" -- capability enabled and served by some other server
+ ;;
+ ; These are enabled by default to localhost. Change if you see fit.
+ Cap_GetTexture = "localhost"
+ Cap_GetMesh = "localhost"
+ ; This is disabled by default. Change if you see fit. Note that
+ ; serving this cap from the simulators may lead to poor performace.
+ Cap_WebFetchInventoryDescendents = ""
+
[SimulatorFeatures]
- ; Experimental new information sent in SimulatorFeatures cap for Kokua viewers
- ; meant to override the MapImage and search server url given at login, and varying
- ; on a sim-basis.
- ; Viewers that don't understand it, will ignore it
- ;MapImageServerURI = "http://127.0.0.1:9000/
- ;SearchServerURI = "http://127.0.0.1:9000/
+ ; Experimental new information sent in SimulatorFeatures cap for Kokua viewers
+ ; meant to override the MapImage and search server url given at login, and varying
+ ; on a sim-basis.
+ ; Viewers that don't understand it, will ignore it
+ ;MapImageServerURI = "http://127.0.0.1:9000/
+ ;SearchServerURI = "http://127.0.0.1:9000/
+
[Chat]
;# {whisper_distance} {} {Distance at which a whisper is heard, in meters?} {} 10
@@ -650,6 +652,7 @@
;; If using a remote connector, specify the server URL
; FreeswitchServiceURL = http://my.grid.server:8004/fsapi
+
[Groups]
;# {Enabled} {} {Enable groups?} {true false} false
;; Enables the groups module
@@ -707,11 +710,13 @@
;; Enable media on a prim facilities
; Enabled = true;
+
[PrimLimitsModule]
;# {EnforcePrimLimits} {} {Enforce parcel prim limits} {true false} false
;; Enable parcel prim limits. Off by default to emulate pre-existing behavior.
; EnforcePrimLimits = false
+
[Architecture]
;# {Include-Architecture} {} {Choose one of the following architectures} {config-include/Standalone.ini config-include/StandaloneHypergrid.ini config-include/Grid.ini config-include/GridHypergrid.ini config-include/SimianGrid.ini config-include/HyperSimianGrid.ini} config-include/Standalone.ini
;; Uncomment one of the following includes as required. For instance, to create a standalone OpenSim,
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index fd39fe62e6..5aeadceb43 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -14,10 +14,13 @@
; Place to create a PID file
; PIDFile = "/tmp/my.pid"
+ ; Console commands run at startup
startup_console_commands_file = "startup_commands.txt"
+
+ ; Console commands run on shutdown
shutdown_console_commands_file = "shutdown_commands.txt"
- ; To run a script every few minutes, set the script filename here
+ ; Console commands run every 20 minutes
; timer_Script = "filename"
; ##
@@ -70,12 +73,17 @@
; Use terrain texture for maptiles if true, use shaded green if false
TextureOnMapTile = false
- ; Maximum total size, and maximum size where a prim can be physical
+ ; Maximum size of non physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonphysicalPrimMax!).
NonPhysicalPrimMax = 256
- PhysicalPrimMax = 10 ; (I think this was moved to the Regions.ini!)
+
+ ; Maximum size of physical prims. Affects resizing of existing prims. This can be overriden in the region config file.
+ PhysicalPrimMax = 10
+
+ ; If a viewer attempts to rez a prim larger than the non-physical or physical prim max, clamp the dimensions to the appropriate maximum
+ ; This can be overriden in the region config file.
ClampPrimSize = false
- ; Allow scripts to cross region boundaries. These are recompiled on the new region.
+ ; Allow scripts to keep running when they cross region boundaries, rather than being restarted. Script code is recompiled on the destination region and the state reloaded.
AllowScriptCrossing = false
; Allow compiled script binary code to cross region boundaries.
@@ -94,7 +102,7 @@
; neighbors on each side for a total of 49 regions in view. Warning, unless
; all the regions have the same drawdistance, you will end up with strange
; effects because the agents that get closed may be inconsistent.
- ; DefaultDrawDistance = 255.0
+ DefaultDrawDistance = 255.0
; If you have only one region in an instance, or to avoid the many bugs
; that you can trigger in modules by restarting a region, set this to
@@ -102,7 +110,7 @@
; This is meant to be used on systems where some external system like
; Monit will restart any instance that exits, thereby making the shutdown
; into a restart.
- ;InworldRestartShutsDown = false
+ InworldRestartShutsDown = false
; ##
; ## PRIM STORAGE
@@ -227,7 +235,6 @@
; If enabled, enableFlySlow will change the primary fly state to
; FLYSLOW, and the "always run" state will be the regular fly.
-
enableflyslow = false
; PreJump is an additional animation state, but it probably
@@ -236,7 +243,6 @@
; This is commented so it will come on automatically once it's
; supported.
-
; enableprejump = true
; Simulator Stats URI
@@ -265,6 +271,7 @@
DelayBeforeAppearanceSave = 5
DelayBeforeAppearanceSend = 2
+
[SMTP]
enabled=false
diff --git a/bin/config-include/FlotsamCache.ini.example b/bin/config-include/FlotsamCache.ini.example
index ad38ad15b5..cd39f8c740 100644
--- a/bin/config-include/FlotsamCache.ini.example
+++ b/bin/config-include/FlotsamCache.ini.example
@@ -19,9 +19,12 @@
; 0 to disable
HitRateDisplay = 100
- ; Set to false for disk cache only.
+ ; Set to false for no memory cache
MemoryCacheEnabled = false
+ ; Set to false for no file cache
+ FileCacheEnabled = true
+
; How long {in hours} to keep assets cached in memory, .5 == 30 minutes
; Optimization: for VPS or limited memory system installs set Timeout to .016 (1 minute)
; increases performance without large memory impact
diff --git a/prebuild.xml b/prebuild.xml
index 0e96176883..6362848e94 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -2985,6 +2985,7 @@
+
@@ -3029,6 +3030,7 @@
+
@@ -3052,6 +3054,7 @@
+