~ubuntu-branches/debian/squeeze/erlang/squeeze

« back to all changes in this revision

Viewing changes to lib/appmon/src/appmon_info.erl

  • Committer: Bazaar Package Importer
  • Author(s): Erlang Packagers, Sergei Golovan
  • Date: 2006-12-03 17:07:44 UTC
  • mfrom: (2.1.11 feisty)
  • Revision ID: james.westby@ubuntu.com-20061203170744-rghjwupacqlzs6kv
Tags: 1:11.b.2-4
[ Sergei Golovan ]
Fixed erlang-base and erlang-base-hipe prerm scripts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
93
93
%%      processes that are left.
94
94
%%
95
95
%%----------------------------------------------------------------------
96
 
 
97
 
 
98
 
 
99
96
-module(appmon_info).
100
 
%% For CC that doesn't understand fnutts.
101
 
 
102
 
-export([start_link/3, start_link2/3, stop/0]).
103
 
 
104
 
-export([app_ctrl/2, app_ctrl/4,
105
 
         load/2, load/4,
106
 
         app/3, app/4,
107
 
         set_opts/1, set_opts/2,
108
 
         pinfo/3, pinfo/4,
109
 
         register_client/2,
110
 
         status/0]).
111
 
 
112
 
-import(lists, [foldr/3]).
113
 
 
114
 
%% gen server stuff
115
97
-behaviour(gen_server).
116
 
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]).
117
 
-export([code_change/3]).
 
98
 
 
99
%% Exported functions
 
100
-export([start_link/3, app/4, pinfo/4, load/4, app_ctrl/4]).
 
101
 
 
102
%% For internal use (RPC call)
 
103
-export([start_link2/3]).
 
104
 
 
105
%% For debugging
 
106
-export([status/0]).
 
107
 
 
108
%% gen_server callbacks
 
109
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
 
110
         terminate/2, code_change/3]).
118
111
 
119
112
 
120
113
%%----------------------------------------------------------------------
161
154
start_link2(Starter, Client, Opts) ->
162
155
    Name = {local, ?MODULE},
163
156
    Args = {Starter, Opts, Client},
164
 
    %% Check for existence because gen_server gives error when trie
165
 
    %% multiple times
166
 
    case whereis(?MODULE) of
167
 
        Pid when pid(Pid) -> 
 
157
    case gen_server:start(Name, ?MODULE, Args, []) of
 
158
        {ok, Pid} ->
 
159
            {ok, Pid};
 
160
        {error, {already_started, Pid}} -> 
168
161
            register_client(Pid, Client),
169
 
            {ok, Pid};
170
 
        _ ->
171
 
            case catch gen_server:start(Name, ?MODULE, Args, []) of
172
 
                {ok, Pid} when pid(Pid) -> {ok, Pid};
173
 
                {error, {already_started, Pid}} when pid(Pid) -> 
174
 
                    register_client(Pid, Client),
175
 
                    {ok, Pid};
176
 
                Other -> Other
177
 
            end
 
162
            {ok, Pid}
178
163
    end.
179
164
        
180
165
 
181
 
stop() ->
182
 
    ?MODULE ! stop.
183
 
 
184
 
 
185
166
%% app_ctrl
186
167
%%
187
168
%%      Monitors which applications exist on a node
188
169
%%
189
 
app_ctrl(OnOff, Opts) ->
190
 
    app_ctrl(?MODULE, nil, OnOff, Opts).
191
170
app_ctrl(Serv, Aux, OnOff, Opts) ->
192
171
    gen_server:cast(Serv, {self(), app_ctrl, Aux, OnOff, Opts}).
193
172
 
196
175
%%
197
176
%%      Monitors load on a node
198
177
%%
199
 
load(OnOff, Opts) ->
200
 
    load(?MODULE, nil, OnOff, Opts).
201
178
load(Serv, Aux, OnOff, Opts) ->
202
179
    gen_server:cast(Serv, {self(), load, Aux, OnOff, Opts}).
203
180
 
207
184
%%      Monitors one application given by name (this ends up in a
208
185
%%      process tree
209
186
%%
210
 
app(AppName, OnOff, Opts) ->
211
 
    app(?MODULE, AppName, OnOff, Opts).
212
187
app(Serv, AppName, OnOff, Opts) ->
213
188
    gen_server:cast(Serv, {self(), app, AppName, OnOff, Opts}).
214
189
 
215
 
%% set_opts
216
 
%%
217
 
%%      Set global options
218
 
%%
219
 
set_opts(Opt) ->
220
 
    set_opts(?MODULE, Opt).
221
 
set_opts(Serv, Opt) ->
222
 
    gen_server:cast(Serv, {self(), set_option, Opt}).
223
 
 
224
190
%% pinfo
225
191
%%
226
192
%%      Process or Port info
227
193
%%
228
 
pinfo(Pid, OnOff, Opt) ->
229
 
    pinfo(?MODULE, Pid, OnOff, Opt).
230
194
pinfo(Serv, Pid, OnOff, Opt) ->
231
195
    gen_server:cast(Serv, {self(), pinfo, Pid, OnOff, Opt}).
232
196
 
254
218
%%----------------------------------------------------------------------
255
219
 
256
220
init({Starter, Opts, Pid}) ->
257
 
    %%io:format("init opts: ~p, pid: ~p, ~n", [Opts, Pid]),
258
221
    link(Pid),
259
222
    process_flag(trap_exit, true),
260
223
    WorkStore = ets:new(workstore, [set, public]),
261
 
    {ok, #state{starter=Starter, opts=Opts, work=WorkStore, clients=[Pid]}}.
 
224
    {ok, #state{starter=Starter, opts=Opts, work=WorkStore,
 
225
                clients=[Pid]}}.
262
226
 
263
 
terminate(Reason, State) ->
264
 
    tell("Terminating ~p ~p~n", [?MODULE, node()], 5, State#state.opts),
 
227
terminate(_Reason, State) ->
265
228
    ets:delete(State#state.work),
266
229
    ok.
267
230
 
268
 
code_change(OldVsn, State, Extra) ->
 
231
code_change(_OldVsn, State, _Extra) ->
269
232
    {ok, State}.
270
233
 
271
234
 
275
238
%%
276
239
%%----------------------------------------------------------------------
277
240
 
278
 
handle_call(stop, From, State) ->
279
 
    {reply, stop, normal, State};
280
 
handle_call({register_client, Pid}, From, State) ->
281
 
%%    io:format("ns add client: Pid: ~p, List: ~p~n",
282
 
%%            [Pid, State#state.clients]),
 
241
handle_call({register_client, Pid}, _From, State) ->
283
242
    NewState = case lists:member(Pid, State#state.clients) of
284
243
                   true -> State;
285
244
                   _ -> State#state{clients=[Pid | State#state.clients]}
286
245
               end,
287
246
    {reply, ok, NewState};
288
 
handle_call(Other, From, State) ->
289
 
    tell("~p got unknown call: ~p~n", [?MODULE, Other], 1, State#state.opts),
 
247
handle_call(_Other, _From, State) ->
290
248
    {reply, ok, State}.
291
249
 
292
250
%%----------------------------------------------------------------------
295
253
%%
296
254
%%----------------------------------------------------------------------
297
255
 
 
256
%% Cmd = app_ctrl | load | app | pinfo
298
257
handle_cast({From, Cmd, Aux, OnOff, Opts}, State) ->
299
258
    NewState = update_worklist(Cmd, Aux, From, OnOff, Opts, State),
300
259
    {noreply, NewState};
301
260
handle_cast(status, State) ->
302
261
    print_state(State),
303
262
    {noreply, State};
304
 
handle_cast({From, set_option, Opt}, State) ->
305
 
    NewOpts = ins_opt(Opt, State#state.opts),
306
 
    {noreply, State#state{opts=NewOpts}};
307
 
handle_cast(Other, State) ->
308
 
    tell("~p got unknown cast: ~p~n", [?MODULE, Other], 1, State#state.opts),
 
263
handle_cast(_Other, State) ->
309
264
    {noreply, State}.
310
265
 
311
266
 
315
270
%%
316
271
%%----------------------------------------------------------------------
317
272
 
318
 
handle_info(stop, State) ->
319
 
    {stop, normal, State};
320
273
handle_info({do_it, Key}, State) ->
321
274
    ok = do_work(Key, State),
322
275
    {noreply, State};
327
280
            {stop, Reason, State};
328
281
        _Other ->
329
282
            Work = State#state.work,
330
 
            del_work(ets:match(Work, {{'$1', '$2', Pid}, '_', '_', '_'}), Pid, Work),
 
283
            del_work(ets:match(Work, {{'$1','$2',Pid}, '_', '_', '_'}),
 
284
                     Pid, Work),
331
285
            case lists:delete(Pid, State#state.clients) of
332
286
                [] -> case get_opt(stay_resident, State#state.opts) of
333
287
                          true -> {noreply, State#state{clients=[]}};
336
290
                NewClients -> {noreply, State#state{clients=NewClients}}
337
291
            end
338
292
    end;
339
 
handle_info(Other, State) ->
340
 
%%    io:format("gad: ~p~n", [Other]),
341
 
    tell("~p got unknown info: ~p~n", [?MODULE, Other], 1, State#state.opts),
 
293
handle_info(_Other, State) ->
342
294
    {noreply, State}.
343
295
 
344
296
 
349
301
%%----------------------------------------------------------------------
350
302
 
351
303
do_work(Key, State) ->
352
 
    %%io:format("Do work ~p~n", [Key]),
353
304
    WorkStore = State#state.work,
354
 
    {Cmd, Aux, From, OldRef, Old, Opts} = retreive(WorkStore, Key),
355
 
    %%tell("Work: ~p, ~p, ~p~n", [Cmd, Aux, From], 5, State#state.opts),
356
 
    {ok, Result} = do_work2(Cmd, Aux, From, Old, Opts, State),
 
305
    {Cmd, Aux, From, _OldRef, Old, Opts} = retrieve(WorkStore, Key),
 
306
    {ok, Result} = do_work2(Cmd, Aux, From, Old, Opts),
357
307
    if  Result==Old -> ok;
358
308
        true ->
359
 
%%%         tell("Result delivered:~n", [], 4, State#state.opts),
360
 
%%%         tell("   cmd:~p, aux:~p, ", [Cmd, Aux], 4, State#state.opts),
361
 
%%%         tell("from:~p, opts:~p, res:~p~n", 
362
 
%%%              [From, Opts, Result], 4, State#state.opts),
363
309
            From ! {delivery, self(), Cmd, Aux, Result}
364
310
    end,
365
311
    case get_opt(timeout, Opts) of
378
324
%%
379
325
%% Maintenance Note: Add a clause here for each new task.
380
326
%%
381
 
do_work2(load, Aux, From, Old, Opts, State) ->
382
 
    calc_load(load, Aux, From, Old, Opts);
383
 
do_work2(app_ctrl, Aux, From, Old, Opts, State) ->
384
 
    calc_app_on_node(app_ctr, Aux, From, Old, Opts);
385
 
do_work2(app, Aux, From, Old, Opts, State) ->
386
 
    R = calc_app_tree(app, Aux, From, Old, Opts),
387
 
    %%io:format("Result: ~p~n", [R]),
388
 
    R;
389
 
do_work2(pinfo, Aux, From, Old, Opts, State) ->
390
 
    calc_pinfo(pinfo, Aux, From, Old, Opts);
391
 
do_work2(Cmd, Aux, From, Old, Opts, State) ->
392
 
    tell("Do work: ~p~n", [Cmd], 5, State#state.opts),
 
327
do_work2(load, _Aux, _From, Old, Opts) ->
 
328
    calc_load(Old, Opts);
 
329
do_work2(app_ctrl, _Aux, _From, _Old, _Opts) ->
 
330
    calc_app_on_node();
 
331
do_work2(app, Aux, _From, _Old, Opts) ->
 
332
    calc_app_tree(Aux, Opts);
 
333
do_work2(pinfo, Aux, _From, _Old, _Opts) ->
 
334
    calc_pinfo(pinfo, Aux);
 
335
do_work2(Cmd, Aux, _From, _Old, _Opts) ->
393
336
    {Cmd, Aux}.
394
337
 
395
338
 
396
 
retreive(Tab, Key) ->
397
 
    %%io:format("Retrieve: ~p~n", [Key]),
 
339
retrieve(Tab, Key) ->
398
340
    case ets:lookup(Tab, Key) of
399
341
        [{{Cmd, Aux, From}, Ref, Old, Opts}] ->
400
342
            {Cmd, Aux, From, Ref, Old, Opts};
401
 
        Other ->
 
343
        _Other ->
402
344
            false
403
345
    end.
404
346
 
416
358
update_worklist(Cmd, Aux, From, true, Opts, State) ->
417
359
    add_task(Cmd, Aux, From, Opts, State),
418
360
    State;
419
 
update_worklist(Cmd, Aux, From, Other, Opts, State) ->
 
361
update_worklist(Cmd, Aux, From, _Other, _Opts, State) ->
420
362
    del_task(Cmd, Aux, From, State#state.work),
421
363
    State.
422
364
 
431
373
    store(WorkStore, Key, nil, nil, ins_opts(Opts, OldOpts)),
432
374
    catch do_work(Key, State),
433
375
    ok.
434
 
%%self() ! ?MK_DOIT(Key).
435
 
 
436
 
    
437
 
%%    {ok, Ref} = timer:send_after(get_opt(timeout, Opts), 
438
 
%%                               {do_it, Cmd, Aux, From}),
439
 
%%ets:insert(WorkStore, {{Cmd, Aux, From}, Ref, Opts}).
440
376
 
441
377
%% Delete a list of tasks belonging to a pid
442
378
del_work([[Cmd, Aux] | Ws], Pid, Work) ->
443
 
%%    io:format("Deleting ~p ~p ~p~n", [Cmd, Aux, Pid]),
444
379
    del_task(Cmd, Aux, Pid, Work),
445
380
    del_work(Ws, Pid, Work);
446
 
del_work([], Pid, Work) -> ok.
 
381
del_work([], _Pid, _Work) -> ok.
447
382
 
448
383
%% Must return old options or empty list
449
384
del_task(Cmd, Aux, From, WorkStore) ->
450
385
    del_task(?MK_KEY(Cmd, Aux, From, []), WorkStore).
451
386
del_task(Key, WorkStore) ->
452
 
    OldStuff = retreive(WorkStore, Key),
 
387
    OldStuff = retrieve(WorkStore, Key),
453
388
    ets:delete(WorkStore, Key),
454
389
    case OldStuff of
455
 
        {Cmd, Aux, From, Ref, Old, Opts} ->
 
390
        {_Cmd, _Aux, _From, Ref, _Old, Opts} ->
456
391
            if  Ref /= nil ->
457
392
                    timer:cancel(Ref),
458
393
                    receive
501
436
%%----------------------------------------------------------------------
502
437
 
503
438
 
504
 
calc_app_tree(Cmd, Name, From, Old, Opts) ->
 
439
calc_app_tree(Name, Opts) ->
505
440
    Mode = get_opt(info_type, Opts),
506
441
    case application_controller:get_master(Name) of
507
442
        Pid when pid(Pid) ->
524
459
            R;
525
460
        _ ->
526
461
            {ok, {[], [], [], []}}
527
 
    end;
528
 
calc_app_tree(Cmd, undefined, From, Old, Opts) ->
529
 
    {ok, {[], [], [], []}}.
530
 
 
 
462
    end.
531
463
 
532
464
get_pid(P) when pid(P) -> P;
533
465
get_pid(P) when port(P) -> P;
541
473
    case get_next(DB) of
542
474
        {{value, V}, DB2} ->
543
475
            do_find_proc2(V, Mode, DB2, GL, Avoid);
544
 
%%          DB3 = add_proc(V, Mode, DB2, GL, Avoid),
545
 
%%          do_find_proc(Mode, DB3, GL, Avoid);
546
476
        {empty, DB2} ->
547
477
            {ok, DB2}
548
478
    end.
549
479
 
550
 
do_find_proc2(X, Mode, DB, GL, Avoid) when port(X) ->
551
 
    DB2 = case is_proc(DB, X) of
552
 
              [] -> add_port(DB, X);
553
 
              _ -> DB
554
 
          end,
555
 
    do_find_proc(Mode, DB2, GL, Avoid);
 
480
do_find_proc2(X, Mode, DB, GL, Avoid) when is_port(X) ->
 
481
    %% There used to be a broken attempt here to handle ports,
 
482
    %% but the rest of appmon can't handle ports, so now we
 
483
    %% explicitly ignore ports.
 
484
    do_find_proc(Mode, DB, GL, Avoid);
556
485
do_find_proc2(X, Mode, DB, GL, Avoid) ->
557
486
    Xpid = get_pid(X),
558
 
%%    io:format("Adding ~p (~p)~n", [XX, X]),
559
487
    DB2 = case is_proc(DB, Xpid) of
560
488
              false ->
561
489
                  add_proc(DB, Xpid),
562
 
%%                ets:insert(P, {Xpid}),
563
490
                  C1 = find_children(X, Mode),
564
 
%%                ?ifthen(Mode==sup, io:format("find_children ret ~p~n", 
565
 
%%                                             [C1])),
566
491
                  add_children(C1, Xpid, DB, GL, Avoid, Mode);
567
492
              _ -> 
568
493
                  DB
580
505
    %% better be a supervisor, we are smoked otherwise
581
506
    supervisor:which_children(X);
582
507
find_children(X, link) when pid(X), node(X) /= node() ->
583
 
%%    io:format("Proc on other node: ~p~n", [X]),
584
508
    [];
585
509
find_children(X, link) when pid(X) ->
586
510
    case process_info(X, links) of
587
511
        {links, Links} ->
588
 
%%          Links;
589
512
            lists:reverse(Links); % OTP-4082
590
513
        _ -> []
591
514
    end;
592
515
find_children({master, X}, sup) -> 
593
 
%%    io:format("Adding master ~p~n", [X]),
594
516
    case application_master:get_child(X) of
595
 
        {Pid, Name} when pid(Pid) -> [Pid];
 
517
        {Pid, _Name} when pid(Pid) -> [Pid];
596
518
        Pid when pid(Pid)         -> [Pid]
597
519
    end;
598
 
find_children({_, X, worker, _}, sup) -> [];
 
520
find_children({_, _X, worker, _}, sup) -> [];
599
521
find_children({_, X, supervisor, _}, sup) ->
600
522
    lists:filter(fun(Thing) -> 
601
523
                         Pid = get_pid(Thing),
609
531
%% Add links to primary (L1) or secondary (L2) sets and return an
610
532
%% updated queue. A link is considered secondary if its endpoint is in
611
533
%% the queue of un-visited but known processes.
612
 
add_children(CList, Paren, DB, GL, Avoid, sup) ->
613
 
    foldr(fun(C, DB2) -> 
614
 
                  case get_pid(C) of
615
 
                      P when pid(P) -> 
616
 
                          add_prim(C, Paren, DB2);
617
 
                      _ -> DB2 end end,
618
 
          DB, CList);
 
534
add_children(CList, Paren, DB, _GL, _Avoid, sup) ->
 
535
    lists:foldr(fun(C, DB2) -> 
 
536
                        case get_pid(C) of
 
537
                            P when pid(P) -> 
 
538
                                add_prim(C, Paren, DB2);
 
539
                            _ -> DB2 end end,
 
540
                DB, CList);
619
541
 
620
 
add_children(CList, Paren, DB, GL, Avoid, Mode) ->
621
 
    foldr(fun(C, DB2) ->
622
 
                  maybe_add_child(C, Paren, DB2, GL, Avoid)
623
 
          end, DB, CList).
 
542
add_children(CList, Paren, DB, GL, Avoid, _Mode) ->
 
543
    lists:foldr(fun(C, DB2) ->
 
544
                        maybe_add_child(C, Paren, DB2, GL, Avoid)
 
545
                end, DB, CList).
624
546
 
625
547
%% Check if the child is already in P
626
548
maybe_add_child(C, Paren, DB, GL, Avoid) ->
632
554
 
633
555
%% Check if process on this node
634
556
maybe_add_child_node(C, Paren, DB, GL, Avoid) ->
635
 
%%    io:format("Try node: ~p (~p)~n", [C, node(get_pid(C))]),
636
557
    if  node(C) /= node() -> 
637
558
            add_foreign(C, Paren, DB);
638
559
        true -> 
641
562
 
642
563
%% Check if child is on the avoid list
643
564
maybe_add_child_avoid(C, Paren, DB, GL, Avoid) ->
644
 
%%    io:format("Try avoid: ~p~n", [C]),
645
565
    case lists:member(C, Avoid) of
646
566
        true -> DB;
647
567
        false ->
648
 
            maybe_add_child_port(C, Paren, DB, GL, Avoid)
 
568
            maybe_add_child_port(C, Paren, DB, GL)
649
569
    end.
650
570
 
651
571
%% Check if it is a port, then it is added
652
 
maybe_add_child_port(C, Paren, DB, GL, Avoid) ->
 
572
maybe_add_child_port(C, Paren, DB, GL) ->
653
573
    if  port(C) ->
654
574
            add_prim(C, Paren, DB);
655
575
        true ->
656
 
            maybe_add_child_sasl(C, Paren, DB, GL, Avoid)
 
576
            maybe_add_child_sasl(C, Paren, DB, GL)
657
577
    end.
658
578
 
659
579
%% Use SASL stuff if present
660
 
maybe_add_child_sasl(C, Paren, DB, GL, Avoid) ->
 
580
maybe_add_child_sasl(C, Paren, DB, GL) ->
661
581
    case check_sasl_ancestor(Paren, C) of
662
582
        yes ->                                  % Primary
663
 
%%          io:format("Try: Was SASL primary ~p~n", [C]),
664
583
            add_prim(C, Paren, DB);
665
584
        no ->                                   % Secondary
666
 
%%          io:format("Try: was SASL sec ~p~n", [C]),
667
585
            add_sec(C, Paren, DB);
668
586
        dont_know ->
669
 
            maybe_add_child_gl(C, Paren, DB, GL, Avoid)
 
587
            maybe_add_child_gl(C, Paren, DB, GL)
670
588
    end.
671
589
                    
672
590
%% Check group leader
673
 
maybe_add_child_gl(C, Paren, DB, GL, Avoid) ->
674
 
%%    io:format("Try gl: ~p, gl: ~p, cgl: ~p~n", [C, GL, groupl(get_pid(C))]),
 
591
maybe_add_child_gl(C, Paren, DB, GL) ->
675
592
    case cmp_groupl(GL, groupl(C)) of
676
 
        true -> maybe_add_child_sec(C, Paren, DB, GL, Avoid);
 
593
        true -> maybe_add_child_sec(C, Paren, DB);
677
594
        _ -> DB
678
595
    end.
679
596
 
680
597
%% Check if the link should be a secondary one. Note that this part is
681
598
%% pretty much a guess.
682
 
maybe_add_child_sec(C, Paren, DB, GL, Avoid) ->
683
 
%%    io:format("Try sec: ~p~n", [C]),
 
599
maybe_add_child_sec(C, Paren, DB) ->
684
600
    case is_in_queue(DB, C) of
685
601
        true ->                                 % Yes, secondary
686
602
            add_sec(C, Paren, DB);
720
636
get_next(DB) ->
721
637
    {X, Q} = queue:out(DB#db.q),
722
638
    {X, DB#db{q=Q}}.
723
 
add_port(DB, P) ->
724
 
    ets:insert(DB#db.p, {P}).
725
639
add_proc(DB, P) ->
726
640
    ets:insert(DB#db.p, {P}).
727
641
add_prim(C, Paren, DB) ->
733
647
add_sec(C, Paren, DB) ->
734
648
    ?add_link(C, Paren, DB#db.links2),
735
649
    DB.
736
 
is_proc(DB, P) ->
737
 
    case ets:lookup(DB#db.p, P) of
738
 
        [] -> false;
739
 
        _ -> true
740
 
    end.
741
 
is_in_queue(DB, P) ->                           % Should really be in queue.erl
742
 
    {L1, L2} = DB#db.q,
743
 
    case lists:member(P, L1) of
744
 
        true -> true;
745
 
        false -> lists:member(P, L2)
746
 
    end.
747
 
 
748
 
%add_children([C | Cs], Paren, Q, P, L1, L2, GL, Avoid) ->
749
 
%    case lists:member(get_pid(C), Avoid) of
750
 
%       false ->
751
 
%           case queue_member(C, Q) of
752
 
%               false ->
753
 
%                   case add_link(P, L1, Paren, GL, get_pid(C)) of
754
 
%                       added ->
755
 
%                           [C | add_children(Cs, Paren, Q, P, L1, L2, 
756
 
%                                             GL, Avoid)];
757
 
%                       _ ->
758
 
%                           add_children(Cs, Paren, Q, P, L1, L2, GL, Avoid)
759
 
%                   end;
760
 
%               true ->
761
 
%                   add_link(P, L2, Paren, GL, get_pid(C)),
762
 
%                   add_children(Cs, Paren, Q, P, L1, L2, GL, Avoid)
763
 
%           end;
764
 
%       true -> 
765
 
%           add_children(Cs, Paren, Q, P, L1, L2, GL, Avoid)
766
 
%    end;
767
 
%add_children([], Paren, Q, P, L1, L2, GL, Avoid) -> Q.
768
 
 
769
 
 
770
 
 
771
 
%% Add a link if . Do not add link if group leaders differ.
772
 
%%add_link() ->
773
 
%%    case ets:lookup(L, Child) of
774
 
%%      [] -> 
775
 
%%          case ets:lookup(P, Child) of
776
 
%%              [] -> 
777
 
%%                  case cmp_groupl(GL, groupl(Child)) of
778
 
%%                      true ->
779
 
%%                          ets:insert(L, {Paren, Child}), added;
780
 
%%                      _ -> not_added
781
 
%%                  end;
782
 
%%              _ -> not_added
783
 
%%          end;
784
 
%%      _ -> not_added
785
 
%%    end.
786
 
 
 
650
 
 
651
is_proc(#db{p=Tab}, P) ->
 
652
    ets:member(Tab, P).
 
653
 
 
654
is_in_queue(#db{q={L1,L2}}, P) -> % Should really be in queue.erl
 
655
    lists:member(P, L1) orelse lists:member(P, L2).
787
656
 
788
657
%% Group leader handling. No processes or Links to processes must be
789
658
%% added when group leaders differ. Note that catch all is needed
793
662
groupl(P) when pid(P) ->
794
663
    case process_info(P, group_leader) of
795
664
        {group_leader, GL} -> GL;
796
 
        Other -> nil
 
665
        _Other -> nil
797
666
    end;
798
667
groupl(_) -> nil.
799
 
cmp_groupl(GL1, nil) -> true;
 
668
cmp_groupl(_GL1, nil) -> true;
800
669
cmp_groupl(GL1, GL1) -> true;
801
670
cmp_groupl(_, _) -> false.
802
671
 
865
734
%%----------------------------------------------------------------------
866
735
 
867
736
%% Finds all applications on a node
868
 
calc_app_on_node(Cmd, Aux, From, Old, Opts) ->
 
737
calc_app_on_node() ->
869
738
    NewApps = reality_check(application:which_applications()),
870
739
    {ok, NewApps}.
871
740
 
903
772
%%**********************************************************************
904
773
%%----------------------------------------------------------------------
905
774
 
906
 
calc_load(load, Aux, From, Old, Opts) ->
 
775
calc_load(Old, Opts) ->
907
776
    L = load(Opts),
908
777
    case get_opt(load_average, Opts) of
909
778
        true ->
946
815
                end
947
816
    end.
948
817
 
949
 
            
950
 
 
951
 
%%%%            min(time_map(Td/Tot)+trunc(Q*load_range()/6), load_range() ),
952
 
 
953
 
 
954
818
min(X,Y) when X<Y -> X;
955
 
min(X,Y)->Y.
 
819
min(_,Y)->Y.
956
820
 
957
821
 
958
822
%%
962
826
 
963
827
 
964
828
get_sample(queue)  -> statistics(run_queue);
965
 
get_sample(reds)  -> {Rt,Rd} = statistics(reductions), 
966
 
                     delta(reds, Rt, Rd);
967
829
get_sample(runtime)  -> {Rt,Rd} = statistics(runtime), 
968
830
                        delta(runtime, Rt, Rd);
969
831
get_sample(tot_time)  -> {Rt,Rd} = statistics(wall_clock), 
984
846
                 Other ->
985
847
                     if
986
848
                         Other > Val ->
987
 
                             %%?D("Delta error: ~p ~p ~p ~p~n", 
988
 
                             %%[Other, Val, Val-Other, CheatDelta]),
989
849
                             CheatDelta;
990
850
                         true ->
991
851
                             Val-Other
992
852
                     end
993
853
             end,
994
 
    %%?D("~p delta: ~p ~p~n", [node(), RetVal, CheatDelta]),
995
854
    put(KeyWord, Val),
996
855
    RetVal.
997
856
 
1021
880
%%**********************************************************************
1022
881
%%----------------------------------------------------------------------
1023
882
 
1024
 
calc_pinfo(pinfo, Pid, From, Old, Opts) when pid(Pid) ->
 
883
calc_pinfo(pinfo, Pid) when pid(Pid) ->
1025
884
    Info = process_info(Pid),
1026
 
    {ok, io_lib:format("Node: ~p, Process: ~p~n~p~n~n", [node(), Pid, Info])};
1027
 
calc_pinfo(pinfo, Pid, From, Old, Opts) when port(Pid) ->
 
885
    {ok, io_lib:format("Node: ~p, Process: ~p~n~p~n~n",
 
886
                       [node(), Pid, Info])};
 
887
calc_pinfo(pinfo, Pid) when port(Pid) ->
1028
888
    Info = lists:map(fun(Key) ->erlang:port_info(Pid, Key) end,
1029
889
                     [id, name, connected, links, input, output]),
1030
890
    
1031
891
    {ok, io_lib:format("Node: ~p, Port: ~p~n~p~n~n", 
1032
892
                       [node(),  element(2, erlang:port_info(Pid, id)),
1033
893
                        Info])};
1034
 
calc_pinfo(pinfo, Pid, From, Old, Opts) ->
 
894
calc_pinfo(pinfo, _Pid) ->
1035
895
    {ok, ""}.
1036
896
 
1037
897
 
1055
915
%%
1056
916
%%----------------------------------------------------------------------
1057
917
print_state(State) ->
1058
 
    io:format("Status:~n    Opts: ~p~n    Clients: ~p~n    WorkStore:~n",
 
918
    io:format("Status:~n    Opts: ~p~n"
 
919
              "Clients: ~p~n    WorkStore:~n",
1059
920
              [State#state.opts, State#state.clients]),
1060
921
    print_work(ets:tab2list(State#state.work)).
1061
922
 
1064
925
print_work([]) -> ok.
1065
926
    
1066
927
 
1067
 
 
1068
 
 
1069
 
 
1070
928
%%----------------------------------------------------------------------
1071
929
%%
1072
930
%% Option handling
1073
931
%%
1074
932
%%----------------------------------------------------------------------
1075
933
 
 
934
%% The only options ever set by a user is info_type, timeout,
 
935
%% load_scale and load_method.
1076
936
get_opt(Name, Opts) ->
1077
937
    case lists:keysearch(Name, 1, Opts) of
1078
938
        {value, Val} -> element(2, Val);
1079
 
        _ -> case lists:member(Name, Opts) of
1080
 
                 true -> true;
1081
 
                 _ -> default(Name)
1082
 
             end
 
939
        false -> default(Name)
1083
940
    end.
1084
941
 
1085
942
%% not all options have default values
 
943
default(info_type)      -> link;
 
944
default(load_average)   -> true;
1086
945
default(load_method)    -> time;
1087
946
default(load_scale)     -> prog;
1088
 
default(load_average)   -> true;
1089
 
default(timeout)        -> 2000;
1090
 
default(verbosity)      -> 0;
1091
 
default(info_type)      -> link;
1092
947
default(stay_resident)  -> false;
1093
 
default({avoid, _})     -> false;
1094
 
default(method)         -> poll.
 
948
default(timeout)        -> 2000.
1095
949
 
1096
950
ins_opts([Opt | Opts], Opts2) ->
1097
951
    ins_opts(Opts, ins_opt(Opt, Opts2));
1100
954
ins_opt({Opt, Val}, [{Opt, _} | Os]) -> [{Opt, Val} | Os];
1101
955
ins_opt(Opt, [Opt2 | Os]) -> [Opt2 | ins_opt(Opt, Os)];
1102
956
ins_opt(Opt, []) -> [Opt].
1103
 
 
1104
 
 
1105
 
tell(F, A, Prio, Opts) ->
1106
 
    P2 = get_opt(verbosity, Opts),
1107
 
    if  P2 > Prio -> io:format(F, A);
1108
 
        true -> ok
1109
 
    end.