try to reduce the amount of assets created editing materials

LSLKeyTest
UbitUmarov 2016-09-04 07:25:55 +01:00
parent 6526de04cb
commit b5e7816b77
1 changed files with 167 additions and 23 deletions

View File

@ -63,11 +63,16 @@ namespace OpenSim.Region.OptionalModules.Materials
public Type ReplaceableInterface { get { return null; } } public Type ReplaceableInterface { get { return null; } }
IImprovedAssetCache m_cache;
private Scene m_scene = null; private Scene m_scene = null;
private bool m_enabled = false; private bool m_enabled = false;
private int m_maxMaterialsPerTransaction = 50; private int m_maxMaterialsPerTransaction = 50;
public Dictionary<UUID, OSDMap> m_regionMaterials = new Dictionary<UUID, OSDMap>(); public Dictionary<UUID, OSDMap> m_Materials = new Dictionary<UUID, OSDMap>();
public Dictionary<UUID, int> m_MaterialsRefCount = new Dictionary<UUID, int>();
private Dictionary<ulong, AssetBase> m_changes = new Dictionary<ulong, AssetBase>();
private Dictionary<ulong, double> m_changesTime = new Dictionary<ulong, double>();
public void Initialise(IConfigSource source) public void Initialise(IConfigSource source)
{ {
@ -98,6 +103,56 @@ namespace OpenSim.Region.OptionalModules.Materials
m_scene = scene; m_scene = scene;
m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene; m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
m_scene.EventManager.OnBackup += EventManager_OnBackup;
}
private void EventManager_OnBackup(ISimulationDataService datastore, bool forcedBackup)
{
List<AssetBase> toStore;
List<ulong> hashlist;
lock (m_Materials)
{
if(m_changes.Count == 0)
return;
if(forcedBackup)
{
toStore = new List<AssetBase>(m_changes.Values);
m_changes.Clear();
m_changesTime.Clear();
}
else
{
toStore = new List<AssetBase>();
hashlist = new List<ulong>();
double storetime = Util.GetTimeStampMS() - 60000;
foreach(KeyValuePair<ulong,double> kvp in m_changesTime)
{
if(kvp.Value < storetime)
{
toStore.Add(m_changes[kvp.Key]);
hashlist.Add(kvp.Key);
}
}
foreach(ulong u in hashlist)
{
m_changesTime.Remove(u);
m_changes.Remove(u);
}
}
if(toStore.Count > 0)
Util.FireAndForget(delegate
{
foreach(AssetBase a in toStore)
{
a.Local = false;
m_scene.AssetService.Store(a);
}
});
}
} }
private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj) private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
@ -145,12 +200,14 @@ namespace OpenSim.Region.OptionalModules.Materials
m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps; m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene; m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
m_scene.EventManager.OnBackup -= EventManager_OnBackup;
} }
public void RegionLoaded(Scene scene) public void RegionLoaded(Scene scene)
{ {
if (!m_enabled) return; if (!m_enabled) return;
m_cache = scene.RequestModuleInterface<IImprovedAssetCache>();
ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>(); ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>();
if (featuresModule != null) if (featuresModule != null)
featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest; featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
@ -203,8 +260,17 @@ namespace OpenSim.Region.OptionalModules.Materials
{ {
try try
{ {
lock (m_regionMaterials) lock (m_Materials)
m_regionMaterials[matMap["ID"].AsUUID()] = (OSDMap)matMap["Material"]; {
UUID id = matMap["ID"].AsUUID();
if(m_Materials.ContainsKey(id))
m_MaterialsRefCount[id]++;
else
{
m_Materials[id] = (OSDMap)matMap["Material"];
m_MaterialsRefCount[id] = 1;
}
}
} }
catch (Exception e) catch (Exception e)
{ {
@ -252,16 +318,15 @@ namespace OpenSim.Region.OptionalModules.Materials
if (id == UUID.Zero) if (id == UUID.Zero)
return; return;
lock (m_regionMaterials) lock (m_Materials)
{ {
if (m_regionMaterials.ContainsKey(id)) if (m_Materials.ContainsKey(id))
{
m_MaterialsRefCount[id]++;
return; return;
}
// get all asset so it gets into cache
AssetBase matAsset = m_scene.AssetService.Get(id.ToString()); AssetBase matAsset = m_scene.AssetService.Get(id.ToString());
// byte[] data = m_scene.AssetService.GetData(id.ToString());
if (matAsset == null || matAsset.Data == null || matAsset.Data.Length == 0 ) if (matAsset == null || matAsset.Data == null || matAsset.Data.Length == 0 )
{ {
m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id); m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id);
@ -280,7 +345,8 @@ namespace OpenSim.Region.OptionalModules.Materials
return; return;
} }
m_regionMaterials[id] = mat; m_Materials[id] = mat;
m_MaterialsRefCount[id] = 1;
} }
} }
@ -309,13 +375,13 @@ namespace OpenSim.Region.OptionalModules.Materials
{ {
UUID id = new UUID(elem.AsBinary(), 0); UUID id = new UUID(elem.AsBinary(), 0);
lock (m_regionMaterials) lock (m_Materials)
{ {
if (m_regionMaterials.ContainsKey(id)) if (m_Materials.ContainsKey(id))
{ {
OSDMap matMap = new OSDMap(); OSDMap matMap = new OSDMap();
matMap["ID"] = OSD.FromBinary(id.GetBytes()); matMap["ID"] = OSD.FromBinary(id.GetBytes());
matMap["Material"] = m_regionMaterials[id]; matMap["Material"] = m_Materials[id];
respArr.Add(matMap); respArr.Add(matMap);
} }
else else
@ -362,6 +428,7 @@ namespace OpenSim.Region.OptionalModules.Materials
OSDArray respArr = new OSDArray(); OSDArray respArr = new OSDArray();
HashSet<SceneObjectPart> parts = new HashSet<SceneObjectPart>();
if (req.ContainsKey("Zipped")) if (req.ContainsKey("Zipped"))
{ {
OSD osd = null; OSD osd = null;
@ -435,15 +502,16 @@ namespace OpenSim.Region.OptionalModules.Materials
} }
else else
{ {
id = StoreMaterialAsAsset(agentID, mat, sop); id = getNewID(mat);
} }
int face = -1; int face = -1;
UUID oldid = UUID.Zero;
if (matsMap.ContainsKey("Face")) if (matsMap.ContainsKey("Face"))
{ {
face = matsMap["Face"].AsInteger(); face = matsMap["Face"].AsInteger();
Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face); Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face);
oldid = faceEntry.MaterialID;
faceEntry.MaterialID = id; faceEntry.MaterialID = id;
} }
else else
@ -451,19 +519,58 @@ namespace OpenSim.Region.OptionalModules.Materials
if (te.DefaultTexture == null) if (te.DefaultTexture == null)
m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID); m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID);
else else
{
oldid = te.DefaultTexture.MaterialID;
te.DefaultTexture.MaterialID = id; te.DefaultTexture.MaterialID = id;
} }
}
//m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id); //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
// We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
sop.Shape.TextureEntry = te.GetBytes(); sop.Shape.TextureEntry = te.GetBytes();
if (sop.ParentGroup != null) lock(m_Materials)
{
if(oldid != UUID.Zero)
{
m_MaterialsRefCount[oldid]--;
if(m_MaterialsRefCount[oldid] <= 0)
{
m_Materials.Remove(oldid);
m_MaterialsRefCount.Remove(oldid);
m_cache.Expire(oldid.ToString());
}
}
if(id != UUID.Zero)
{
AssetBase asset = CacheMaterialAsAsset(id, agentID, mat, sop);
if(asset != null)
{
ulong materialHash = (ulong)primLocalID << 32;
if(face < 0)
materialHash += 0xffffffff;
else
materialHash +=(ulong)face;
m_changes[materialHash] = asset;
m_changesTime[materialHash] = Util.GetTimeStampMS();
}
}
}
if(!parts.Contains(sop))
parts.Add(sop);
}
foreach(SceneObjectPart sop in parts)
{
if (sop.ParentGroup != null && !sop.ParentGroup.IsDeleted)
{ {
sop.TriggerScriptChangedEvent(Changed.TEXTURE); sop.TriggerScriptChangedEvent(Changed.TEXTURE);
sop.ParentGroup.HasGroupChanged = true;
sop.ScheduleFullUpdate(); sop.ScheduleFullUpdate();
sop.ParentGroup.HasGroupChanged = true;
} }
} }
} }
@ -491,6 +598,40 @@ namespace OpenSim.Region.OptionalModules.Materials
return response; return response;
} }
private UUID getNewID(OSDMap mat)
{
// ugly and done twice but keep compatibility for now
Byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
using (var md5 = MD5.Create())
return new UUID(md5.ComputeHash(data), 0);
}
private AssetBase CacheMaterialAsAsset(UUID id, UUID agentID, OSDMap mat, SceneObjectPart sop)
{
AssetBase asset = null;
lock (m_Materials)
{
if (!m_Materials.ContainsKey(id))
{
m_Materials[id] = mat;
m_MaterialsRefCount[id] = 1;
byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
// This asset might exist already, but it's ok to try to store it again
string name = "Material " + ChooseMaterialName(mat, sop);
name = name.Substring(0, Math.Min(64, name.Length)).Trim();
asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString());
asset.Data = data;
asset.Local = true;
m_cache.Cache(asset);
}
else
m_MaterialsRefCount[id]++;
}
return asset;
}
private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop) private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop)
{ {
UUID id; UUID id;
@ -500,11 +641,12 @@ namespace OpenSim.Region.OptionalModules.Materials
using (var md5 = MD5.Create()) using (var md5 = MD5.Create())
id = new UUID(md5.ComputeHash(data), 0); id = new UUID(md5.ComputeHash(data), 0);
lock (m_regionMaterials) lock (m_Materials)
{ {
if (!m_regionMaterials.ContainsKey(id)) if (!m_Materials.ContainsKey(id))
{ {
m_regionMaterials[id] = mat; m_Materials[id] = mat;
m_MaterialsRefCount[id] = 1;
// This asset might exist already, but it's ok to try to store it again // This asset might exist already, but it's ok to try to store it again
string name = "Material " + ChooseMaterialName(mat, sop); string name = "Material " + ChooseMaterialName(mat, sop);
@ -513,6 +655,8 @@ namespace OpenSim.Region.OptionalModules.Materials
asset.Data = data; asset.Data = data;
m_scene.AssetService.Store(asset); m_scene.AssetService.Store(asset);
} }
else
m_MaterialsRefCount[id]++;
} }
return id; return id;
} }
@ -554,9 +698,9 @@ namespace OpenSim.Region.OptionalModules.Materials
int matsCount = 0; int matsCount = 0;
OSDArray allOsd = new OSDArray(); OSDArray allOsd = new OSDArray();
lock (m_regionMaterials) lock (m_Materials)
{ {
foreach (KeyValuePair<UUID, OSDMap> kvp in m_regionMaterials) foreach (KeyValuePair<UUID, OSDMap> kvp in m_Materials)
{ {
OSDMap matMap = new OSDMap(); OSDMap matMap = new OSDMap();