capricorn 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
- ]}}.