/jaerlang-code/code/indexer-1.1/indexer_checkpoint.erl

https://github.com/killme2008/erlib · Erlang · 74 lines · 47 code · 13 blank · 14 comment · 0 complexity · 39576714c8b7b49157a4b9faf5c8af50 MD5 · raw file

  1. %% ---
  2. %% Excerpted from "Programming Erlang",
  3. %% published by The Pragmatic Bookshelf.
  4. %% Copyrights apply to this code. It may not be used to create training material,
  5. %% courses, books, articles, and the like. Contact us if you are in doubt.
  6. %% We make no guarantees that this code is fit for any purpose.
  7. %% Visit http://www.pragmaticprogrammer.com/titles/jaerlang for more book information.
  8. %%---
  9. -module(indexer_checkpoint).
  10. -export([init/2, resume/1, checkpoint/2]).
  11. -import(filelib, [is_file/1]).
  12. %%% init(Dir, Term) -> true. %% define a checkpoitn dirextory and term X
  13. %% resume(Dir) -> {Check, X} %% Check is used in the *next* call to checkpoint
  14. %% %% X is a term
  15. %% checkpoint(Check, X) -> %% Set a new checkpoint
  16. %% Check'
  17. init(Dir, X) ->
  18. One = Dir ++ "/1.check",
  19. Two = Dir ++ "/2.check",
  20. case is_file(One) or is_file(Two) of
  21. true ->
  22. exit(eBadInit);
  23. false ->
  24. checkpoint({Dir, 1}, X),
  25. checkpoint({Dir, 2}, X)
  26. end.
  27. %% resume(Dir) -> {NextCheckPointFile, X} | error
  28. resume(Dir) ->
  29. R1 = recover(Dir ++ "/1.check"),
  30. R2 = recover(Dir ++ "/2.check"),
  31. case {R1, R2} of
  32. {error, error} -> error;
  33. {error, _} -> {{Dir,1}, element(2, R2)};
  34. {_, error} -> {{Dir,2}, element(2, R1)};
  35. {{T1,X},{T2,_}} when T1 > T2 -> {{Dir,2}, X};
  36. {_,{_,X}} -> {{Dir,1}, X}
  37. end.
  38. recover(File) ->
  39. case file:read_file(File) of
  40. {ok, Bin} when size(Bin) > 32 ->
  41. {B1,B2} = split_binary(Bin, 16),
  42. case bin_to_md5(B2) of
  43. B1 ->
  44. binary_to_term(B2);
  45. _ ->
  46. error
  47. end;
  48. _ ->
  49. error
  50. end.
  51. checkpoint({Dir, Next}, X) ->
  52. File = Dir ++ "/" ++ integer_to_list(Next) ++ ".check",
  53. Time = now(),
  54. B = term_to_binary({Time, X}),
  55. CheckSum = bin_to_md5(B),
  56. ok = file:write_file(File, [CheckSum,B]),
  57. {Dir, 3-Next}.
  58. bin_to_md5(Bin) ->
  59. C1 = erlang:md5_init(),
  60. C2 = erlang:md5_update(C1, Bin),
  61. erlang:md5_final(C2).