internal async Task HandleCloseSessionRequest(CloseSessionParams closeSessionParams, RequestContext <CloseSessionResponse> context) { Logger.Write(LogLevel.Verbose, "HandleCloseSessionRequest"); Func <Task <CloseSessionResponse> > closeSession = () => { Validate.IsNotNull(nameof(closeSessionParams), closeSessionParams); Validate.IsNotNull(nameof(context), context); return(Task.Factory.StartNew(() => { string uri = closeSessionParams.SessionId; ObjectExplorerSession session = null; bool success = false; if (!sessionMap.TryGetValue(uri, out session)) { Logger.Write(LogLevel.Verbose, $"Cannot close object explorer session. Couldn't find session for uri. {uri} "); } if (session != null) { // refresh the nodes for given node path CloseSession(uri); success = true; } var response = new CloseSessionResponse() { Success = success, SessionId = uri }; return response; })); }; await HandleRequestAsync(closeSession, context, "HandleCloseSessionRequest"); }
internal async Task HandleExpandRequest(ExpandParams expandParams, RequestContext <bool> context) { Logger.Write(LogLevel.Verbose, "HandleExpandRequest"); Func <Task <bool> > expandNode = async() => { Validate.IsNotNull(nameof(expandParams), expandParams); Validate.IsNotNull(nameof(context), context); string uri = expandParams.SessionId; ObjectExplorerSession session = null; if (!sessionMap.TryGetValue(uri, out session)) { Logger.Write(LogLevel.Verbose, $"Cannot expand object explorer node. Couldn't find session for uri. {uri} "); await serviceHost.SendEvent(ExpandCompleteNotification.Type, new ExpandResponse { SessionId = expandParams.SessionId, NodePath = expandParams.NodePath, ErrorMessage = $"Couldn't find session for session: {uri}" }); return(false); } else { RunExpandTask(session, expandParams); return(true); } }; await HandleRequestAsync(expandNode, context, "HandleExpandRequest"); }
private async Task ExpandTree(NodeInfo node, ObjectExplorerSession session, StringBuilder stringBuilder = null, bool verifySystemObjects = false) { if (node != null && !node.IsLeaf) { var children = (await _service.ExpandNode(session, node.NodePath)).Nodes; foreach (var child in children) { VerifyMetadata(child); if (stringBuilder != null && child.NodeType != "Folder" && child.NodeType != "FileGroupFile") { stringBuilder.Append($"NodeType: {child.NodeType} Label: {child.Label} SubType:{child.NodeSubType} Status:{child.NodeStatus}{Environment.NewLine}"); } if (!verifySystemObjects && (child.Label == SR.SchemaHierarchy_SystemStoredProcedures || child.Label == SR.SchemaHierarchy_SystemViews || child.Label == SR.SchemaHierarchy_SystemFunctions || child.Label == SR.SchemaHierarchy_SystemDataTypes)) { // don't expand the system folders because then the test will take for ever } else { await ExpandTree(child, session, stringBuilder, verifySystemObjects); } } } }
/// <summary> /// Returns the node with the given label /// </summary> private async Task <NodeInfo> FindNodeByLabel(NodeInfo node, ObjectExplorerSession session, string label) { if (node != null && node.Label == label) { return(node); } else if (node != null && !node.IsLeaf) { var response = await _service.ExpandNode(session, node.NodePath); var children = response.Nodes; Assert.NotNull(children); foreach (var child in children) { VerifyMetadata(child); if (child.Label == label) { return(child); } var result = await FindNodeByLabel(child, session, label); if (result != null) { return(result); } } } return(null); }
internal async Task <ExpandResponse> ExpandNode(ObjectExplorerSession session, string nodePath, bool forceRefresh = false) { return(await Task.Factory.StartNew(() => { return QueueExpandNodeRequest(session, nodePath, forceRefresh); })); }
private ExpandResponse CreateExpandResponse(ObjectExplorerSession session, ExpandParams expandParams) { return(new ExpandResponse() { SessionId = session.Uri, NodePath = expandParams.NodePath }); }
/// <summary> /// Establishes a new session and stores its information /// </summary> /// <returns><see cref="ObjectExplorerSession"/> object if successful, null if unsuccessful</returns> internal async Task <ObjectExplorerSession> DoCreateSession(ConnectionDetails connectionDetails, string uri) { try { ObjectExplorerSession session; connectionDetails.PersistSecurityInfo = true; ConnectParams connectParams = new ConnectParams() { OwnerUri = uri, Connection = connectionDetails }; ConnectionCompleteParams connectionResult = await Connect(connectParams, uri); if (connectionResult == null) { // Connection failed and notification is already sent return(null); } session = ObjectExplorerSession.CreateSession(connectionResult, serviceProvider); sessionMap.AddOrUpdate(uri, session, (key, oldSession) => session); return(session); } catch (Exception ex) { await SendSessionFailedNotification(uri, ex.Message); return(null); } }
internal async Task HandleRefreshRequest(RefreshParams refreshParams, RequestContext <bool> context) { try { Logger.Write(LogLevel.Verbose, "HandleRefreshRequest"); Validate.IsNotNull(nameof(refreshParams), refreshParams); Validate.IsNotNull(nameof(context), context); string uri = refreshParams.SessionId; ObjectExplorerSession session = null; if (!sessionMap.TryGetValue(uri, out session)) { Logger.Write(LogLevel.Verbose, $"Cannot expand object explorer node. Couldn't find session for uri. {uri} "); await serviceHost.SendEvent(ExpandCompleteNotification.Type, new ExpandResponse { SessionId = refreshParams.SessionId, NodePath = refreshParams.NodePath, ErrorMessage = $"Couldn't find session for session: {uri}" }); } else { RunExpandTask(session, refreshParams, true); } await context.SendResult(true); } catch (Exception ex) { await context.SendError(ex.ToString()); } }
/// <summary> /// Establishes a new session and stores its information /// </summary> /// <returns><see cref="ObjectExplorerSession"/> object if successful, null if unsuccessful</returns> internal async Task <ObjectExplorerSession> DoCreateSession(ConnectionDetails connectionDetails, string uri) { try { ObjectExplorerSession session = null; connectionDetails.PersistSecurityInfo = true; ConnectParams connectParams = new ConnectParams() { OwnerUri = uri, Connection = connectionDetails, Type = Connection.ConnectionType.ObjectExplorer }; bool isDefaultOrSystemDatabase = DatabaseUtils.IsSystemDatabaseConnection(connectionDetails.DatabaseName) || string.IsNullOrWhiteSpace(connectionDetails.DatabaseDisplayName); ConnectionInfo connectionInfo; ConnectionCompleteParams connectionResult = await Connect(connectParams, uri); if (!connectionService.TryFindConnection(uri, out connectionInfo)) { return(null); } if (connectionResult == null) { // Connection failed and notification is already sent return(null); } int timeout = (int)TimeSpan.FromSeconds(settings?.CreateSessionTimeout ?? ObjectExplorerSettings.DefaultCreateSessionTimeout).TotalMilliseconds; QueueItem queueItem = bindingQueue.QueueBindingOperation( key: bindingQueue.AddConnectionContext(connectionInfo, connectionName), bindingTimeout: timeout, waitForLockTimeout: timeout, bindOperation: (bindingContext, cancelToken) => { session = ObjectExplorerSession.CreateSession(connectionResult, serviceProvider, bindingContext.ServerConnection, isDefaultOrSystemDatabase); session.ConnectionInfo = connectionInfo; sessionMap.AddOrUpdate(uri, session, (key, oldSession) => session); return(session); }); queueItem.ItemProcessed.WaitOne(); if (queueItem.GetResultAsT <ObjectExplorerSession>() != null) { session = queueItem.GetResultAsT <ObjectExplorerSession>(); } return(session); } catch (Exception ex) { await SendSessionFailedNotification(uri, ex.Message); return(null); } }
public static ObjectExplorerSession CreateSession(ConnectionCompleteParams response, IMultiServiceProvider serviceProvider, ServerConnection serverConnection, bool isDefaultOrSystemDatabase) { ServerNode rootNode = new ServerNode(response, serviceProvider, serverConnection); var session = new ObjectExplorerSession(response.OwnerUri, rootNode, serviceProvider, serviceProvider.GetService <ConnectionService>()); if (!isDefaultOrSystemDatabase) { // Assuming the databases are in a folder under server node DatabaseTreeNode databaseNode = new DatabaseTreeNode(rootNode, response.ConnectionSummary.DatabaseName); session.Root = databaseNode; } return(session); }
private async Task ExpandNodeAsync(ObjectExplorerSession session, ExpandParams expandParams, CancellationToken cancellationToken, bool forceRefresh = false) { ExpandResponse response = null; response = await ExpandNode(session, expandParams.NodePath, forceRefresh); if (cancellationToken.IsCancellationRequested) { Logger.Write(LogLevel.Verbose, "OE expand canceled"); } else { await serviceHost.SendEvent(ExpandCompleteNotification.Type, response); } }
internal ExpandResponse QueueExpandNodeRequest(ObjectExplorerSession session, string nodePath, bool forceRefresh = false) { NodeInfo[] nodes = null; TreeNode node = session.Root.FindNodeByPath(nodePath); ExpandResponse response = new ExpandResponse { Nodes = new NodeInfo[] { }, ErrorMessage = node.ErrorMessage, SessionId = session.Uri, NodePath = nodePath }; if (node != null && Monitor.TryEnter(node.BuildingMetadataLock, LanguageService.OnConnectionWaitTimeout)) { try { int timeout = (int)TimeSpan.FromSeconds(settings?.ExpandTimeout ?? ObjectExplorerSettings.DefaultExpandTimeout).TotalMilliseconds; QueueItem queueItem = bindingQueue.QueueBindingOperation( key: bindingQueue.AddConnectionContext(session.ConnectionInfo, connectionName), bindingTimeout: timeout, waitForLockTimeout: timeout, bindOperation: (bindingContext, cancelToken) => { if (forceRefresh) { nodes = node.Refresh().Select(x => x.ToNodeInfo()).ToArray(); } else { nodes = node.Expand().Select(x => x.ToNodeInfo()).ToArray(); } response.Nodes = nodes; response.ErrorMessage = node.ErrorMessage; return(response); }); queueItem.ItemProcessed.WaitOne(); if (queueItem.GetResultAsT <ExpandResponse>() != null) { response = queueItem.GetResultAsT <ExpandResponse>(); } } catch { } finally { Monitor.Exit(node.BuildingMetadataLock); } } return(response); }
private void RunExpandTask(ObjectExplorerSession session, ExpandParams expandParams, bool forceRefresh = false) { CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); Task task = ExpandNodeAsync(session, expandParams, cancellationTokenSource.Token, forceRefresh); ExpandTask = task; Task.Run(async() => { ObjectExplorerTaskResult result = await RunTaskWithTimeout(task, settings?.ExpandTimeout ?? ObjectExplorerSettings.DefaultExpandTimeout); if (result != null && !result.IsCompleted) { cancellationTokenSource.Cancel(); ExpandResponse response = CreateExpandResponse(session, expandParams); response.ErrorMessage = result.Exception != null ? result.Exception.Message: $"Failed to expand node: {expandParams.NodePath} in session {session.Uri}"; await serviceHost.SendEvent(ExpandCompleteNotification.Type, response); } return(result); }).ContinueWithOnFaulted(null); }
private async Task ExpandAndVerifyDatabaseNode(string databaseName, ObjectExplorerSession session) { Assert.NotNull(session); Assert.NotNull(session.Root); NodeInfo nodeInfo = session.Root.ToNodeInfo(); Assert.Equal(nodeInfo.IsLeaf, false); Assert.Equal(nodeInfo.NodeType, NodeTypes.Database.ToString()); Assert.True(nodeInfo.Label.Contains(databaseName)); var children = (await _service.ExpandNode(session, session.Root.GetNodePath())).Nodes; //All server children should be folder nodes foreach (var item in children) { Assert.Equal(item.NodeType, "Folder"); } var tablesRoot = children.FirstOrDefault(x => x.Label == SR.SchemaHierarchy_Tables); Assert.NotNull(tablesRoot); }
internal async Task <ExpandResponse> ExpandNode(ObjectExplorerSession session, string nodePath, bool forceRefresh = false) { return(await Task.Factory.StartNew(() => { NodeInfo[] nodes = null; TreeNode node = session.Root.FindNodeByPath(nodePath); if (node != null) { if (forceRefresh) { nodes = node.Refresh().Select(x => x.ToNodeInfo()).ToArray(); } else { nodes = node.Expand().Select(x => x.ToNodeInfo()).ToArray(); } } return new ExpandResponse { Nodes = nodes, ErrorMessage = node.ErrorMessage, SessionId = session.Uri, NodePath = nodePath }; })); }
private async Task VerifyRefresh(ObjectExplorerSession session, string tablePath, string tableName, bool deleted = true) { //Refresh Root var rootChildren = await _service.ExpandNode(session, session.Root.ToNodeInfo().NodePath, true); //Verify tables cache is empty var rootChildrenCache = session.Root.GetChildren(); var tablesCache = rootChildrenCache.First(x => x.Label == SR.SchemaHierarchy_Tables).GetChildren(); Assert.False(tablesCache.Any()); //Expand Tables var tableChildren = (await _service.ExpandNode(session, tablePath, true)).Nodes; //Verify table is not returned Assert.Equal(tableChildren.Any(t => t.Label == tableName), !deleted); //Verify tables cache has items rootChildrenCache = session.Root.GetChildren(); tablesCache = rootChildrenCache.First(x => x.Label == SR.SchemaHierarchy_Tables).GetChildren(); Assert.True(tablesCache.Any()); }
private async Task <NodeInfo> ExpandServerNodeAndVerifyDatabaseHierachy(string databaseName, ObjectExplorerSession session, bool serverNode = true) { Assert.NotNull(session); Assert.NotNull(session.Root); NodeInfo nodeInfo = session.Root.ToNodeInfo(); Assert.Equal(nodeInfo.IsLeaf, false); NodeInfo databaseNode = null; if (serverNode) { Assert.Equal(nodeInfo.NodeType, NodeTypes.Server.ToString()); var children = session.Root.Expand(new CancellationToken()); //All server children should be folder nodes foreach (var item in children) { Assert.Equal(item.NodeType, "Folder"); } var databasesRoot = children.FirstOrDefault(x => x.NodeTypeId == NodeTypes.Databases); var databasesChildren = (await _service.ExpandNode(session, databasesRoot.GetNodePath())).Nodes; var databases = databasesChildren.Where(x => x.NodeType == NodeTypes.Database.ToString()); //Verify the test databases is in the list Assert.NotNull(databases); Assert.False(databases.Any(x => x.Label == "master")); var systemDatabasesNode = databasesChildren.FirstOrDefault(x => x.Label == SR.SchemaHierarchy_SystemDatabases); Assert.NotNull(systemDatabasesNode); var systemDatabases = await _service.ExpandNode(session, systemDatabasesNode.NodePath); Assert.True(systemDatabases.Nodes.Any(x => x.Label == "master")); databaseNode = databases.FirstOrDefault(d => d.Label == databaseName); } else { Assert.Equal(nodeInfo.NodeType, NodeTypes.Database.ToString()); databaseNode = session.Root.ToNodeInfo(); Assert.True(databaseNode.Label.Contains(databaseName)); var databasesChildren = (await _service.ExpandNode(session, databaseNode.NodePath)).Nodes; Assert.False(databasesChildren.Any(x => x.Label == SR.SchemaHierarchy_SystemDatabases)); } Assert.NotNull(databaseNode); return(databaseNode); }
internal ExpandResponse QueueExpandNodeRequest(ObjectExplorerSession session, string nodePath, bool forceRefresh = false) { NodeInfo[] nodes = null; TreeNode node = session.Root.FindNodeByPath(nodePath); ExpandResponse response = new ExpandResponse { Nodes = new NodeInfo[] { }, ErrorMessage = node.ErrorMessage, SessionId = session.Uri, NodePath = nodePath }; if (node != null && Monitor.TryEnter(node.BuildingMetadataLock, LanguageService.OnConnectionWaitTimeout)) { try { int timeout = (int)TimeSpan.FromSeconds(settings?.ExpandTimeout ?? ObjectExplorerSettings.DefaultExpandTimeout).TotalMilliseconds; QueueItem queueItem = bindingQueue.QueueBindingOperation( key: bindingQueue.AddConnectionContext(session.ConnectionInfo, connectionName), bindingTimeout: timeout, waitForLockTimeout: timeout, bindOperation: (bindingContext, cancelToken) => { if (forceRefresh) { nodes = node.Refresh().Select(x => x.ToNodeInfo()).ToArray(); } else { nodes = node.Expand().Select(x => x.ToNodeInfo()).ToArray(); } response.Nodes = nodes; response.ErrorMessage = node.ErrorMessage; try { // SMO changes the database when getting sql objects. Make sure the database is changed back to the original one if (bindingContext.ServerConnection.CurrentDatabase != bindingContext.ServerConnection.DatabaseName) { bindingContext.ServerConnection.SqlConnectionObject.ChangeDatabase(bindingContext.ServerConnection.DatabaseName); } } catch (Exception ex) { Logger.Write(LogLevel.Warning, $"Failed to change the database in OE connection. error: {ex.Message}"); // We should just try to change the connection. If it fails, there's not much we can do } return(response); }); queueItem.ItemProcessed.WaitOne(); if (queueItem.GetResultAsT <ExpandResponse>() != null) { response = queueItem.GetResultAsT <ExpandResponse>(); } } catch { } finally { Monitor.Exit(node.BuildingMetadataLock); } } return(response); }