private BrowseResultCollection BrowseBlock(Session session, BrowseDescriptionCollection nodesToBrowse)
{
try
{
// Utils.Trace("Browsing {0} Nodes", nodesToBrowse.Count);
ViewDescription view = new ViewDescription();
Dictionary<int,BrowseResult> combinedResults = new Dictionary<int, BrowseResult>();
// initialize the table of indexes used to correlate results.
BrowseDescriptionCollection browseOperations = nodesToBrowse;
List<int> browseIndexes = new List<int>();
for (int ii = 0; ii < nodesToBrowse.Count; ii++)
{
browseIndexes.Add(ii);
}
BrowseDescriptionCollection unprocessedOperations = new BrowseDescriptionCollection();
List<int> unprocessedBrowseIndexes = new List<int>();
while (browseOperations.Count > 0)
{
// start the browse operation.
BrowseResultCollection results = null;
DiagnosticInfoCollection diagnosticInfos = null;
session.Browse(
null,
view,
0,
browseOperations,
out results,
out diagnosticInfos);
ClientBase.ValidateResponse(results, browseOperations);
ClientBase.ValidateDiagnosticInfos(diagnosticInfos, browseOperations);
unprocessedOperations.Clear();
unprocessedBrowseIndexes.Clear();
ByteStringCollection continuationPoints = new ByteStringCollection();
List<int> continuationPointIndexes = new List<int>();
for (int ii = 0; ii < browseOperations.Count; ii++)
{
int index = browseIndexes[ii];
// Utils.Trace("{0}/{1}/{2}", browseOperations[ii].NodeId, browseOperations[ii].ReferenceTypeId, results[ii].References.Count);
// look up results.
BrowseResult combinedResult = null;
if (!combinedResults.TryGetValue(index, out combinedResult))
{
combinedResults[index] = combinedResult = new BrowseResult();
}
// check for error.
if (StatusCode.IsBad(results[ii].StatusCode))
{
// this error indicates that the server does not have enough simultaneously active
// continuation points. This request will need to be resent after the other operations
// have been completed and their continuation points released.
if (results[ii].StatusCode == StatusCodes.BadNoContinuationPoints)
{
unprocessedOperations.Add(browseOperations[ii]);
unprocessedBrowseIndexes.Add(index);
continue;
}
// save error.
if (StatusCode.IsGood(combinedResult.StatusCode))
{
combinedResult.StatusCode = results[ii].StatusCode;
}
continue;
}
// check if all references have been fetched.
if (results[ii].References.Count == 0)
{
continue;
}
// save results.
combinedResult.References.AddRange(results[ii].References);
// check for continuation point.
if (results[ii].ContinuationPoint != null && results[ii].ContinuationPoint.Length > 0)
{
continuationPoints.Add(results[ii].ContinuationPoint);
continuationPointIndexes.Add(index);
}
}
// process continuation points.
ByteStringCollection revisedContinuationPoints = new ByteStringCollection();
List<int> revisedContinuationPointIndexes = new List<int>();
while (continuationPoints.Count > 0)
{
bool releaseContinuationPoints = false;
// continue browse operation.
session.BrowseNext(
null,
releaseContinuationPoints,
continuationPoints,
out results,
out diagnosticInfos);
ClientBase.ValidateResponse(results, continuationPoints);
ClientBase.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints);
revisedContinuationPoints.Clear();
revisedContinuationPointIndexes.Clear();
for (int ii = 0; ii < continuationPoints.Count; ii++)
{
int index = continuationPointIndexes[ii];
// look up results.
BrowseResult combinedResult = null;
if (!combinedResults.TryGetValue(index, out combinedResult))
{
combinedResults[index] = new BrowseResult();
}
// check for error.
if (StatusCode.IsBad(results[ii].StatusCode))
{
// save error.
if (StatusCode.IsGood(combinedResult.StatusCode))
{
combinedResult.StatusCode = results[ii].StatusCode;
}
continue;
}
// check if all references have been fetched.
if (results[ii].References.Count == 0)
{
continue;
}
// save results.
combinedResult.References.AddRange(results[ii].References);
// check for continuation point.
if (results[ii].ContinuationPoint != null && results[ii].ContinuationPoint.Length > 0)
{
revisedContinuationPoints.Add(results[ii].ContinuationPoint);
revisedContinuationPointIndexes.Add(index);
}
}
// check if browsing must continue;
continuationPoints = revisedContinuationPoints;
continuationPointIndexes = revisedContinuationPointIndexes;
}
// check if unprocessed results exist.
browseOperations = unprocessedOperations;
browseIndexes = unprocessedBrowseIndexes;
}
// reconstruct list of combined results.
BrowseResultCollection finalResults = new BrowseResultCollection();
for (int ii = 0; ii < nodesToBrowse.Count; ii++)
{
BrowseResult combinedResult = null;
if (!combinedResults.TryGetValue(ii, out combinedResult))
{
combinedResult = new BrowseResult();
}
finalResults.Add(combinedResult);
}
// return complete list.
return finalResults;
}
catch (Exception e)
{
throw ComUtils.CreateComException(e, ResultIds.E_FAIL);
}
}