Created
June 25, 2009 02:11
-
-
Save davisp/135646 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/.gitignore b/.gitignore | |
index ea1f975..70788fa 100644 | |
--- a/.gitignore | |
+++ b/.gitignore | |
@@ -1,3 +1,5 @@ | |
+ | |
+# copied from jChirs .gitignore | |
*.beam | |
*.gz | |
*.tpl | |
@@ -6,6 +8,7 @@ | |
*.m4 | |
*.in | |
*.in~ | |
+ | |
erl_crash.dump | |
configure | |
autom4te.cache | |
@@ -27,7 +30,9 @@ etc/launchd/Makefile | |
etc/logrotate.d/Makefile | |
libtool | |
share/Makefile | |
+ | |
src/couchdb/.deps/* | |
+ | |
src/couchdb/Makefile | |
src/mochiweb/Makefile | |
stamp-h1 | |
@@ -35,8 +40,10 @@ test/.deps/ | |
test/Makefile | |
var/Makefile | |
+ | |
# for make | |
+ | |
bin/couchdb | |
bin/couchdb.1 | |
bin/couchjs | |
@@ -44,7 +51,9 @@ bin/couchjs.1 | |
etc/couchdb/default.ini | |
etc/launchd/org.apache.couchdb.plist | |
etc/logrotate.d/couchdb | |
+ | |
src/couchdb/.libs/* | |
+ | |
src/couchdb/couch.app | |
src/couchdb/couch_erl_driver.la | |
src/couchdb/couchjs | |
@@ -52,18 +61,22 @@ src/couchdb/edoc-info | |
src/couchdb/erlang.png | |
src/couchdb/stylesheet.css | |
test/local.ini | |
+ | |
share/server/main.js | |
# for make dev | |
+ | |
bin/.deps/ | |
bin/couchjs_dev | |
bin/couchpw | |
etc/couchdb/default_dev.ini | |
etc/couchdb/local_dev.ini | |
utils/run | |
+ | |
tmp | |
+ | |
# for make check | |
test/etap/temp.* | |
@@ -71,3 +84,4 @@ test/etap/temp.* | |
# for make cover | |
cover/* | |
+ | |
diff --git a/src/couchdb/couch_task_status.erl b/src/couchdb/couch_task_status.erl | |
index a0ef490..384d673 100644 | |
--- a/src/couchdb/couch_task_status.erl | |
+++ b/src/couchdb/couch_task_status.erl | |
@@ -19,7 +19,7 @@ | |
% it will be automatically removed the tracking. To get the tasks list, use the | |
% all/0 function | |
--export([start_link/0,init/1,terminate/2,handle_call/3,handle_cast/2,handle_info/2, | |
+-export([start_link/0,stop/0,init/1,terminate/2,handle_call/3,handle_cast/2,handle_info/2, | |
code_change/3,add_task/3,update/1,update/2,all/0,set_update_frequency/1]). | |
-include("couch_db.hrl"). | |
@@ -27,6 +27,9 @@ | |
start_link() -> | |
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). | |
+stop() -> | |
+ gen_server:cast(?MODULE, stop). | |
+ | |
to_binary(L) when is_list(L) -> | |
?l2b(L); | |
to_binary(B) when is_binary(B) -> | |
@@ -57,11 +60,7 @@ update(Format, Data) -> | |
% returns a list of proplists. Each proplist describes a running task. | |
all() -> | |
- [[{type,Type}, | |
- {task,Task}, | |
- {status,Status}, | |
- {pid,?l2b(pid_to_list(Pid))}] || | |
- {Pid, {Type,Task,Status}} <- ets:tab2list(tasks_by_pid)]. | |
+ gen_server:call(?MODULE,{all}). | |
init([]) -> | |
% read configuration settings and register for configuration changes | |
@@ -80,14 +79,26 @@ handle_call({add_task,Type,TaskName,StatusText}, {From, _}, Server) -> | |
{reply, ok, Server}; | |
[_] -> | |
{reply, {add_task_error, already_registered}, Server} | |
- end. | |
+ end; | |
+handle_call({all}, _, Server) -> | |
+ All = [[{type,Type}, | |
+ {task,Task}, | |
+ {status,Status}, | |
+ {pid,?l2b(pid_to_list(Pid))}] || | |
+ {Pid, {Type,Task,Status}} <- ets:tab2list(tasks_by_pid)], | |
+ {reply, All, Server}. | |
+ | |
handle_cast({update_status, Pid, StatusText}, Server) -> | |
[{Pid, {Type,TaskName,_StatusText}}] = ets:lookup(tasks_by_pid, Pid), | |
true = ets:insert(tasks_by_pid, {Pid, {Type,TaskName,StatusText}}), | |
- {noreply, Server}. | |
+ {noreply, Server}; | |
+ | |
+handle_cast(stop, State) -> | |
+ {stop, normal, State}. | |
handle_info({'DOWN', _MonitorRef, _Type, Pid, _Info}, Server) -> | |
+ %% should we also erlang:demonitor(_MonitorRef), ? | |
ets:delete(tasks_by_pid, Pid), | |
{noreply, Server}. | |
diff --git a/test/etap/090-task-status.t b/test/etap/090-task-status.t | |
new file mode 100755 | |
index 0000000..de7a28a | |
--- /dev/null | |
+++ b/test/etap/090-task-status.t | |
@@ -0,0 +1,136 @@ | |
+#!/usr/bin/env escript | |
+%% -*- erlang -*- | |
+ | |
+main(_) -> | |
+ code:add_pathz("src/couchdb"), | |
+ etap:plan(12), | |
+ | |
+ case (catch test()) of | |
+ ok -> | |
+ etap:end_tests(); | |
+ Other -> | |
+ etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), | |
+ etap:bail(Other) | |
+ end, | |
+ | |
+ ok. | |
+ | |
+check_status(Pid,ListPropLists) -> | |
+ From = list_to_binary(pid_to_list(Pid)), | |
+ Element = lists:foldl(fun(PropList,Acc) -> | |
+ case proplists:get_value(pid,PropList) of | |
+ From -> [PropList | Acc]; | |
+ _ -> [] | |
+ end | |
+ end,[],ListPropLists), | |
+ proplists:get_value(status,hd(Element)). | |
+ | |
+loop() -> | |
+ receive | |
+ {add, From} -> | |
+ couch_task_status:add_task("type","task","init"), | |
+ From ! {ok, self()}, | |
+ loop(); | |
+ {update, Status, From} -> | |
+ couch_task_status:update(Status), | |
+ From ! {ok, self()}, | |
+ loop(); | |
+ {update_frequency, Msecs, From} -> | |
+ couch_task_status:set_update_frequency(Msecs), | |
+ From ! {ok, self()}, | |
+ loop(); | |
+ {done, From} -> | |
+ From ! {ok, self()} | |
+ end. | |
+ | |
+call(Pid, Command) -> | |
+ Pid ! {Command, self()}, | |
+ wait(). | |
+ | |
+call(Pid, Command, Arg) -> | |
+ Pid ! {Command, Arg, self()}, | |
+ wait(). | |
+ | |
+wait() -> | |
+ receive | |
+ _ -> ok | |
+ after 1000 -> | |
+ etap:is(true, false, "Timed out waiting for pid to respond.") | |
+ end. | |
+ | |
+test() -> | |
+ {ok, TaskStatusPid} = couch_task_status:start_link(), | |
+ | |
+ | |
+ | |
+ TaskUpDater = fun() -> loop() end, | |
+ % create three updaters | |
+ Pid1 = spawn(TaskUpDater), | |
+ Pid2 = spawn(TaskUpDater), | |
+ Pid3 = spawn(TaskUpDater), | |
+ % add the first | |
+ call(Pid1,add), | |
+ | |
+ etap:is(length(couch_task_status:all()),1,"one task is running."), | |
+ etap:is(check_status(Pid1,couch_task_status:all()),<<"init">>, | |
+ "status should be initialized."), | |
+ | |
+ call(Pid1,update,"running"), | |
+ | |
+ etap:is(check_status(Pid1,couch_task_status:all()),<<"running">>, | |
+ "status should be running."), | |
+ | |
+ call(Pid2,add), | |
+ etap:is(length(couch_task_status:all()),2,"two tasks are running."), | |
+ etap:is(check_status(Pid2,couch_task_status:all()),<<"init">>, | |
+ "status of second should be initialized."), | |
+ call(Pid2,update,"running"), | |
+ etap:is(check_status(Pid2,couch_task_status:all()),<<"running">>, | |
+ "status should be running."), | |
+ | |
+ | |
+ call(Pid3,add), | |
+ etap:is(length(couch_task_status:all()),3,"two tasks are running."), | |
+ etap:is(check_status(Pid3,couch_task_status:all()),<<"init">>, | |
+ "status of second should be initialized."), | |
+ call(Pid3,update,"running"), | |
+ etap:is(check_status(Pid3,couch_task_status:all()),<<"running">>, | |
+ "status should be running."), | |
+ | |
+ | |
+ call(Pid3,update_frequency,500), | |
+ call(Pid3,update,"still running"), | |
+ etap:is(check_status(Pid3,couch_task_status:all()),<<"still running">>, | |
+ "status should be running."), | |
+ | |
+ call(Pid3,update,"are we there yet daddy"), | |
+ etap:is(check_status(Pid3,couch_task_status:all()),<<"still running">>, | |
+ "no we're not there yet."), | |
+ | |
+ call(Pid3,update_frequency,0), | |
+ call(Pid3,update,"are we there"), | |
+ etap:is(check_status(Pid3,couch_task_status:all()),<<"are we there">>, | |
+ "status should now be are we there."), | |
+ | |
+ | |
+ call(Pid1,done), | |
+ etap:is(length(couch_task_status:all()),2,"two tasks are running."), | |
+ | |
+ call(Pid2,done), | |
+ etap:is(length(couch_task_status:all()),1,"one tasks is running."), | |
+ call(Pid3,done), | |
+ etap:is(length(couch_task_status:all()),0,"no tasks are running."), | |
+ | |
+ % test gen_server stop | |
+ erlang:monitor(process, TaskStatusPid), | |
+ couch_task_status:stop(), | |
+ receive | |
+ {'DOWN', _, _, TaskStatusPid, _} -> | |
+ etap:diag("task_status stopped",[]), | |
+ ok; | |
+ _Other -> etap:diag("OTHER: ~p~n", [_Other]) | |
+ after | |
+ 1000 -> throw({timeout_error, task_status_stop}) | |
+ end, | |
+ | |
+ ok. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment