capricorn 2.0.1 → 2.0.2

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.
data/bin/capricornctl CHANGED
@@ -1,7 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require File.dirname(File.expand_path(__FILE__))+'/../../minigems'
4
-
5
3
  begin
6
4
  require 'capricorn-client'
7
5
  rescue LoadError
data/bin/capricornd CHANGED
@@ -5,27 +5,34 @@ src = File.expand_path('../../', __FILE__)
5
5
  rel = File.join(src, 'erlang/rel/capricorn')
6
6
  etc = File.join(root, 'etc/capricorn')
7
7
 
8
- if ARGV.size == 1 and ARGV[0] == "install"
9
- require 'fileutils'
8
+ if ARGV.size == 1
9
+ case ARGV[0]
10
10
 
11
- FileUtils.mkdir_p(File.join(root, "etc/capricorn"),
12
- :verbose => true)
13
- FileUtils.mkdir_p(File.join(root, "var/run/capricorn-machine"),
14
- :verbose => true)
15
- FileUtils.mkdir_p(File.join(root, "var/run/capricorn-cluster"),
16
- :verbose => true)
17
- FileUtils.mkdir_p(File.join(root, "var/log/sasl"),
18
- :verbose => true)
11
+ when "install"
12
+ require 'fileutils'
19
13
 
20
- FileUtils.cp(File.join(rel, 'etc/capricorn/app.config'),
21
- File.join(etc, 'app.config'),
22
- :verbose => true)
23
- FileUtils.cp(File.join(rel, 'etc/capricorn/cluster-vm.args'),
24
- File.join(etc, 'cluster-vm.args'),
25
- :verbose => true)
26
- FileUtils.cp(File.join(rel, 'etc/capricorn/machine-vm.args'),
27
- File.join(etc, 'machine-vm.args'),
28
- :verbose => true)
14
+ FileUtils.mkdir_p(File.join(root, "etc/capricorn"),
15
+ :verbose => true)
16
+ FileUtils.mkdir_p(File.join(root, "var/run/capricorn-machine"),
17
+ :verbose => true)
18
+ FileUtils.mkdir_p(File.join(root, "var/run/capricorn-cluster"),
19
+ :verbose => true)
20
+ FileUtils.mkdir_p(File.join(root, "var/log/sasl"),
21
+ :verbose => true)
22
+
23
+ FileUtils.cp(File.join(rel, 'etc/capricorn/app.config'),
24
+ File.join(etc, 'app.config'),
25
+ :verbose => true)
26
+ FileUtils.cp(File.join(rel, 'etc/capricorn/cluster-vm.args'),
27
+ File.join(etc, 'cluster-vm.args'),
28
+ :verbose => true)
29
+ FileUtils.cp(File.join(rel, 'etc/capricorn/machine-vm.args'),
30
+ File.join(etc, 'machine-vm.args'),
31
+ :verbose => true)
32
+ when "tail"
33
+ exec("tail", "-n", "0", "-f", File.join(root, "var/log/capricorn.log"))
34
+
35
+ end
29
36
  else
30
37
  exec(File.join(rel, 'bin/capricornd'), root, *ARGV)
31
38
  end
@@ -27,6 +27,7 @@
27
27
  cap_external_apps_api,
28
28
  cap_external_gems_api,
29
29
  cap_external_machines_api,
30
+ cap_external_runtime_api,
30
31
  cap_gem_utils,
31
32
  cap_internal_api,
32
33
  cap_internal_apps_api,
@@ -34,6 +35,7 @@
34
35
  cap_machine,
35
36
  cap_machine_apps,
36
37
  cap_machine_apps_sup,
38
+ cap_runtime,
37
39
  cap_sup,
38
40
  cap_util
39
41
  ]},
@@ -51,6 +53,6 @@
51
53
  cap_secondary_services,
52
54
  cap_sup
53
55
  ]},
54
- {applications, [kernel, stdlib, sasl, inets, bertio, bertrpc, gcd, emq]},
56
+ {applications, [kernel, stdlib, sasl, inets, bertio, bertrpc, emq]},
55
57
  {mod, {capricorn_app, []}}
56
58
  ]}.
@@ -31,6 +31,9 @@ init(Services) ->
31
31
 
32
32
 
33
33
 
34
+ handle_call({runtime, F, A, I}, From, State) ->
35
+ cap_external_runtime_api:handle_call({F, A, I}, From, State);
36
+
34
37
  handle_call({machines, F, A, I}, From, State) ->
35
38
  cap_external_machines_api:handle_call({F, A, I}, From, State);
36
39
 
@@ -51,6 +54,9 @@ handle_call({M, F, A, I}, From, State) ->
51
54
 
52
55
 
53
56
 
57
+ handle_cast({runtime, F, A, I}, State) ->
58
+ cap_external_runtime_api:handle_cast({F, A, I}, State);
59
+
54
60
  handle_cast({machines, F, A, I}, State) ->
55
61
  cap_external_machines_api:handle_cast({F, A, I}, State);
56
62
 
@@ -0,0 +1,49 @@
1
+ -module(cap_external_runtime_api).
2
+ -export([handle_call/3, handle_cast/2]).
3
+
4
+
5
+
6
+ handle_call({nodes,
7
+ _, _},
8
+ _From, State) ->
9
+ Nodes = [atom_to_list(Node) || Node <- nodes()],
10
+ Machines = [list_to_atom(Node) || Node <- Nodes, string:substr(Node, 1, 8) == "machine-"],
11
+ {reply, [node() | Machines], State};
12
+
13
+
14
+
15
+ handle_call({selfupdate, [RawNode], _}, _From, State) ->
16
+ try
17
+ Node =
18
+ case RawNode of
19
+ RawNode when is_atom(RawNode) -> RawNode;
20
+ RawNode when is_list(RawNode) -> list_to_atom(RawNode);
21
+ RawNode when is_binary(RawNode) -> list_to_atom(binary_to_list(RawNode))
22
+ end,
23
+ {reply, cap_runtime:selfupdate(Node), State}
24
+ catch
25
+ throw:T -> {reply, {error, T}, State}
26
+ end;
27
+
28
+
29
+
30
+ handle_call({reboot, [RawNode], _}, _From, State) ->
31
+ try
32
+ Node =
33
+ case RawNode of
34
+ RawNode when is_atom(RawNode) -> RawNode;
35
+ RawNode when is_list(RawNode) -> list_to_atom(RawNode);
36
+ RawNode when is_binary(RawNode) -> list_to_atom(binary_to_list(RawNode))
37
+ end,
38
+ {reply, cap_runtime:reboot(Node), State}
39
+ catch
40
+ throw:T -> {reply, {error, T}, State}
41
+ end.
42
+
43
+
44
+
45
+ handle_cast({_, _, _},
46
+ State) ->
47
+ {noreply, State}.
48
+
49
+
@@ -0,0 +1,65 @@
1
+ -module(cap_runtime).
2
+ -include("capricorn.hrl").
3
+ -behaviour(gen_server).
4
+
5
+ -export([reboot/1, selfupdate/1, start_link/1]).
6
+ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
7
+
8
+
9
+
10
+ reboot(Node) ->
11
+ gen_server:call({cap_runtime, Node}, reboot).
12
+
13
+
14
+
15
+ selfupdate(Node) ->
16
+ gen_server:call({cap_runtime, Node}, selfupdate).
17
+
18
+
19
+
20
+ start_link(NodeType) ->
21
+ gen_server:start_link({local, cap_runtime}, ?MODULE, NodeType, []).
22
+
23
+
24
+
25
+ init(NodeType) ->
26
+ {ok, NodeType}.
27
+
28
+
29
+
30
+ handle_call(selfupdate, From, NodeType) ->
31
+ Install = os:cmd("gem update capricorn"),
32
+ init:reboot(),
33
+ gen_server:reply(From, list_to_binary(Install)),
34
+ {noreply, NodeType};
35
+
36
+
37
+
38
+ handle_call(reboot, From, NodeType) ->
39
+ ?LOG_DEBUG("rebooting", []),
40
+ init:reboot(),
41
+ gen_server:reply(From, ok),
42
+ {noreply, NodeType}.
43
+
44
+
45
+
46
+ handle_cast(abcdefg, State) ->
47
+ {noreply, State}.
48
+
49
+
50
+
51
+ handle_info({_, {data, Msg}}, State) ->
52
+ ?LOG_DEBUG("reboot> ~s", [Msg]),
53
+ {noreply, State}.
54
+
55
+
56
+
57
+ terminate(_Reason, _State) ->
58
+ ok.
59
+
60
+
61
+
62
+ code_change(_OldVsn, State, _Extra) ->
63
+ {ok, State}.
64
+
65
+
@@ -24,9 +24,9 @@
24
24
  %% supervisor callback
25
25
  -export([init/1]).
26
26
 
27
-
27
+
28
28
  -define(SERVER, ?MODULE).
29
-
29
+
30
30
  %%
31
31
  %% Operation & Maintenance API
32
32
  %%
@@ -56,14 +56,14 @@ restart_core_server(machine) ->
56
56
 
57
57
  start_server(NodeType) ->
58
58
  LogLevel = cap_config:get(log, level, info),
59
-
59
+
60
60
  % announce startup
61
61
  io:format("Capricorn (LogLevel=~s, Node=~s, Type=~s) is starting.~n", [
62
62
  LogLevel,
63
63
  atom_to_list(node()),
64
64
  atom_to_list(NodeType)
65
65
  ]),
66
-
66
+
67
67
  BaseChildSpecs =
68
68
  {{one_for_all, 10, 3600},[
69
69
  {cap_primary_services,
@@ -79,16 +79,16 @@ start_server(NodeType) ->
79
79
  supervisor,
80
80
  [cap_sup]}
81
81
  ]},
82
-
82
+
83
83
  {ok, Pid} = supervisor:start_link({local, cap_sup}, cap_sup, BaseChildSpecs),
84
-
84
+
85
85
  io:format("Capricorn has started. Time to relax.~n"),
86
-
86
+
87
87
  {ok, Pid}.
88
88
 
89
89
  start_primary_services(cluster) ->
90
90
  ExternalApi = cap_config:get(cluster, api),
91
-
91
+
92
92
  supervisor:start_link({local, cap_primary_services}, cap_sup,
93
93
  {{one_for_one, 10, 3600},[
94
94
  {cap_log,
@@ -120,11 +120,17 @@ start_primary_services(cluster) ->
120
120
  permanent,
121
121
  1000,
122
122
  worker,
123
- [cap_external_api]}
123
+ [cap_external_api]},
124
+ {cap_runtime,
125
+ {cap_runtime, start_link, ["cluster"]},
126
+ permanent,
127
+ brutal_kill,
128
+ worker,
129
+ [cap_runtime]}
124
130
  ]});
125
131
  start_primary_services(machine) ->
126
132
  InternalApi = cap_config:get(machine, api),
127
-
133
+
128
134
  supervisor:start_link({local, cap_primary_services}, cap_sup,
129
135
  {{one_for_one, 10, 3600},[
130
136
  {cap_log,
@@ -162,7 +168,13 @@ start_primary_services(machine) ->
162
168
  permanent,
163
169
  infinity,
164
170
  supervisor,
165
- [cap_machine_apps_sup]}
171
+ [cap_machine_apps_sup]},
172
+ {cap_runtime,
173
+ {cap_runtime, start_link, ["machine"]},
174
+ permanent,
175
+ brutal_kill,
176
+ worker,
177
+ [cap_runtime]}
166
178
  ]}).
167
179
 
168
180
  start_secondary_services(NodeType) ->
@@ -177,7 +189,7 @@ start_secondary_services(NodeType) ->
177
189
  end
178
190
  || {Name, {Module, Fun, Args}}
179
191
  <- cap_config:get(NodeType, daemons, [])],
180
-
192
+
181
193
  EventHandlerSpecs = [
182
194
  begin
183
195
  {Name,
@@ -189,7 +201,7 @@ start_secondary_services(NodeType) ->
189
201
  end
190
202
  || {Name, {Module, Args}}
191
203
  <- cap_config:get(NodeType, event_handlers, [])],
192
-
204
+
193
205
  supervisor:start_link({local, cap_secondary_services}, cap_sup,
194
206
  {{one_for_one, 10, 3600}, DaemonChildSpecs++EventHandlerSpecs}).
195
207
 
data/erlang/rebar.config CHANGED
@@ -2,7 +2,6 @@
2
2
  "lib/bert",
3
3
  "lib/bertio",
4
4
  "lib/bertrpc",
5
- "lib/gcd",
6
5
  "lib/emq",
7
6
  "lib/capricorn",
8
7
  "rel"
@@ -7,7 +7,7 @@
7
7
 
8
8
  ## Heartbeat management; auto-restarts VM if it dies or becomes unresponsive
9
9
  ## (Disabled by default..use with caution!)
10
- ##-heart
10
+ -heart
11
11
 
12
12
  ## Enable kernel poll and a few async threads
13
13
  +K true
@@ -16,6 +16,6 @@
16
16
  ## Increase number of concurrent ports/sockets
17
17
  -env ERL_MAX_PORTS 4096
18
18
 
19
- ## Tweak GC to run more often
19
+ ## Tweak GC to run more often
20
20
  -env ERL_FULLSWEEP_AFTER 10
21
21
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  ## Heartbeat management; auto-restarts VM if it dies or becomes unresponsive
9
9
  ## (Disabled by default..use with caution!)
10
- ##-heart
10
+ -heart
11
11
 
12
12
  ## Enable kernel poll and a few async threads
13
13
  +K true
@@ -16,6 +16,6 @@
16
16
  ## Increase number of concurrent ports/sockets
17
17
  -env ERL_MAX_PORTS 4096
18
18
 
19
- ## Tweak GC to run more often
19
+ ## Tweak GC to run more often
20
20
  -env ERL_FULLSWEEP_AFTER 10
21
21
 
@@ -8,7 +8,6 @@
8
8
  bert,
9
9
  bertio,
10
10
  bertrpc,
11
- gcd,
12
11
  emq,
13
12
  capricorn
14
13
  ]},
@@ -26,7 +25,6 @@
26
25
  {app, bert, [{incl_cond, include}]},
27
26
  {app, bertio, [{incl_cond, include}]},
28
27
  {app, bertrpc, [{incl_cond, include}]},
29
- {app, gcd, [{incl_cond, include}]},
30
28
  {app, emq, [{incl_cond, include}]},
31
29
  {app, capricorn, [{incl_cond, include}]},
32
30
  {app, sasl, [{incl_cond, include}]}
@@ -38,6 +36,6 @@
38
36
  "var/run/capricorn-cluster",
39
37
  "var/log/sasl"
40
38
  ]},
41
-
39
+
42
40
  {overlay, "overlay"}
43
41
  ]}.
@@ -4,29 +4,29 @@ module Capricorn
4
4
  require 'bertrpc'
5
5
  require 'highline'
6
6
  require 'fileutils'
7
-
7
+
8
8
  require 'capricorn-client/helpers'
9
-
9
+
10
10
  module CLI
11
11
  require 'capricorn-client/cli/applications'
12
12
  require 'capricorn-client/cli/gems'
13
13
  require 'capricorn-client/cli/machines'
14
14
  end
15
-
15
+
16
16
  module Runner
17
-
17
+
18
18
  HELP = <<-EOH
19
19
  Topics:
20
20
  CLUSTER applications
21
21
  # manage applications
22
-
22
+
23
23
  CLUSTER gems
24
24
  # manage gems
25
-
25
+
26
26
  CLUSTER machines
27
27
  # manage machines
28
28
  EOH
29
-
29
+
30
30
  DEFAULT_CONFIG = <<-EOH
31
31
  cluster_name:
32
32
  host: localhost
@@ -34,20 +34,20 @@ cluster_name:
34
34
  username: dummy
35
35
  password: dummy
36
36
  EOH
37
-
37
+
38
38
  def start
39
39
  cluster_name = ARGV.shift
40
40
  unless cluster_name
41
41
  help
42
42
  exit 1
43
43
  end
44
-
44
+
45
45
  @cluster = config[cluster_name]
46
46
  unless @cluster
47
47
  puts "I don't know this cluster"
48
48
  exit 1
49
49
  end
50
-
50
+
51
51
  case ARGV.shift
52
52
  when 'applications'
53
53
  Capricorn::CLI::Applications.start
@@ -59,15 +59,15 @@ EOH
59
59
  help
60
60
  end
61
61
  end
62
-
62
+
63
63
  def help
64
64
  puts HELP
65
65
  end
66
-
66
+
67
67
  def cluster
68
68
  @cluster
69
69
  end
70
-
70
+
71
71
  def config
72
72
  @config ||= begin
73
73
  config_path = File.expand_path('~/.capricorn/config.yml')
@@ -80,7 +80,7 @@ EOH
80
80
  YAML.load_file(config_path)
81
81
  end
82
82
  end
83
-
83
+
84
84
  extend self
85
85
  end
86
86
  end
@@ -1,9 +1,21 @@
1
1
  class Capricorn::CLI::Machines < Thor
2
2
  include Capricorn::Helpers
3
-
3
+
4
4
  desc "list", "list all machines"
5
5
  def list
6
6
  ui.table("Machines", self.machines)
7
7
  end
8
-
8
+
9
+ desc "reboot [NODE]", "reboot a node"
10
+ def reboot(node=nil)
11
+ node ||= select_node
12
+ puts client.call.runtime.reboot(node.to_sym)
13
+ end
14
+
15
+ desc "selfupdate [NODE]", "update a node"
16
+ def selfupdate(node=nil)
17
+ node ||= select_node
18
+ puts client.call.runtime.selfupdate(node.to_sym)
19
+ end
20
+
9
21
  end
@@ -1,5 +1,5 @@
1
1
  module Capricorn::Helpers
2
-
2
+
3
3
  def select_machine
4
4
  if self.machines.size > 1
5
5
  ui.choose(*self.machines)
@@ -10,16 +10,27 @@ module Capricorn::Helpers
10
10
  exit(1)
11
11
  end
12
12
  end
13
-
13
+
14
+ def select_node
15
+ if self.nodes.size > 1
16
+ ui.choose(*self.nodes)
17
+ elsif self.nodes.size == 1 and ui.agree("Use nodes #{self.nodes.first}? ")
18
+ self.nodes.first
19
+ else
20
+ puts ui.color('No nodes found!!!', :red)
21
+ exit(1)
22
+ end
23
+ end
24
+
14
25
  def select_application
15
26
  machine = select_machine
16
-
27
+
17
28
  apps = client.call.applications.all(machine.to_sym).last || []
18
29
  apps.collect! do |app|
19
30
  app[1]
20
31
  end
21
32
  apps.flatten!
22
-
33
+
23
34
  if apps.size > 1
24
35
  [machine, ui.choose(*apps)]
25
36
  elsif apps.size == 1 and ui.agree("Use application #{apps.first}? ")
@@ -29,20 +40,26 @@ module Capricorn::Helpers
29
40
  exit(1)
30
41
  end
31
42
  end
32
-
43
+
33
44
  def machines
34
45
  @machines ||= (client.call.machines.all || []).collect do |machine|
35
46
  machine.to_s
36
47
  end
37
48
  end
38
-
49
+
50
+ def nodes
51
+ @nodes ||= (client.call.runtime.nodes || []).collect do |node|
52
+ node.to_s
53
+ end
54
+ end
55
+
39
56
  def client
40
57
  cluster = Capricorn::Runner.cluster
41
58
  host = (cluster['host'] || 'localhost').to_s
42
59
  port = (cluster['port'] || 3457).to_i
43
60
  @client ||= BERTRPC::Service.new(host, port)
44
61
  end
45
-
62
+
46
63
  def ui
47
64
  @ui ||= begin
48
65
  @ui = HighLine.new
@@ -50,13 +67,13 @@ module Capricorn::Helpers
50
67
  @ui
51
68
  end
52
69
  end
53
-
70
+
54
71
  module UI
55
-
72
+
56
73
  def table(headers, items, mode=:rows, option=nil)
57
74
  headers = [headers].flatten.collect { |h| color(h, :green) }
58
75
  @output.puts list(headers+items, mode, option)
59
76
  end
60
-
77
+
61
78
  end
62
79
  end
@@ -1,5 +1,5 @@
1
1
  module Capricorn
2
2
 
3
- VERSION = '2.0.1'
3
+ VERSION = '2.0.2'
4
4
 
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capricorn
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 11
5
5
  prerelease: false
6
6
  segments:
7
7
  - 2
8
8
  - 0
9
- - 1
10
- version: 2.0.1
9
+ - 2
10
+ version: 2.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Simon Menke
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-06-01 00:00:00 +02:00
18
+ date: 2010-06-02 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -26,12 +26,12 @@ dependencies:
26
26
  requirements:
27
27
  - - "="
28
28
  - !ruby/object:Gem::Version
29
- hash: 27
29
+ hash: 25
30
30
  segments:
31
31
  - 1
32
32
  - 3
33
- - 0
34
- version: 1.3.0
33
+ - 1
34
+ version: 1.3.1
35
35
  type: :runtime
36
36
  version_requirements: *id001
37
37
  - !ruby/object:Gem::Dependency
@@ -169,6 +169,7 @@ files:
169
169
  - erlang/lib/capricorn/src/cap_external_apps_api.erl
170
170
  - erlang/lib/capricorn/src/cap_external_gems_api.erl
171
171
  - erlang/lib/capricorn/src/cap_external_machines_api.erl
172
+ - erlang/lib/capricorn/src/cap_external_runtime_api.erl
172
173
  - erlang/lib/capricorn/src/cap_gem_utils.erl
173
174
  - erlang/lib/capricorn/src/cap_internal_api.erl
174
175
  - erlang/lib/capricorn/src/cap_internal_apps_api.erl
@@ -176,6 +177,7 @@ files:
176
177
  - erlang/lib/capricorn/src/cap_machine.erl
177
178
  - erlang/lib/capricorn/src/cap_machine_apps.erl
178
179
  - erlang/lib/capricorn/src/cap_machine_apps_sup.erl
180
+ - erlang/lib/capricorn/src/cap_runtime.erl
179
181
  - erlang/lib/capricorn/src/cap_sup.erl
180
182
  - erlang/lib/capricorn/src/cap_util.erl
181
183
  - erlang/lib/capricorn/src/capricorn.erl
@@ -187,15 +189,6 @@ files:
187
189
  - erlang/lib/emq/src/emq_queue.erl
188
190
  - erlang/lib/emq/src/emq_status.erl
189
191
  - erlang/lib/emq/src/emq_sup.erl
190
- - erlang/lib/gcd/ebin/gcd.app
191
- - erlang/lib/gcd/include/gcd.hrl
192
- - erlang/lib/gcd/rebar.config
193
- - erlang/lib/gcd/src/gcd.erl
194
- - erlang/lib/gcd/src/gcd_app.erl
195
- - erlang/lib/gcd/src/gcd_event.erl
196
- - erlang/lib/gcd/src/gcd_server.erl
197
- - erlang/lib/gcd/src/gcd_srv.erl
198
- - erlang/lib/gcd/src/gcd_sup.erl
199
192
  - erlang/rebar
200
193
  - erlang/rebar.config
201
194
  - erlang/rel/overlay/bin/capricornd
@@ -1,18 +0,0 @@
1
- {application, gcd, [
2
- {description, "Grand Central Dispatch"},
3
- {vsn, "0.1"},
4
- {modules, [
5
- gcd_app,
6
- gcd_sup,
7
- gcd_srv,
8
- gcd_event,
9
- gcd_server,
10
- gcd
11
- ]},
12
- {registered, [
13
- gcd_srv,
14
- gcd_sup
15
- ]},
16
- {applications, [kernel, stdlib]},
17
- {mod, {gcd_app, []}}
18
- ]}.
@@ -1,5 +0,0 @@
1
-
2
- -record(state, {local,remote,nodes,monitors}).
3
- -record(service, {pid,node,location,name,description}).
4
- -record(node, {name}).
5
- -record(monitor, {ref,pid,pattern}).
@@ -1,3 +0,0 @@
1
- {cover_enabled, true}.
2
- {erl_opts, [debug_info, fail_on_warning, {i, ".."}]}.
3
- {lib_dirs, [".."]}.
@@ -1,51 +0,0 @@
1
- -module(gcd).
2
- -include("gcd.hrl").
3
-
4
- -export([start/0, stop/0]).
5
-
6
- -export([connect/1]).
7
- -export([register/2, unregister/0]).
8
- -export([monitor/1, demonitor/1]).
9
- -export([match_object/1, foldl/2]).
10
-
11
-
12
- %%% Application API
13
- start() ->
14
- application:start(gcd).
15
-
16
- stop() ->
17
- application:stop(gcd).
18
-
19
-
20
- %%% External API
21
- connect(Node) when is_atom(Node) ->
22
- connect([Node]);
23
- connect([]) -> ok;
24
- connect([Node|Rest]) ->
25
- net_adm:ping(Node),
26
- connect(Rest).
27
-
28
- register(Name, Description) ->
29
- Info = erlang:process_info(self()),
30
- RegisteredName = proplists:get_value(registered_name, Info),
31
- Location =
32
- case RegisteredName of
33
- undefined -> self();
34
- _Else -> {RegisteredName, node()}
35
- end,
36
- gen_server:call(gcd_srv, {register, self(), Name, node(), Location, Description}).
37
-
38
- unregister() ->
39
- gen_server:call(gcd_srv, {unregister, self()}).
40
-
41
- monitor(Pattern) ->
42
- gen_server:call(gcd_srv, {monitor, self(), Pattern}).
43
-
44
- demonitor(Ref) ->
45
- gen_server:call(gcd_srv, {demonitor, Ref}).
46
-
47
- foldl(Fun, Acc) ->
48
- gen_server:call(gcd_srv, {foldl, Fun, Acc}).
49
-
50
- match_object(Pattern) ->
51
- gen_server:call(gcd_srv, {match_object, Pattern}).
@@ -1,13 +0,0 @@
1
- -module(gcd_app).
2
- -behaviour(application).
3
-
4
- -export([start/2, stop/1]).
5
-
6
- start(_StartType, _StartArgs) ->
7
- case gcd_sup:start_link() of
8
- {ok, Pid} -> {ok, Pid};
9
- Error -> Error
10
- end.
11
-
12
- stop(_State) ->
13
- ok.
@@ -1,39 +0,0 @@
1
- -module(gcd_event).
2
- -include("gcd.hrl").
3
-
4
-
5
- -export([notify/2, sync_notify/2]).
6
- -export([call/3, call/4]).
7
-
8
-
9
- notify(Pattern, Message) ->
10
- [begin
11
- #service{location=Location} = Service,
12
- gen_event:notify(Location, Message)
13
- end ||
14
- Service <- gcd:match_object(Pattern)].
15
-
16
-
17
- sync_notify(Pattern, Message) ->
18
- [begin
19
- #service{location=Location} = Service,
20
- gen_event:sync_notify(Location, Message)
21
- end ||
22
- Service <- gcd:match_object(Pattern)].
23
-
24
-
25
- call(Pattern, Handler, Message) ->
26
- [begin
27
- #service{location=Location} = Service,
28
- gen_event:call(Location, Handler, Message)
29
- end ||
30
- Service <- gcd:match_object(Pattern)].
31
-
32
-
33
- call(Pattern, Handler, Message, Timeout) ->
34
- [begin
35
- #service{location=Location} = Service,
36
- gen_event:call(Location, Handler, Message, Timeout)
37
- end ||
38
- Service <- gcd:match_object(Pattern)].
39
-
@@ -1,30 +0,0 @@
1
- -module(gcd_server).
2
- -include("gcd.hrl").
3
-
4
-
5
- -export([cast/2]).
6
- -export([call/2, call/3]).
7
-
8
-
9
- call(Pattern, Message) ->
10
- [begin
11
- #service{location=Location} = Service,
12
- gen_server:call(Location, Message)
13
- end ||
14
- Service <- gcd:match_object(Pattern)].
15
-
16
-
17
- call(Pattern, Message, Timeout) ->
18
- [begin
19
- #service{location=Location} = Service,
20
- gen_server:call(Location, Message, Timeout)
21
- end ||
22
- Service <- gcd:match_object(Pattern)].
23
-
24
-
25
- cast(Pattern, Message) ->
26
- [begin
27
- #service{location=Location} = Service,
28
- gen_server:cast(Location, Message)
29
- end ||
30
- Service <- gcd:match_object(Pattern)].
@@ -1,186 +0,0 @@
1
- -module(gcd_srv).
2
- -behaviour(gen_server).
3
- -include("gcd.hrl").
4
-
5
- -export([start_link/0]).
6
- -export([init/1, handle_call/3, handle_cast/2,
7
- handle_info/2, terminate/2, code_change/3]).
8
-
9
- -define(L(State), State#state.local).
10
- -define(R(State), State#state.remote).
11
- -define(N(State), State#state.nodes).
12
- -define(M(State), State#state.monitors).
13
-
14
-
15
- %%% Start the server
16
- start_link() ->
17
- gen_server:start_link({local, gcd_srv}, ?MODULE, [], []).
18
-
19
-
20
- %%% Initialize the server
21
- init([]) ->
22
- net_kernel:monitor_nodes(true),
23
- Local = ets:new(gcd_srv_local, [set,private,{keypos,2}]),
24
- Remote = ets:new(gcd_srv_remote, [set,private,{keypos,4}]),
25
- Nodes = ets:new(gcd_srv_nodes, [set,private,{keypos,2}]),
26
- Monitors = ets:new(gcd_srv_monitors, [set,private,{keypos,2}]),
27
- {ok, #state{local=Local,remote=Remote,nodes=Nodes,monitors=Monitors}}.
28
-
29
-
30
- %%% Handle call messages
31
- handle_call({foldl, Fun, Acc1}, _From, State) ->
32
- Acc2 = ets:foldl(Fun, Acc1, ?L(State)),
33
- Acc3 = ets:foldl(Fun, Acc2, ?R(State)),
34
- {reply, Acc3, State};
35
-
36
- handle_call({match_object, Pattern}, _From, State) ->
37
- Services1 = ets:match_object(?L(State), Pattern),
38
- Services2 = ets:match_object(?R(State), Pattern),
39
- {reply, Services1 ++ Services2, State};
40
-
41
- handle_call({register, Pid, Name, Node, Location, Description}, _From, State) ->
42
- Service = #service{node=Node, location=Location, pid=Pid, name=Name, description=Description},
43
- case ets:insert_new(?L(State), Service) of
44
- true ->
45
- erlang:monitor(process, Pid),
46
- gen_server:cast(self(), {serviceup, Service}),
47
- {reply, ok, State};
48
- false ->
49
- {reply, {error, already_registerd}, State}
50
- end;
51
-
52
- handle_call({unregister, Pid}, _From, State) ->
53
- case ets:lookup(?L(State), Pid) of
54
- [Service] ->
55
- gen_server:cast(self(), {servicedown, Service}),
56
- ets:delete(?L(State), Pid);
57
- _ -> ok
58
- end,
59
- {reply, ok, State};
60
-
61
- handle_call({monitor, Pid, Pattern}, _From, State) ->
62
- Monitor = #monitor{ref=erlang:make_ref(), pid=Pid, pattern=Pattern},
63
- case ets:insert_new(?M(State), Monitor) of
64
- true ->
65
- erlang:monitor(process, Pid),
66
- {reply, Monitor#monitor.ref, State};
67
- false ->
68
- {reply, {error, already_registerd}, State}
69
- end;
70
-
71
- handle_call({demonitor, Ref}, _From, State) ->
72
- ets:delete(?M(State), Ref),
73
- {reply, ok, State};
74
-
75
- handle_call(_Request, _From, State) ->
76
- {reply, ok, State}.
77
-
78
-
79
- %%% Handle cast messages
80
- handle_cast({info, Node, Nodes, Services}, State) ->
81
- ets:insert(?N(State), #node{name=Node}),
82
- ets:insert(?R(State), Services),
83
- [net_adm:ping(Node1) || Node1 <- Nodes],
84
- [gen_server:cast(self(), {serviceup, Service}) || Service <- Services],
85
- {noreply, State};
86
-
87
- handle_cast({serviceup, Service}, State) ->
88
- case Service#service.pid of
89
- remote ->
90
- ets:insert(?R(State), Service);
91
- _Pid ->
92
- ets:insert(?L(State), Service),
93
- ets:foldl(fun(#node{name=Node}, _) ->
94
- gen_server:cast({gcd_srv, Node}, {serviceup, Service#service{pid=remote}})
95
- end, [], ?N(State))
96
- end,
97
-
98
- ets:foldl(fun(#monitor{pattern=Pattern,pid=Pid,ref=Ref}, _) ->
99
- case ets:test_ms(Service, [{Pattern,[],[true]}]) of
100
- {ok, true} ->
101
- Pid ! {serviceup, Ref, Service};
102
- _Else -> ignore
103
- end
104
- end, [], ?M(State)),
105
-
106
- {noreply, State};
107
-
108
- handle_cast({servicedown, Service}, State) ->
109
- case Service#service.pid of
110
- remote ->
111
- ets:delete(?R(State), Service#service.location);
112
- _Pid ->
113
- ets:delete(?L(State), Service#service.pid),
114
- ets:foldl(fun(#node{name=Node}, _) ->
115
- gen_server:cast({gcd_srv, Node}, {servicedown, Service#service{pid=remote}})
116
- end, [], ?N(State))
117
- end,
118
-
119
- ets:foldl(fun(#monitor{pattern=Pattern,pid=Pid,ref=Ref}, _) ->
120
- case ets:test_ms(Service, [{Pattern,[],[true]}]) of
121
- {ok, true} ->
122
- Pid ! {servicedown, Ref, Service};
123
- _Else -> ignore
124
- end
125
- end, [], ?M(State)),
126
-
127
- {noreply, State};
128
-
129
- handle_cast(stop, State) ->
130
- {stop, normal, State};
131
-
132
- handle_cast(_Msg, State) ->
133
- {noreply, State}.
134
-
135
-
136
- %%% Handle generic messages
137
- handle_info({'DOWN', _Ref, process, Pid, _Reason}, State) ->
138
- case ets:lookup(?L(State), Pid) of
139
- [Service] ->
140
- gen_server:cast(self(), {servicedown, Service}),
141
- ets:delete(?L(State), Pid);
142
- _ -> ok
143
- end,
144
- Monitors = ets:foldl(fun
145
- (#monitor{ref=Ref,pid=Pid1}, Acc) when Pid1 == Pid ->
146
- [Ref|Acc];
147
- (_Else, Acc) -> Acc
148
- end, [], ?M(State)),
149
- [ets:delete(?M(State), Ref) || Ref <- Monitors],
150
- {noreply, State};
151
-
152
- handle_info({nodeup, Node}, State) ->
153
- gen_server:cast({gcd_srv, Node}, {info, node(),
154
- ets:foldl(fun(#node{name=N}, Acc) -> [N|Acc] end, [], ?N(State)),
155
- ets:foldl(fun(#service{}=S, Acc) -> [S#service{pid=remote}|Acc] end, [], ?L(State))
156
- }),
157
-
158
- {noreply, State};
159
-
160
- handle_info({nodedown, Node}, State) ->
161
- ets:delete(?N(State), Node),
162
-
163
- Keys = ets:foldl(fun
164
- (#service{node=Node1,location=L}=Service, Acc) when Node1 == Node->
165
- gen_server:cast(self(), {servicedown, Service}),
166
- [L|Acc];
167
- (_Else, Acc) -> Acc
168
- end, [], ?R(State)),
169
- [ets:delete(?R(State), Key) || Key <- Keys],
170
-
171
- {noreply, State};
172
-
173
- handle_info(_Info, State) ->
174
- {noreply, State}.
175
-
176
- %%% Before stopping the server
177
- terminate(_Reason, State) ->
178
- ets:delete(?L(State)),
179
- ets:delete(?R(State)),
180
- ets:delete(?N(State)),
181
- ets:delete(?M(State)),
182
- ok.
183
-
184
- %%% Code Changes
185
- code_change(_OldVsn, State, _Extra) ->
186
- {ok, State}.
@@ -1,18 +0,0 @@
1
- -module(gcd_sup).
2
- -behaviour(supervisor).
3
-
4
- -export([start_link/0]).
5
- -export([init/1]).
6
-
7
- start_link() ->
8
- supervisor:start_link({local, gcd_sup}, ?MODULE, []).
9
-
10
- init([]) ->
11
- {ok, {{one_for_one, 10, 3600},[
12
- {gcd_srv,
13
- {gcd_srv, start_link, []},
14
- permanent,
15
- brutal_kill,
16
- worker,
17
- [gcd_srv]}
18
- ]}}.