ass_maintainer-info_base 0.1.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,80 @@
1
+ module AssMaintainer
2
+ class InfoBase
3
+ module ServerIb
4
+ require 'ass_ole'
5
+ module EnterpriseServers
6
+ require 'ass_maintainer/info_base/server_ib/enterprise_servers/support'
7
+ require 'ass_maintainer/info_base/server_ib/enterprise_servers/server_agent'
8
+ require 'ass_maintainer/info_base/server_ib/enterprise_servers/cluster'
9
+ require 'ass_maintainer/info_base/server_ib/enterprise_servers/wp_connection'
10
+
11
+ # @api private
12
+ # Wrappers for 1C OLE objects
13
+ module Wrappers
14
+ # @api private
15
+ # Wrapper for 1C:Enterprise +IWorkingProcessInfo+ ole object
16
+ class WorkingProcessInfo
17
+ include Support::SendToOle
18
+ attr_reader :ole, :cluster, :sagent, :connection
19
+ def initialize(ole, cluster)
20
+ @ole, @cluster, @sagent = ole, cluster, cluster.sagent
21
+ end
22
+
23
+ def connect(infobase_wrapper)
24
+ WpConnection.new(self).connect(infobase_wrapper)
25
+ end
26
+
27
+ # Return +true+ if TCP port available on server
28
+ def ping?
29
+ tcp_ping.ping?
30
+ end
31
+
32
+ require 'net/ping/tcp'
33
+ # @return [Net::Ping::TCP] instance
34
+ def tcp_ping
35
+ @tcp_ping ||= Net::Ping::TCP.new(hostName, mainPort)
36
+ end
37
+ end
38
+
39
+ # @api private
40
+ # Wrapper for 1C:Enterprise +ISessionInfo+ ole object
41
+ class Session
42
+ include Support::SendToOle
43
+
44
+ # @api private
45
+ # @return +ISessionInfo+ ole object
46
+ attr_reader :ole
47
+
48
+ # @api private
49
+ # @return [EnterpriseServers::Cluster] cluster where session
50
+ # registred
51
+ attr_reader :cluster
52
+
53
+ # @api private
54
+ # @return [EnterpriseServers::ServerAgent] 1C server where session
55
+ # registred
56
+ attr_reader :sagent
57
+
58
+ # @api private
59
+ def initialize(ole, cluster)
60
+ @ole, @cluster, @sagent = ole, cluster, cluster.sagent
61
+ end
62
+
63
+ # Terminate session
64
+ def terminate
65
+ sagent.TerminateSession(cluster.ole, ole)
66
+ rescue WIN32OLERuntimeError
67
+ end
68
+
69
+ # @return [InfoBase::Session]
70
+ # @param infobase [InfoBase] instance
71
+ def to_session(infobase)
72
+ InfoBase::Session
73
+ .new SessionId(), AppId(), Host(), UserName(), infobase
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,114 @@
1
+ module AssMaintainer
2
+ class InfoBase
3
+ module ServerIb
4
+ module EnterpriseServers
5
+ # @api private
6
+ # Object descrbed 1C cluster
7
+ class Cluster
8
+ # Deafult 1C:Enterprise cluster TCP port
9
+ DEF_PORT = '1541'
10
+
11
+ include Support::ServerConnection
12
+ include Support::SendToOle
13
+ include Support::InfoBaseFind
14
+
15
+ # @return [String] {DEF_PORT}
16
+ def default_port
17
+ DEF_PORT
18
+ end
19
+
20
+ # Attache cluster into server agent
21
+ # @param agent [ServerAgent]
22
+ # @raise (see #authenticate)
23
+ def attach(agent)
24
+ @sagent = agent unless @sagent
25
+ ole_set
26
+ authenticate
27
+ end
28
+
29
+ # @return [ServerAgent] which cluster attached
30
+ # @raise [RuntimeError] unless cluster attached
31
+ def sagent
32
+ fail 'Cluster must be attachet to ServerAgent' unless @sagent
33
+ @sagent
34
+ end
35
+
36
+ # @return +IClusterInfo+ ole object
37
+ # @raise [RuntimeError] if cluster not found on {#sagent} server
38
+ def ole
39
+ fail ArgumentError, "Cluster `#{host_port}'"\
40
+ " not found on server `#{sagent.host_port}'" unless @ole
41
+ @ole
42
+ end
43
+
44
+ # Authenticate cluster user
45
+ # @raise (see #ole)
46
+ def authenticate
47
+ sagent.Authenticate(ole, user.to_s, password.to_s)
48
+ self
49
+ end
50
+
51
+ def ole_set
52
+ @ole = sagent.cluster_find(host, port)
53
+ ole
54
+ end
55
+ private :ole_set
56
+
57
+ # @return [Array<WIN32OLE>] aray of +IInfoBaseShort+ ole objects
58
+ # registred in cluster
59
+ # @raise (see #ole)
60
+ # @raise (see #sagent)
61
+ def infobases
62
+ sagent.GetInfoBases(ole)
63
+ end
64
+
65
+ # @return [nil Array<Wrappers::Session>] sessions for infobase
66
+ # runned in cluster. +nil+ if infobase +ib_name+ not registred in
67
+ # cluster.
68
+ # @param ib_name [String] infobase name
69
+ # @raise (see #sagent)
70
+ def infobase_sessions(ib_name)
71
+ ib = infobase_find(ib_name)
72
+ return unless ib
73
+ sagent.GetInfoBaseSessions(ole, ib).map do |s|
74
+ Wrappers::Session.new(s, self)
75
+ end
76
+ end
77
+
78
+ # All Working processes in cluster
79
+ # @return [Array<Wrappers::WorkingProcessInfo]
80
+ def wprocesses
81
+ sagent.GetWorkingProcesses(ole).map do |wpi|
82
+ Wrappers::WorkingProcessInfo.new(wpi, self)
83
+ end
84
+ end
85
+
86
+ # Connect to working process
87
+ # @return [WpConnection] object for comunication with 1C Working
88
+ # process
89
+ def wp_connection(infobase_wrapper)
90
+ if !@wp_connection.nil? && !@wp_connection.ping?
91
+ @wp_connection = nil
92
+ end
93
+ @wp_connection ||= alive_wprocess_get.connect(infobase_wrapper)
94
+ end
95
+
96
+ def alive_wprocess_get
97
+ wp_info = wprocesses.select{|p| p.Running == 1 && p.ping?}[0]
98
+ fail 'No alive working processes found' unless wp_info
99
+ wp_info
100
+ end
101
+
102
+ # Delete infobase
103
+ # @param infobase_wrapper [InfoBaseWrapper] infobase wrapper
104
+ # @param mode [Symbol] defines what should do with
105
+ # infobase's database. See {WpConnection::DROP_MODES}
106
+ def drop_infobase!(infobase_wrapper, mode)
107
+ wp_connection(infobase_wrapper).drop_infobase!(mode)
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+
@@ -0,0 +1,91 @@
1
+ module AssMaintainer
2
+ class InfoBase
3
+ module ServerIb
4
+ module EnterpriseServers
5
+ # @api private
6
+ # Object descrbed 1C server agent connection.
7
+ # @example
8
+ # # Get 1C:Eneterprise server agent connection object and connect
9
+ # # to net service
10
+ # sagent = ServerAgent.new('localhost:1540', 'admin', 'password')
11
+ # .connect('~> 8.3.8.0')
12
+ #
13
+ # # Working with server agent connection
14
+ # sagent.ConnectionString #=> "tcp://localhost:1540"
15
+ # cl = sagent.cluster_find 'localhost', '1542'
16
+ #
17
+ # # Close connection
18
+ # sagent.disconnect
19
+ #
20
+ module ServerAgent
21
+ include Support::ServerConnection
22
+ include Support::OleRuntime
23
+ include Support::Reconnect
24
+
25
+ # Make new object of anonymous class which included this module.
26
+ def self.new(host_port, user, password)
27
+ Class.new do
28
+ include ServerAgent
29
+ end.new host_port, user, password
30
+ end
31
+
32
+ # @return [String] wrapper for {InfoBase::DEFAULT_SAGENT_PORT}
33
+ def default_port
34
+ InfoBase::DEFAULT_SAGENT_PORT
35
+ end
36
+
37
+ def runtime_type
38
+ :agent
39
+ end
40
+
41
+ # Connect to 1C:Eneterprise server via OLE
42
+ # @note while connecting in instance class will be included
43
+ # {.runtime_new} module
44
+ # @param platform_require [String Gem::Requirement]
45
+ # 1C:Eneterprise version required
46
+ # @return +self+
47
+ def connect(platform_require)
48
+ _connect(host_port, platform_require)
49
+ end
50
+
51
+ # Authenticate {#user}
52
+ # @raise if not connected
53
+ def authenticate
54
+ AuthenticateAgent(user.to_s, password.to_s) if\
55
+ connected? && !authenticate?
56
+ end
57
+
58
+ # True if #{user} authenticate
59
+ def authenticate?
60
+ return false unless connected?
61
+ begin
62
+ ole_connector.GetAgentAdmins
63
+ rescue WIN32OLERuntimeError
64
+ return false
65
+ end
66
+ true
67
+ end
68
+
69
+ # @return [nil WIN32OLE] +IClusterInfo+ ole object
70
+ # @raise if not connected
71
+ def cluster_find(host, port)
72
+ reconnect
73
+ GetClusters().find do |cl|
74
+ cl.HostName.upcase == host.upcase && cl.MainPort == port.to_i
75
+ end
76
+ end
77
+
78
+ def platform_require
79
+ return unless connected?
80
+ ole_connector.send(:__ole_binary__).requirement.to_s
81
+ end
82
+
83
+ def _reconnect_required?
84
+ getClusters.empty?
85
+ end
86
+ private :_reconnect_required?
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,200 @@
1
+ module AssMaintainer
2
+ class InfoBase
3
+ module ServerIb
4
+ module EnterpriseServers
5
+ # @api private
6
+ # Mixins
7
+ module Support
8
+ # Mixin for redirect +method_missing+ to +ole+ object
9
+ module SendToOle
10
+ def method_missing(m, *args)
11
+ ole.send m, *args
12
+ end
13
+ end
14
+
15
+ # Ole runtime mixin
16
+ module OleRuntime
17
+ require 'ass_ole'
18
+ # Close connection with 1C:Enterprise server
19
+ def disconnect
20
+ runtime_stop
21
+ end
22
+
23
+ # True if connected
24
+ def connected?
25
+ respond_to?(:ole_runtime_get) && ole_runtime_get.runned?
26
+ end
27
+
28
+ def runtime_stop
29
+ ole_runtime_get.stop if respond_to? :ole_runtime_get
30
+ end
31
+ private :runtime_stop
32
+
33
+ # Include and run {.runtime_new} runtime
34
+ def runtime_run(host_port, platform_require)
35
+ self.class.like_ole_runtime OleRuntime.runtime_new(self) unless\
36
+ respond_to? :ole_runtime_get
37
+ ole_runtime_get.run host_port, platform_require
38
+ end
39
+ private :runtime_run
40
+
41
+ # Make new runtime module +AssOle::Runtimes::Claster::(Agent|Wp)+
42
+ # for access to
43
+ # +AssLauncher::Enterprise::Ole::(AgentConnection|WpConnection)+
44
+ # @param inst [#runtime_type] +#runtime_type+ must returns
45
+ # +:wp+ or +:agent+ values
46
+ # @return [Module]
47
+ def self.runtime_new(inst)
48
+ Module.new do
49
+ is_ole_runtime inst.runtime_type
50
+ end
51
+ end
52
+
53
+ def _connect(host_port, platform_require)
54
+ runtime_run host_port, platform_require unless connected?
55
+ begin
56
+ authenticate unless authenticate?
57
+ rescue
58
+ runtime_stop
59
+ raise
60
+ end
61
+ self
62
+ end
63
+
64
+ def authenticate
65
+ fail 'Abstract method'
66
+ end
67
+
68
+ def authenticate?
69
+ fail 'Abstract method'
70
+ end
71
+ end
72
+
73
+ # Mixin for find infobase per name
74
+ module InfoBaseFind
75
+ def infobases
76
+ fail 'Abstract method'
77
+ end
78
+
79
+ # Searching infobase in {#infobases} array
80
+ # @param ib_name [String] infobase name
81
+ # @return [WIN32OLE] +IInfoBaseShort+ ole object
82
+ # @raise (see #infobases)
83
+ def infobase_find(ib_name)
84
+ infobases.find do |ib|
85
+ ib.Name.upcase == ib_name.upcase
86
+ end
87
+ end
88
+
89
+ # True if infobase registred in cluster
90
+ # @param ib_name [String] infobase name
91
+ # @raise (see #infobase_find)
92
+ def infobase_include?(ib_name)
93
+ !infobase_find(ib_name).nil?
94
+ end
95
+ end
96
+
97
+ # Mixin for reconnect ole runtime
98
+ module Reconnect
99
+ def reconnect
100
+ fail "Serevice #{host_port} not"\
101
+ " available: #{tcp_ping.exception}" unless ping?
102
+ return unless reconnect_required?
103
+ ole_connector.__close__
104
+ ole_connector.__open__ host_port
105
+ end
106
+ private :reconnect
107
+
108
+ def reconnect_required?
109
+ return true unless ole_connector.__opened__?
110
+ begin
111
+ _reconnect_required?
112
+ rescue WIN32OLERuntimeError => e
113
+ return true if e.message =~ %r{descr=10054}
114
+ end
115
+ end
116
+ private :reconnect_required?
117
+
118
+ def _reconnect_required?
119
+ fail 'Abstract method'
120
+ end
121
+ private :_reconnect_required?
122
+ end
123
+
124
+ # @api private
125
+ # Abstract server connection.
126
+ # Mixin for {Cluster} and {ServerAgent}
127
+ module ServerConnection
128
+ # Server user name
129
+ # See {#initialize} +user+ argument.
130
+ # @return [String]
131
+ attr_accessor :user
132
+
133
+ # Server user password
134
+ # See {#initialize} +password+ argument.
135
+ # @return [String]
136
+ attr_accessor :password
137
+
138
+ # Host name
139
+ attr_accessor :host
140
+
141
+ # TCP port
142
+ attr_accessor :port
143
+
144
+ # @param host_port [String] string like a +host_name:port_number+
145
+ # @param user [String] server user name
146
+ # @param password [String] server user password
147
+ def initialize(host_port, user = nil, password = nil)
148
+ fail ArgumentError, 'Host name require' if host_port.to_s.empty?
149
+ @raw_host_port = host_port
150
+ @host = parse_host
151
+ @port = parse_port || default_port
152
+ @user = user
153
+ @password = password
154
+ end
155
+
156
+ # String like a +host_name:port_number+.
157
+ # @return [String]
158
+ def host_port
159
+ "#{host}:#{port}"
160
+ end
161
+
162
+ def parse_port
163
+ p = @raw_host_port.split(':')[1].to_s.strip
164
+ return p unless p.empty?
165
+ end
166
+ private :parse_port
167
+
168
+ def parse_host
169
+ p = @raw_host_port.split(':')[0].to_s.strip
170
+ fail ArgumentError, "Invalid host_name for `#{@raw_host_port}'" if\
171
+ p.empty?
172
+ p
173
+ end
174
+ private :parse_host
175
+
176
+ def default_port
177
+ fail 'Abstract method'
178
+ end
179
+
180
+ # Return +true+ if TCP port available on server
181
+ def ping?
182
+ tcp_ping.ping?
183
+ end
184
+
185
+ require 'net/ping/tcp'
186
+ # @return [Net::Ping::TCP] instance
187
+ def tcp_ping
188
+ @tcp_ping ||= Net::Ping::TCP.new(host, port)
189
+ end
190
+
191
+ def eql?(other)
192
+ host.upcase == other.host.upcase && port == other.port
193
+ end
194
+ alias_method :==, :eql?
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end