C0 code coverage information

Generated on 2009-08-09 21:22:55 with etap 0.3.4.

Name Total lines Lines of code Total coverage Code coverage
couch_ref_counter ?? ?? ??
97% 
....1 % Licensed under the Apache License, Version 2.0 (the "License"); you may not
....2 % use this file except in compliance with the License. You may obtain a copy of
....3 % the License at
....4 %
....5 %   http://www.apache.org/licenses/LICENSE-2.0
....6 %
....7 % Unless required by applicable law or agreed to in writing, software
....8 % distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
....9 % WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
...10 % License for the specific language governing permissions and limitations under
...11 % the License.
...12 
...13 -module(couch_ref_counter).
...14 -behaviour(gen_server).
...15 
...16 -export([start/1, init/1, terminate/2, handle_call/3, handle_cast/2, code_change/3, handle_info/2]).
...17 -export([drop/1,drop/2,add/1,add/2,count/1]).
...18 
...19 start(ChildProcs) ->
...20     gen_server:start(couch_ref_counter, {self(), ChildProcs}, []).
...21 
...22 
...23 drop(RefCounterPid) ->
...24     drop(RefCounterPid, self()).
...25 
...26 drop(RefCounterPid, Pid) ->
...27     gen_server:cast(RefCounterPid, {drop, Pid}).
...28 
...29 
...30 add(RefCounterPid) ->
...31     add(RefCounterPid, self()).
...32 
...33 add(RefCounterPid, Pid) ->
...34     gen_server:call(RefCounterPid, {add, Pid}).
...35 
...36 count(RefCounterPid) ->
...37     gen_server:call(RefCounterPid, count).
...38 
...39 % server functions
...40 
...41 -record(srv,
...42     {
...43     referrers=dict:new() % a dict of each ref counting proc.
...44     }).
...45 
...46 init({Pid, ChildProcs}) ->
...47     [link(ChildProc) || ChildProc <- ChildProcs],
...48     Referrers = dict:from_list([{Pid, {erlang:monitor(process, Pid), 1}}]),
...49     {ok, #srv{referrers=Referrers}}.
...50 
...51 
...52 terminate(Reason, _Srv) ->
...53     couch_util:terminate_linked(Reason),
...54     ok.
...55 
...56 
...57 handle_call({add, Pid},_From, #srv{referrers=Referrers}=Srv) ->
...58     Referrers2 =
...59     case dict:find(Pid, Referrers) of
...60     error ->
...61         dict:store(Pid, {erlang:monitor(process, Pid), 1}, Referrers);
...62     {ok, {MonRef, RefCnt}} ->
...63         dict:store(Pid, {MonRef, RefCnt + 1}, Referrers)
...64     end,
...65     {reply, ok, Srv#srv{referrers=Referrers2}};
...66 handle_call(count, _From, Srv) ->
...67     {monitors, Monitors} =  process_info(self(), monitors),
...68     {reply, length(Monitors), Srv}.
...69 
...70 
...71 handle_cast({drop, Pid}, #srv{referrers=Referrers}=Srv) ->
...72     Referrers2 =
...73     case dict:find(Pid, Referrers) of
...74     {ok, {MonRef, 1}} ->
...75         erlang:demonitor(MonRef, [flush]),
...76         dict:erase(Pid, Referrers);
...77     {ok, {MonRef, Num}} ->
...78         dict:store(Pid, {MonRef, Num-1}, Referrers);
...79     error ->
...80         Referrers
...81     end,
...82     maybe_close_async(Srv#srv{referrers=Referrers2}).
...83 
...84 
...85 code_change(_OldVsn, State, _Extra) ->
...86     {ok, State}.
...87 
...88 handle_info({'DOWN', MonRef, _, Pid, _}, #srv{referrers=Referrers}=Srv) ->
...89     {ok, {MonRef, _RefCount}} = dict:find(Pid, Referrers),
...90     maybe_close_async(Srv#srv{referrers=dict:erase(Pid, Referrers)}).
...91 
...92 
...93 should_close() ->
...94     case process_info(self(), monitors) of
...95     {monitors, []} ->
...96         true;
...97     _ ->
...98         false
...99     end.
..100 
..101 maybe_close_async(Srv) ->
..102     case should_close() of
..103     true ->
..104         {stop,normal,Srv};
..105     false ->
..106         {noreply,Srv}
..107     end.

Generated using etap 0.3.4.