ass_maintainer-info_base 0.1.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|