Replaced all calling to SendLinkObject to SyncLinkObject.
Added a bunch of debugging message to keep track of Shape updates synchronization.dsg
parent
cb6630aa35
commit
49139f53bb
|
@ -699,6 +699,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
SendDelinkObjectToRelevantSyncConnectors(m_actorID, beforeDelinkGroups, rsm);
|
SendDelinkObjectToRelevantSyncConnectors(m_actorID, beforeDelinkGroups, rsm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Debug(String debugMsg)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("{0}", debugMsg);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion //IRegionSyncModule
|
#endregion //IRegionSyncModule
|
||||||
|
|
||||||
|
@ -2409,15 +2413,29 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
foreach (PropertySyncInfo p in propertiesSyncInfo)
|
foreach (PropertySyncInfo p in propertiesSyncInfo)
|
||||||
{
|
{
|
||||||
pString += p.Property.ToString() + " ";
|
pString += p.Property.ToString() + " ";
|
||||||
|
if (p.Property == SceneObjectPartSyncProperties.Shape)
|
||||||
|
{
|
||||||
|
PrimitiveBaseShape shape = PropertySerializer.DeSerializeShape((String)p.LastUpdateValue);
|
||||||
|
m_log.DebugFormat("Shaped changed on SOP {0}, {1} to ProfileShape {2}", sop.Name, sop.UUID, shape.ProfileShape);
|
||||||
|
//m_log.DebugFormat("SOP {0}, {1} Shape value in incoming message: {1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_log.DebugFormat("{0}: HandleUpdatedPrimProperties, for prim {1},{2} with updated properties -- {3}", LogHeader, sop.Name, sop.UUID, pString);
|
//m_log.DebugFormat("ms {0}: HandleUpdatedPrimProperties, for prim {1},{2} with updated properties -- {3}", DateTime.Now.Millisecond, sop.Name, sop.UUID, pString);
|
||||||
|
|
||||||
|
|
||||||
List<SceneObjectPartSyncProperties> propertiesUpdated = m_primSyncInfoManager.UpdatePrimSyncInfoBySync(sop, propertiesSyncInfo);
|
List<SceneObjectPartSyncProperties> propertiesUpdated = m_primSyncInfoManager.UpdatePrimSyncInfoBySync(sop, propertiesSyncInfo);
|
||||||
|
|
||||||
//SYNC DEBUG
|
//SYNC DEBUG
|
||||||
if (propertiesUpdated.Contains(SceneObjectPartSyncProperties.AggregateScriptEvents))
|
if (propertiesUpdated.Contains(SceneObjectPartSyncProperties.AggregateScriptEvents))
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("AggregateScriptEvents updated: " + sop.AggregateScriptEvents);
|
//m_log.DebugFormat("AggregateScriptEvents updated: " + sop.AggregateScriptEvents);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propertiesUpdated.Contains(SceneObjectPartSyncProperties.Shape))
|
||||||
|
{
|
||||||
|
String hashedShape = Util.Md5Hash((PropertySerializer.SerializeShape(sop)));
|
||||||
|
m_log.DebugFormat("HandleUpdatedPrimProperties -- SOP {0},{1}, Shape, ProfileShape {2}, hashed value in SOP:{3}, in PrinSyncInfoManager: {4}",
|
||||||
|
sop.Name, sop.UUID, sop.Shape.ProfileShape, hashedShape, m_primSyncInfoManager.GetPrimSyncInfo(sop.UUID).PropertiesSyncInfo[SceneObjectPartSyncProperties.Shape].LastUpdateValueHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (propertiesUpdated.Count > 0)
|
if (propertiesUpdated.Count > 0)
|
||||||
|
@ -2449,7 +2467,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
SceneObjectDecoder(encodedSOG, out linkedGroup, out primsSyncInfo);
|
SceneObjectDecoder(encodedSOG, out linkedGroup, out primsSyncInfo);
|
||||||
|
|
||||||
//TEMP DEBUG
|
//TEMP DEBUG
|
||||||
m_log.DebugFormat("{0}: received linkedGroup: {1}", LogHeader, linkedGroup.DebugObjectUpdateResult());
|
m_log.DebugFormat(" received linkedGroup: {1}", linkedGroup.DebugObjectUpdateResult());
|
||||||
//m_log.DebugFormat(linkedGroup.DebugObjectUpdateResult());
|
//m_log.DebugFormat(linkedGroup.DebugObjectUpdateResult());
|
||||||
|
|
||||||
if (linkedGroup == null)
|
if (linkedGroup == null)
|
||||||
|
@ -3530,6 +3548,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
}
|
}
|
||||||
* */
|
* */
|
||||||
|
|
||||||
|
if(updatedProperties.Contains(SceneObjectPartSyncProperties.Shape))
|
||||||
|
{
|
||||||
|
string hashedShape = Util.Md5Hash((PropertySerializer.SerializeShape(part)));
|
||||||
|
m_log.DebugFormat("ProcessAndEnqueuePrimUpdatesByLocal: Shape of SOP {0}, {1} updated, ProfileShape {2}, hashed value in SOP: {3}, in PrimSyncInfoManager: {4}",
|
||||||
|
part.Name, part.UUID, part.Shape.ProfileShape, hashedShape, m_primSyncInfoManager.GetPrimSyncInfo(part.UUID).PropertiesSyncInfo[SceneObjectPartSyncProperties.Shape].LastUpdateValueHash);
|
||||||
|
}
|
||||||
|
|
||||||
//Enqueue the prim with the set of updated properties, excluding the group properties
|
//Enqueue the prim with the set of updated properties, excluding the group properties
|
||||||
if (propertiesWithSyncInfoUpdated.Count > 0)
|
if (propertiesWithSyncInfoUpdated.Count > 0)
|
||||||
{
|
{
|
||||||
|
@ -3653,6 +3678,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
UUID primUUID = updatedPrimProperties.Key;
|
UUID primUUID = updatedPrimProperties.Key;
|
||||||
HashSet<SceneObjectPartSyncProperties> updatedProperties = updatedPrimProperties.Value;
|
HashSet<SceneObjectPartSyncProperties> updatedProperties = updatedPrimProperties.Value;
|
||||||
|
|
||||||
|
//Sync the SOP data and cached property values in PrimSyncInfoManager again
|
||||||
|
//HashSet<SceneObjectPartSyncProperties> propertiesWithSyncInfoUpdated = m_primSyncInfoManager.UpdatePrimSyncInfoByLocal(part, updatedProperties);
|
||||||
|
|
||||||
SendPrimPropertyUpdates(primUUID, updatedProperties);
|
SendPrimPropertyUpdates(primUUID, updatedProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3677,7 +3705,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
|
||||||
if (syncData.Count > 0)
|
if (syncData.Count > 0)
|
||||||
{
|
{
|
||||||
//SYNC DEBUG
|
//DSG DEBUG
|
||||||
|
|
||||||
string pString = "";
|
string pString = "";
|
||||||
foreach (SceneObjectPartSyncProperties property in updatedProperties)
|
foreach (SceneObjectPartSyncProperties property in updatedProperties)
|
||||||
|
@ -3686,13 +3714,21 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
}
|
}
|
||||||
m_log.DebugFormat("{0}: SendPrimPropertyUpdates for {1}, {2}, with updated properties -- {3}", LogHeader, sop.Name, sop.UUID, pString);
|
m_log.DebugFormat("{0}: SendPrimPropertyUpdates for {1}, {2}, with updated properties -- {3}", LogHeader, sop.Name, sop.UUID, pString);
|
||||||
|
|
||||||
//SYNC DEBUG
|
//DSG DEBUG
|
||||||
|
|
||||||
if (updatedProperties.Contains(SceneObjectPartSyncProperties.AggregateScriptEvents))
|
if (updatedProperties.Contains(SceneObjectPartSyncProperties.AggregateScriptEvents))
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("SendPrimPropertyUpdates -- AggregateScriptEvents: " + sop.AggregateScriptEvents);
|
// m_log.DebugFormat("SendPrimPropertyUpdates -- AggregateScriptEvents: " + sop.AggregateScriptEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (updatedProperties.Contains(SceneObjectPartSyncProperties.Shape))
|
||||||
|
{
|
||||||
|
String hashedShape = Util.Md5Hash((PropertySerializer.SerializeShape(sop)));
|
||||||
|
m_log.DebugFormat("SendPrimPropertyUpdates -- SOP {0},{1}, Shape updated: ProfileShape {2}, hashed value in SOP:{3}, in PrinSyncInfoManager: {4}",
|
||||||
|
sop.Name, sop.UUID, sop.Shape.ProfileShape,
|
||||||
|
hashedShape, m_primSyncInfoManager.GetPrimSyncInfo(sop.UUID).PropertiesSyncInfo[SceneObjectPartSyncProperties.Shape].LastUpdateValueHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedPrimProperties, OSDParser.SerializeJsonString(syncData));
|
SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedPrimProperties, OSDParser.SerializeJsonString(syncData));
|
||||||
SendPrimUpdateToRelevantSyncConnectors(primUUID, syncMsg);
|
SendPrimUpdateToRelevantSyncConnectors(primUUID, syncMsg);
|
||||||
|
@ -3783,6 +3819,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//DSG DEBUG
|
||||||
|
m_log.DebugFormat("calling AddNewSceneObjectByDecoding for SOG {1}, {2}", group.Name, group.UUID);
|
||||||
|
|
||||||
//Add the list of PrimSyncInfo to PrimSyncInfoManager's record.
|
//Add the list of PrimSyncInfo to PrimSyncInfoManager's record.
|
||||||
m_primSyncInfoManager.InsertMultiPrimSyncInfo(primsSyncInfo);
|
m_primSyncInfoManager.InsertMultiPrimSyncInfo(primsSyncInfo);
|
||||||
|
|
||||||
|
@ -4052,6 +4091,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
}
|
}
|
||||||
|
|
||||||
private string m_lastUpdateValueHash = String.Empty;
|
private string m_lastUpdateValueHash = String.Empty;
|
||||||
|
public String LastUpdateValueHash
|
||||||
|
{
|
||||||
|
get {return m_lastUpdateValueHash;}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Record the time the last sync message about this property is received.
|
/// Record the time the last sync message about this property is received.
|
||||||
|
@ -5152,6 +5195,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
if (lastUpdateTS > m_propertiesSyncInfo[property].LastUpdateTimeStamp)
|
if (lastUpdateTS > m_propertiesSyncInfo[property].LastUpdateTimeStamp)
|
||||||
{
|
{
|
||||||
UpdatePropertySyncInfoByLocal(property, lastUpdateTS, syncID, (Object)primShapeString, primShapeStringHash);
|
UpdatePropertySyncInfoByLocal(property, lastUpdateTS, syncID, (Object)primShapeString, primShapeStringHash);
|
||||||
|
|
||||||
|
//DSG DEBUG
|
||||||
|
DebugLog.DebugFormat("CompareHashedValue_UpdateByLocal - Shape of {0}, {1}, updated: hashed value {2}", part.Name, part.UUID, m_propertiesSyncInfo[property].LastUpdateValueHash);
|
||||||
|
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
else if (lastUpdateTS < m_propertiesSyncInfo[property].LastUpdateTimeStamp)
|
else if (lastUpdateTS < m_propertiesSyncInfo[property].LastUpdateTimeStamp)
|
||||||
|
@ -6513,7 +6560,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
case SceneObjectPartSyncProperties.Shape:
|
case SceneObjectPartSyncProperties.Shape:
|
||||||
PrimitiveBaseShape shapeVal = PropertySerializer.DeSerializeShape((string)pSyncInfo.LastUpdateValue);
|
PrimitiveBaseShape shapeVal = PropertySerializer.DeSerializeShape((string)pSyncInfo.LastUpdateValue);
|
||||||
if (shapeVal != null)
|
if (shapeVal != null)
|
||||||
|
{
|
||||||
part.Shape = shapeVal;
|
part.Shape = shapeVal;
|
||||||
|
String hashedShape = Util.Md5Hash((PropertySerializer.SerializeShape(part)));
|
||||||
|
DebugLog.DebugFormat("prim type of SOP {0}, {1}, changed, hashed shape = {2} in SOP, = {3} in PrimSyncInfoManager",
|
||||||
|
part.Name, part.UUID, hashedShape, pSyncInfo.LastUpdateValueHash);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SceneObjectPartSyncProperties.TaskInventory:
|
case SceneObjectPartSyncProperties.TaskInventory:
|
||||||
TaskInventoryDictionary taskVal = PropertySerializer.DeSerializeTaskInventory((string)pSyncInfo.LastUpdateValue);
|
TaskInventoryDictionary taskVal = PropertySerializer.DeSerializeTaskInventory((string)pSyncInfo.LastUpdateValue);
|
||||||
|
@ -6527,7 +6579,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
case SceneObjectPartSyncProperties.AggregateScriptEvents:
|
case SceneObjectPartSyncProperties.AggregateScriptEvents:
|
||||||
part.AggregateScriptEvents = (scriptEvents)pSyncInfo.LastUpdateValue;
|
part.AggregateScriptEvents = (scriptEvents)pSyncInfo.LastUpdateValue;
|
||||||
|
|
||||||
DebugLog.DebugFormat("set {0} value to be {1}", property.ToString(), part.AggregateScriptEvents);
|
//DebugLog.DebugFormat("set {0} value to be {1}", property.ToString(), part.AggregateScriptEvents);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case SceneObjectPartSyncProperties.AllowedDrop:
|
case SceneObjectPartSyncProperties.AllowedDrop:
|
||||||
|
|
|
@ -101,6 +101,8 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
//void QueuePresenceForTerseUpdate(ScenePresence presence)
|
//void QueuePresenceForTerseUpdate(ScenePresence presence)
|
||||||
//void SendAvatarUpdates();
|
//void SendAvatarUpdates();
|
||||||
|
|
||||||
|
//Debug purpose, mainly for LSL scripts
|
||||||
|
void Debug(String debugMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -792,7 +792,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
public void LinkObjectBySync(SceneObjectGroup linkedGroup, UUID rootID, List<UUID> childrenIDs)
|
public void LinkObjectBySync(SceneObjectGroup linkedGroup, UUID rootID, List<UUID> childrenIDs)
|
||||||
{
|
{
|
||||||
m_log.Debug("Start to LinkObjectBySync");
|
m_log.Debug("Start to LinkObjectBySync");
|
||||||
DebugSceneObjectGroups();
|
//DebugSceneObjectGroups();
|
||||||
|
|
||||||
List<SceneObjectPart> children = new List<SceneObjectPart>();
|
List<SceneObjectPart> children = new List<SceneObjectPart>();
|
||||||
SceneObjectPart root = GetSceneObjectPart(rootID);
|
SceneObjectPart root = GetSceneObjectPart(rootID);
|
||||||
|
@ -837,7 +837,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
//SceneObjectGroup localGroup = root.ParentGroup;
|
//SceneObjectGroup localGroup = root.ParentGroup;
|
||||||
//localGroup.UpdateObjectGroupBySync(linkedGroup);
|
//localGroup.UpdateObjectGroupBySync(linkedGroup);
|
||||||
|
|
||||||
//debug
|
//DSG DEBUG
|
||||||
|
|
||||||
m_log.Debug("after SceneGraph.LinkObjectsBySync, the newly linked group is \n" + root.ParentGroup.DebugObjectUpdateResult());
|
m_log.Debug("after SceneGraph.LinkObjectsBySync, the newly linked group is \n" + root.ParentGroup.DebugObjectUpdateResult());
|
||||||
m_log.Debug("parts before linking now have properties: ");
|
m_log.Debug("parts before linking now have properties: ");
|
||||||
|
|
|
@ -42,6 +42,7 @@ using OpenSim.Region.Framework.Interfaces;
|
||||||
using OpenSim.Region.Framework.Scenes.Scripting;
|
using OpenSim.Region.Framework.Scenes.Scripting;
|
||||||
using OpenSim.Region.Framework.Scenes.Serialization;
|
using OpenSim.Region.Framework.Scenes.Serialization;
|
||||||
using OpenSim.Region.Physics.Manager;
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace OpenSim.Region.Framework.Scenes
|
namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
|
@ -5488,7 +5489,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
//{
|
//{
|
||||||
// debugMsg += ", Bucket " + pair.Key + ": TimeStamp - " + pair.Value.LastUpdateTimeStamp + ", ActorID - " + pair.Value.LastUpdateActorID;
|
// debugMsg += ", Bucket " + pair.Key + ": TimeStamp - " + pair.Value.LastUpdateTimeStamp + ", ActorID - " + pair.Value.LastUpdateActorID;
|
||||||
//}
|
//}
|
||||||
debugMsg += ", AggregateScriptEvents = " + AggregateScriptEvents.ToString()+", OffsetPosition: "+OffsetPosition;
|
debugMsg += ", AggregateScriptEvents = " + AggregateScriptEvents.ToString()+", OffsetPosition: "+OffsetPosition;
|
||||||
|
String hashedShape = Util.Md5Hash(SerializeShape());
|
||||||
|
debugMsg += ", hashed Shape = " + hashedShape;
|
||||||
return debugMsg;
|
return debugMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6155,6 +6158,21 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
//Per property sync functions
|
//Per property sync functions
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//For debugging, same implemenation with PropertySerializer.SerializeShape
|
||||||
|
private string SerializeShape()
|
||||||
|
{
|
||||||
|
string serializedShape;
|
||||||
|
using (StringWriter sw = new StringWriter())
|
||||||
|
{
|
||||||
|
using (XmlTextWriter writer = new XmlTextWriter(sw))
|
||||||
|
{
|
||||||
|
SceneObjectSerializer.WriteShape(writer, Shape, new Dictionary<string, object>());
|
||||||
|
}
|
||||||
|
serializedShape = sw.ToString();
|
||||||
|
}
|
||||||
|
return serializedShape;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//end of DSG SYNC
|
//end of DSG SYNC
|
||||||
|
|
|
@ -3622,9 +3622,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
{
|
{
|
||||||
//Tell other actors to link the SceneObjectParts together as a new group.
|
//Tell other actors to link the SceneObjectParts together as a new group.
|
||||||
//parentGroup.SyncInfoUpdate();
|
//parentGroup.SyncInfoUpdate();
|
||||||
World.RegionSyncModule.SendLinkObject(parentPrim, parentPrim.RootPart, children);
|
//World.RegionSyncModule.SendLinkObject(parentPrim, parentPrim.RootPart, children);
|
||||||
|
World.RegionSyncModule.SyncLinkObject(parentPrim, parentPrim.RootPart, children);
|
||||||
}
|
}
|
||||||
m_host.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.None}); //SendLinkObject above will synchronize the link operation, no need to taint updates here
|
m_host.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.None }); //SyncLinkObject above will synchronize the link operation, no need to taint updates here
|
||||||
//end of DSG SYNC
|
//end of DSG SYNC
|
||||||
|
|
||||||
if (client != null)
|
if (client != null)
|
||||||
|
@ -3724,7 +3725,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
//DSG SYNC
|
//DSG SYNC
|
||||||
if (World.RegionSyncModule != null)
|
if (World.RegionSyncModule != null)
|
||||||
{
|
{
|
||||||
World.RegionSyncModule.SendLinkObject(newRoot.ParentGroup, newRoot, new List<SceneObjectPart>(newRoot.ParentGroup.Parts));
|
//World.RegionSyncModule.SendLinkObject(newRoot.ParentGroup, newRoot, new List<SceneObjectPart>(newRoot.ParentGroup.Parts));
|
||||||
|
World.RegionSyncModule.SyncLinkObject(newRoot.ParentGroup, newRoot, new List<SceneObjectPart>(newRoot.ParentGroup.Parts));
|
||||||
}
|
}
|
||||||
newRoot.ParentGroup.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.None});
|
newRoot.ParentGroup.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.None});
|
||||||
//end of DSG SYNC
|
//end of DSG SYNC
|
||||||
|
@ -7090,6 +7092,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
|
|
||||||
code = (int)rules.GetLSLIntegerItem(idx++);
|
code = (int)rules.GetLSLIntegerItem(idx++);
|
||||||
|
|
||||||
|
//debug
|
||||||
|
part.ParentGroup.Scene.RegionSyncModule.Debug("LSL_Api: Prim " + part.Name + "," + part.UUID + ", changing shape to " + code);
|
||||||
|
|
||||||
remain = rules.Length - idx;
|
remain = rules.Length - idx;
|
||||||
float hollow;
|
float hollow;
|
||||||
LSL_Vector twist;
|
LSL_Vector twist;
|
||||||
|
|
Loading…
Reference in New Issue