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.
- checksums.yaml +4 -4
- data/.gitignore +0 -0
- data/.simplecov +0 -0
- data/.travis.yml +0 -0
- data/Gemfile +0 -0
- data/LICENSE.txt +0 -0
- data/README.md +94 -15
- data/Rakefile +0 -0
- data/ass_maintainer-info_base.gemspec +4 -1
- data/bin/runsrv +241 -0
- data/examples/describe_infobase.rb +0 -0
- data/lib/ass_maintainer/info_base.rb +79 -73
- data/lib/ass_maintainer/info_base/cfg.rb +14 -10
- data/lib/ass_maintainer/info_base/config.rb +0 -0
- data/lib/ass_maintainer/info_base/default_maker.rb +0 -0
- data/lib/ass_maintainer/info_base/file_ib.rb +24 -41
- data/lib/ass_maintainer/info_base/interfaces.rb +49 -20
- data/lib/ass_maintainer/info_base/server_ib.rb +257 -55
- data/lib/ass_maintainer/info_base/server_ib/enterprise_servers.rb +80 -0
- data/lib/ass_maintainer/info_base/server_ib/enterprise_servers/cluster.rb +114 -0
- data/lib/ass_maintainer/info_base/server_ib/enterprise_servers/server_agent.rb +91 -0
- data/lib/ass_maintainer/info_base/server_ib/enterprise_servers/support.rb +200 -0
- data/lib/ass_maintainer/info_base/server_ib/enterprise_servers/wp_connection.rb +198 -0
- data/lib/ass_maintainer/info_base/version.rb +1 -1
- metadata +72 -26
- data/lib/ass_maintainer/info_base/server_ib/helpers.rb +0 -50
@@ -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
|