You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
7.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#Region "Microsoft.VisualBasic::e60e21b276f0d529eb9cae8b0a40b16b, ComputingServices\Taskhost.d\Invoke\TaskHost.vb"
' Author:
'
' asuka (amethyst.asuka@gcmodeller.org)
' xie (genetics@smrucc.org)
' xieguigang (xie.guigang@live.com)
'
' Copyright (c) 2018 GPL3 Licensed
'
'
' GNU GENERAL PUBLIC LICENSE (GPL3)
'
'
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
' GNU General Public License for more details.
'
' You should have received a copy of the GNU General Public License
' along with this program. If not, see <http://www.gnu.org/licenses/>.
' /********************************************************************************/
' Summaries:
' Class TaskRemote
'
' Properties: FileSystem, Key, Load
'
' Constructor: (+2 Overloads) Sub New
' Function: [Select], AsLinq, (+3 Overloads) Invoke, Shell
'
'
' /********************************************************************************/
#End Region
Imports Microsoft.VisualBasic.ComponentModel.Collection.Generic
Imports Microsoft.VisualBasic.Net
Imports Microsoft.VisualBasic.Net.Http
Imports Microsoft.VisualBasic.Net.Protocols
Imports Microsoft.VisualBasic.Serialization.JSON
Imports sciBASIC.ComputingServices.ComponentModel
Imports sciBASIC.ComputingServices.FileSystem
Namespace TaskHost
''' <summary>
''' Using this object to running the method on the remote machine.
''' (由于是远程调用,所以运行的环境可能会很不一样,所以在设计程序的时候请尽量
''' 避免或者不要使用模块变量以免出现难以调查的BUG)
''' </summary>
Public Class TaskRemote : Implements IRemoteSupport
Implements INamedValue
Dim _remote As IPEndPoint
Public ReadOnly Property FileSystem As FileSystemHost Implements IRemoteSupport.FileSystem
Private Property Key As String Implements INamedValue.Key
Get
Return _remote.IPAddress
End Get
Set(value As String)
_remote.IPAddress = value
End Set
End Property
''' <summary>
''' 获取得到远程主机的负载量
''' </summary>
''' <returns></returns>
Public ReadOnly Property Load As Double
Get
Dim req As New RequestStream(Protocols.ProtocolEntry, TaskProtocols.NodeLoad)
Dim rep = New AsynInvoke(_remote).SendMessage(req, 1000)
If rep.Protocol <> HTTP_RFC.RFC_OK Then
Return 1000
Else
Return rep.LoadObject(Of Double)
End If
End Get
End Property
Sub New(remote As IPEndPoint)
_remote = remote
FileSystem = New FileSystemHost(GetFirstAvailablePort)
End Sub
Sub New(remote As String, port As Integer)
Call Me.New(New IPEndPoint(remote, port))
End Sub
''' <summary>
''' Start the application on the remote host.(相当于Sub调用远程的命令行程序只会返回0或者错误代码)
''' </summary>
''' <param name="exe">Exe file path</param>
''' <param name="args"></param>
''' <returns></returns>
Public Function Shell(exe As String, args As String) As Integer
Dim func As Func(Of String, String, Integer) = AddressOf Protocols.Shell
Return Invoke(Of Integer)(func, {exe, args})
End Function
''' <summary>
''' Running the function delegate pointer on the remote machine.
'''
''' *****************************************************************************************************
''' NOTE: Performance issue, this is important! if the function pointer its returns type is a collection,
''' then you should using the method <see cref="TaskRemote.AsLinq(Of T)([Delegate], Object())"/> to running
''' your code on the remote. Or a large json data will be return back through network in one package,
''' this may cause a serious performance problem both on your server and your local client.
''' (本地服务器通过这个方法调用远程主机上面的函数,假若目标函数的返回值类型是一个集合,
''' 请使用<see cref="TaskRemote.AsLinq(Of T)([Delegate], Object())"/>方法,否则集合之中的所有数据都将会一次性返回,
''' 这个可能会导致严重的性能问题)
''' </summary>
''' <param name="target"></param>
''' <param name="args"></param>
''' <returns></returns>
Public Function Invoke(target As [Delegate], ParamArray args As Object()) As Object
Dim params As InvokeInfo = InvokeInfo.CreateObject(target, args)
Dim rtvl As Rtvl = Invoke(params)
Dim obj As Object = rtvl.GetValue(target)
Return obj
End Function
Public Function Invoke(info As InvokeInfo) As Rtvl
Dim value As String = JsonContract.GetJson(info)
Dim req As RequestStream = New RequestStream(ProtocolEntry, TaskProtocols.Invoke, value)
Dim rep As RequestStream = New AsynInvoke(_remote).SendMessage(req)
Dim rtvl As Rtvl = JsonContract.LoadObject(Of Rtvl)(rep.GetUTF8String)
Return rtvl
End Function
Public Function Invoke(Of T)(target As [Delegate], ParamArray args As Object()) As T
Dim value As Object = Invoke(target, args)
If value Is Nothing Then
Return Nothing
Else
Return DirectCast(value, T)
End If
End Function
''' <summary>
''' If your function pointer returns type is a collection, then using this method is recommended.
''' (执行远程机器上面的代码,然后返回数据查询接口)
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="target">远程机器上面的函数指针</param>
''' <param name="args"></param>
''' <returns></returns>
Public Function AsLinq(Of T)(target As [Delegate], ParamArray args As Object()) As ILinq(Of T)
Dim params As InvokeInfo = InvokeInfo.CreateObject(target, args)
Dim jparam As String = params.GetJson
Dim req As New RequestStream(ProtocolEntry, TaskProtocols.InvokeLinq, jparam)
Dim rep As RequestStream = New AsynInvoke(_remote).SendMessage(req)
Dim svr As IPEndPoint = rep.GetUTF8String.LoadObject(Of IPEndPoint)
Return New ILinq(Of T)(svr)
End Function
Public Function [Select](Of T, Tout)(target As [Delegate], source As T(), ParamArray args As Object()) As ILinq(Of Tout)
Dim params As InvokeInfo = InvokeInfo.CreateObject(target, {CObj(source)}.Join(args))
Dim jparam As String = params.GetJson
Dim req As New RequestStream(ProtocolEntry, TaskProtocols.Select, jparam)
Dim rep As RequestStream = New AsynInvoke(_remote).SendMessage(req)
Dim svr As IPEndPoint = rep.GetUTF8String.LoadObject(Of IPEndPoint)
Return New ILinq(Of Tout)(svr)
End Function
End Class
End Namespace