/carrier/dataServer/data_writer.erl

http://egfs.googlecode.com/ · Erlang · 247 lines · 221 code · 18 blank · 8 comment · 1 complexity · 972313bbde7b283214aa5ca73629f4a4 MD5 · raw file

  1. -module(data_writer).
  2. -include("../include/egfs.hrl").
  3. -include("data_server.hrl").
  4. -import(chunk_db).
  5. -import(toolkit).
  6. -export([handle_write/4]).
  7. generate_write_reply()->
  8. {ok, Listen} = gen_tcp:listen(0, [binary, {packet, 2}, {active, true}]),
  9. {ok, IP_Addr} = toolkit:get_local_addr(),
  10. {ok, Port} = inet:port(Listen),
  11. {ok, Listen, {ok, IP_Addr, Port}}.
  12. handle_write(FileID, ChunkIndex, ChunkID, []) ->
  13. {ok, Listen, Reply} = generate_write_reply(),
  14. spawn(fun() -> write_process(FileID, ChunkIndex, ChunkID, Listen) end),
  15. Reply;
  16. handle_write(FileID, ChunkIndex, ChunkID, [H|T]) ->
  17. {ok, Listen, Reply} = generate_write_reply(),
  18. Next = gen_server:call(H, {writechunk, FileID, ChunkIndex, ChunkID, T}),
  19. {ok, _Next_IP, _Next_Port} = Next,
  20. spawn(fun() -> relay_write_process(FileID, ChunkIndex, ChunkID, Listen, Next) end),
  21. Reply.
  22. init_write_process(Listen) ->
  23. {ok, Socket} = gen_tcp:accept(Listen),
  24. gen_tcp:close(Listen),
  25. {ok, ListenData} = gen_tcp:listen(0, [binary, {packet, 2}, {active, true}]),
  26. Reply = inet:port(ListenData),
  27. gen_tcp:send(Socket, term_to_binary(Reply)),
  28. process_flag(trap_exit, true),
  29. Parent = self(),
  30. {ok, Socket, ListenData, Parent}.
  31. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  32. %%%%%% Write to Itself
  33. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  34. write_process(FileID, ChunkIndex, ChunkID, Listen) ->
  35. {ok, Socket, ListenData, Parent} = init_write_process(Listen),
  36. Child = spawn_link(fun() -> receive_it_tail(Parent, ListenData, ChunkID) end),
  37. Result = loop_write_control_tail(Socket, Child, FileID, ChunkIndex, ChunkID, 0),
  38. io:format("[~p, ~p] write control finish: ~p~n", [?MODULE, ?LINE, Result]),
  39. write_aftercare(Result, ChunkID),
  40. io:format("[~p, ~p] write_process finish~n", [?MODULE, ?LINE]).
  41. loop_write_control_tail(Socket, Child, FileID, ChunkIndex, ChunkID, State) ->
  42. receive
  43. {finish, Child, Len} ->
  44. ?DEBUG("[~p, ~p]: write transfer finish, ~pBytes~n", [?MODULE, ?LINE, Len]),
  45. {ok, Name} = toolkit:get_file_name(ChunkID),
  46. chunk_db:insert_chunk_info(ChunkID, FileID, Name, Len),
  47. gen_tcp:send(Socket, term_to_binary({check, Len})),
  48. wait_for_check_result(Socket);
  49. {error, Child, Why} ->
  50. ?DEBUG("[~p, ~p]: data transfer error~p~n", [?MODULE, ?LINE, Why]),
  51. {error, data_receive, Why};
  52. {tcp, Socket, Binary} ->
  53. Term = binary_to_term(Binary),
  54. case Term of
  55. {stop, Why} ->
  56. ?DEBUG("[data_server, ~p]: write stop msg from client.~n", [?LINE]),
  57. Child ! {stop, self(), Why},
  58. gen_tcp:close(Socket),
  59. {ok, stop, "write stop from writer"};
  60. _Any ->
  61. loop_write_control_tail(Socket, Child, FileID, ChunkIndex, ChunkID, State)
  62. end;
  63. {tcp_closed, Socket} ->
  64. ?DEBUG("[~p, ~p]: write control broken~n", [?MODULE, ?LINE]),
  65. {error, write_control, "write control broken"};
  66. Any ->
  67. ?DEBUG("[~p, ~p]: unkown msg ~p~n", [?MODULE, ?LINE, Any]),
  68. loop_write_control_tail(Socket, Child, FileID, ChunkIndex, ChunkID, State)
  69. end.
  70. receive_it_tail(Parent, ListenData, ChkID) ->
  71. {ok, SocketData} = gen_tcp:accept(ListenData),
  72. gen_tcp:close(ListenData),
  73. {ok, Hdl} = toolkit:get_file_handle(write, ChkID),
  74. loop_receive(Parent, SocketData, Hdl, 0),
  75. gen_tcp:close(SocketData).
  76. loop_receive(Parent, SocketData, Hdl, Len) ->
  77. receive
  78. {tcp, SocketData, Binary} ->
  79. Len2 = Len + size(Binary),
  80. file:write(Hdl, Binary),
  81. loop_receive(Parent, SocketData, Hdl, Len2);
  82. {tcp_closed, SocketData} ->
  83. file:close(Hdl),
  84. Parent ! {finish, self(), Len};
  85. {stop, Parent, _Why} ->
  86. file:close(Hdl),
  87. get_tcp:close(SocketData);
  88. Any ->
  89. ?DEBUG("[data_server, ~p]:loop Any:~p~n", [?LINE, Any]),
  90. loop_receive(Parent, SocketData, Hdl, Len)
  91. end.
  92. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  93. %%%%%% Relay Write
  94. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  95. connect_to_next({ok, Next_IP, Next_Port}) ->
  96. {ok, NextSocket} = gen_tcp:connect(Next_IP, Next_Port, [binary, {packet, 2}, {active, true}]),
  97. receive
  98. {tcp, NextSocket, Binary} ->
  99. {ok, Next_DataPort} = binary_to_term(Binary),
  100. {ok, NextSocket, Next_IP, Next_DataPort};
  101. _Any ->
  102. {error, next_connect, "cann't get next data port"}
  103. end.
  104. relay_write_process(FileID, ChunkIndex, ChunkID, Listen, Next) ->
  105. {ok, Socket, ListenData, Parent} = init_write_process(Listen),
  106. {ok, NextSocket, Next_IP, Next_DataPort} = connect_to_next(Next),
  107. Child = spawn_link(fun() -> relay_receive_it(Parent, ListenData, Next_IP, Next_DataPort, ChunkID) end),
  108. Result = loop_relay_write_control(Socket, NextSocket, Child, FileID, ChunkIndex, ChunkID, 0),
  109. io:format("[~p, ~p] write control finish: ~p~n", [?MODULE, ?LINE, Result]),
  110. write_aftercare(Result, ChunkID),
  111. io:format("[~p, ~p] write_process finish~n", [?MODULE, ?LINE]),
  112. gen_tcp:close(NextSocket).
  113. write_aftercare(Result, ChunkID) ->
  114. case Result of
  115. {ok, check} ->
  116. ok;
  117. _Any ->
  118. toolkit:rm_pending_chunk(ChunkID),
  119. chunk_db:remove_chunk_info(ChunkID)
  120. end.
  121. loop_relay_write_control(Socket, NextSocket, Child, FileID, ChunkIndex, ChunkID, State) ->
  122. receive
  123. {finish, Child, Len} ->
  124. {ok, Name} = toolkit:get_file_name(ChunkID),
  125. chunk_db:insert_chunk_info(ChunkID, FileID, Name, Len),
  126. %% Result = report_metaServer(FileID, ChunkIndex, ChunkID, Len),
  127. Child ! {die, self()},
  128. wait_for_check(Socket, NextSocket, ChunkID, Len, 0);
  129. {error, Child, Why} ->
  130. ?DEBUG("[~p, ~p] error from child(data transfer) ~n", [?MODULE, ?LINE]),
  131. toolkit:rm_pending_chunk(ChunkID),
  132. gen_tcp:send(Socket, term_to_binary({error, "data transfer error"})),
  133. gen_tcp:send(NextSocket, term_to_binary({stop, "data transfer error"})),
  134. gen_tcp:close(NextSocket),
  135. Child ! {die, self()},
  136. {error, data_receive, Why};
  137. {'EXIT', _, normal} ->
  138. loop_relay_write_control(Socket, NextSocket, Child, FileID, ChunkIndex, ChunkID, State);
  139. {tcp, Socket, Binary} ->
  140. gen_tcp:send(NextSocket, Binary),
  141. loop_relay_write_control(Socket, NextSocket, Child, FileID, ChunkIndex, ChunkID, State);
  142. {tcp, NextSocket, Binary} ->
  143. gen_tcp:send(Socket, Binary),
  144. loop_relay_write_control(Socket, NextSocket, Child, FileID, ChunkIndex, ChunkID, State);
  145. {tcp_closed, Socket} ->
  146. toolkit:rm_pending_chunk(ChunkID),
  147. gen_tcp:send(NextSocket, term_to_binary({stop, "data control error"})),
  148. gen_tcp:close(NextSocket),
  149. {error, control_socket, "control socket broken"};
  150. {tcp_closed, NextSocket} ->
  151. %%rm_pending_chunk(ChunkID),
  152. gen_tcp:send(Socket, term_to_binary({error, "next data control broken"})),
  153. {error, next_control_socket, "next control socket broken"};
  154. Any ->
  155. ?DEBUG("[~p, ~p] unkown control msg:~p ~n", [?MODULE, ?LINE, Any]),
  156. loop_relay_write_control(Socket, NextSocket, Child, FileID, ChunkIndex, ChunkID, State)
  157. end.
  158. wait_for_check(Socket, NextSocket, ChunkID, Len, State) ->
  159. receive
  160. {tcp, NextSocket, Binary} ->
  161. Term = binary_to_term(Binary),
  162. case Term of
  163. {check, Len} ->
  164. Result = {ok, check},
  165. gen_tcp:send(NextSocket, term_to_binary(Result)),
  166. gen_tcp:send(Socket, Binary),
  167. wait_for_check_result(Socket);
  168. _Other ->
  169. Result = {error, check, "length error"},
  170. gen_tcp:send(Socket, term_to_binary(Result)),
  171. gen_tcp:send(NextSocket, term_to_binary(Result)),
  172. Result
  173. end;
  174. _Any ->
  175. wait_for_check(Socket, NextSocket, ChunkID, Len, State)
  176. end.
  177. wait_for_check_result(Socket) ->
  178. receive
  179. {tcp, Socket, Binary} ->
  180. Term = binary_to_term(Binary),
  181. case Term of
  182. {ok, check} ->
  183. Term;
  184. {error, check, _Why} ->
  185. Term;
  186. Other ->
  187. {error, check, Other}
  188. end;
  189. {tcp_closed, Socket} ->
  190. {error, check, "broken socket"};
  191. _Any ->
  192. wait_for_check_result(Socket)
  193. end.
  194. relay_receive_it(Parent, ListenData, Next_IP, Next_DataPort, ChunkID) ->
  195. {ok, SocketData} = gen_tcp:accept(ListenData),
  196. gen_tcp:close(ListenData),
  197. {ok, Hdl} = toolkit:get_file_handle(write, ChunkID),
  198. {ok, NextSocketData} = gen_tcp:connect(Next_IP, Next_DataPort, [binary, {packet, 2}, {active, true}]),
  199. loop_relay_receive(Parent, SocketData, NextSocketData, Hdl, 0),
  200. gen_tcp:close(NextSocketData).
  201. loop_relay_receive(Parent, SocketData, NextSocketData, Hdl, Len) ->
  202. receive
  203. {tcp, SocketData, Binary} ->
  204. Len2 = Len + size(Binary),
  205. file:write(Hdl, Binary),
  206. gen_tcp:send(NextSocketData, Binary),
  207. loop_relay_receive(Parent, SocketData, NextSocketData, Hdl, Len2);
  208. {tcp_closed, SocketData} ->
  209. file:close(Hdl),
  210. Parent ! {finish, self(), Len},
  211. wait_to_die(Parent, NextSocketData, 0);
  212. {tcp_closed, NextSocketData} ->
  213. ?DEBUG("[~p, ~p] next data socket broken ~n", [?MODULE, ?LINE]),
  214. file:close(Hdl),
  215. Parent ! {error, self(), "next socket data closed"},
  216. wait_to_die(Parent, NextSocketData, 0);
  217. Any ->
  218. ?DEBUG("[~p, ~p] unknown: ~p~n", [?MODULE, ?LINE, Any]),
  219. loop_relay_receive(Parent, SocketData, NextSocketData, Hdl, Len)
  220. end.
  221. wait_to_die(Parent, NextSocketData, State) ->
  222. receive
  223. {die, Parent} ->
  224. gen_tcp:close(NextSocketData),
  225. ?DEBUG("[~p, ~p] close next socket data~n", [?MODULE, ?LINE]);
  226. Any ->
  227. ?DEBUG("[~p, ~p] unknown when wait for death: ~p~n", [?MODULE, ?LINE, Any]),
  228. wait_to_die(Parent, NextSocketData, State)
  229. end.