-
Notifications
You must be signed in to change notification settings - Fork 955
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix a deadlock in binary channel on cleanup, reduce contention due to locks on high server load #2714
Fix a deadlock in binary channel on cleanup, reduce contention due to locks on high server load #2714
Changes from all commits
d588ece
1a7d9b8
5dc7c1e
25d535b
953d409
6192b52
ee88424
a1ce315
d96001b
e8b188b
5181668
b1d994e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -102,10 +102,6 @@ protected CustomNodeManager2( | |
} | ||
} | ||
|
||
// create the table of monitored items. | ||
// these are items created by clients when they subscribe to data or events. | ||
m_monitoredItems = new Dictionary<uint, IDataChangeMonitoredItem>(); | ||
|
||
// create the table of monitored nodes. | ||
// these are created by the node manager whenever a client subscribe to an attribute of the node. | ||
m_monitoredNodes = new Dictionary<NodeId, MonitoredNode2>(); | ||
|
@@ -237,14 +233,6 @@ protected List<NodeState> RootNotifiers | |
get { return m_rootNotifiers; } | ||
} | ||
|
||
/// <summary> | ||
/// Gets the table of monitored items. | ||
/// </summary> | ||
protected Dictionary<uint, IDataChangeMonitoredItem> MonitoredItems | ||
{ | ||
get { return m_monitoredItems; } | ||
} | ||
|
||
/// <summary> | ||
/// Gets the table of nodes being monitored. | ||
/// </summary> | ||
|
@@ -929,7 +917,7 @@ public virtual void DeleteAddressSpace() | |
/// </remarks> | ||
public virtual object GetManagerHandle(NodeId nodeId) | ||
{ | ||
lock (Lock) | ||
lock (m_lock) | ||
{ | ||
return GetManagerHandle(m_systemContext, nodeId, null); | ||
} | ||
|
@@ -945,20 +933,17 @@ protected virtual NodeHandle GetManagerHandle(ServerSystemContext context, NodeI | |
return null; | ||
} | ||
|
||
if (m_predefinedNodes != null) | ||
{ | ||
NodeState node = null; | ||
NodeState node = null; | ||
|
||
if (m_predefinedNodes.TryGetValue(nodeId, out node)) | ||
{ | ||
NodeHandle handle = new NodeHandle(); | ||
if (m_predefinedNodes?.TryGetValue(nodeId, out node) == true) | ||
romanett marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
NodeHandle handle = new NodeHandle(); | ||
|
||
handle.NodeId = nodeId; | ||
handle.Node = node; | ||
handle.Validated = true; | ||
handle.NodeId = nodeId; | ||
handle.Node = node; | ||
handle.Validated = true; | ||
|
||
return handle; | ||
} | ||
return handle; | ||
} | ||
|
||
return null; | ||
|
@@ -3706,7 +3691,6 @@ protected virtual ServiceResult CreateMonitoredItem( | |
monitoredItem = datachangeItem; | ||
|
||
// save the monitored item. | ||
m_monitoredItems.Add(monitoredItemId, datachangeItem); | ||
monitoredNode.Add(datachangeItem); | ||
|
||
// report change. | ||
|
@@ -3809,7 +3793,7 @@ public ServiceResult ValidateEventRolePermissions(IEventMonitoredItem monitoredI | |
eventTypeId = baseEventState.EventType?.Value; | ||
sourceNodeId = baseEventState.SourceNode?.Value; | ||
} | ||
|
||
OperationContext operationContext = new OperationContext(monitoredItem); | ||
|
||
// validate the event type id permissions as specified | ||
|
@@ -4259,9 +4243,6 @@ protected virtual ServiceResult DeleteMonitoredItem( | |
} | ||
} | ||
|
||
// remove the monitored item. | ||
m_monitoredItems.Remove(monitoredItem.Id); | ||
|
||
// report change. | ||
OnMonitoredItemDeleted(context, handle, datachangeItem); | ||
|
||
|
@@ -4777,7 +4758,6 @@ protected NodeState AddNodeToComponentCache(ISystemContext context, NodeHandle h | |
private ServerSystemContext m_systemContext; | ||
private string[] m_namespaceUris; | ||
private ushort[] m_namespaceIndexes; | ||
private Dictionary<uint, IDataChangeMonitoredItem> m_monitoredItems; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have to admit I do not fully understand this change. It seems the m_moniteredItems was not used at all, is that correct? Do we know that people who have extended/derived from CustomNodeManager2 did not use it? I'm also wondering: the method CreateMonitoredItems is implemented in several node managers, with always slightly different implementations. Is this by intention? (CustomNodeManager2, CoreNodeManager and SampleNodeManager) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the idea is to not enforce specific implementations and how the monitored items handles are implemented in a node manager. |
||
private Dictionary<NodeId, MonitoredNode2> m_monitoredNodes; | ||
private Dictionary<NodeId, CacheEntry> m_componentCache; | ||
private NodeIdDictionary<NodeState> m_predefinedNodes; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not very deep into this, but there are about 10 places where a call to GetManagerHandle is protected by lock(Lock), one is protected by m_lock, and one (ore two?) are not protected by any lock. Which attribute is it we want to protect by the lock?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in this case the read access to the NodeIdDictionary is protected. In a next improvement we could change the underlying dictionary to Concurrentdictionary, then the number of locks which cause contention can be greatly reduced. GetManagerHandle is the first candidate to have the lock removed. We tested without the lock but it could be unsafe if the node dictionary is modified. Lock and m_lock access the same lock here.