kvs_fs.erl 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. -module(kvs_fs).
  2. -include("backend.hrl").
  3. -include("kvs.hrl").
  4. -include("metainfo.hrl").
  5. -include_lib("stdlib/include/qlc.hrl").
  6. -export(?BACKEND).
  7. start() -> ok.
  8. stop() -> ok.
  9. destroy() -> ok.
  10. version() -> {version,"KVX FS"}.
  11. dir() -> [ {table,F} || F <- filelib:wildcard("data/*"), filelib:is_dir(F) ].
  12. join(_Node) -> filelib:ensure_dir("data/"), initialize(). % should be rsync or smth
  13. initialize() ->
  14. mnesia:create_schema([node()]),
  15. [ kvs:initialize(kvs_fs,Module) || Module <- kvs:modules() ],
  16. mnesia:wait_for_tables([ T#table.name || T <- kvs:tables()],infinity).
  17. index(_Tab,_Key,_Value) -> [].
  18. get(TableName, Key) ->
  19. HashKey = encode(base64:encode(crypto:hash(sha, term_to_binary(Key)))),
  20. Dir = lists:concat(["data/",TableName,"/"]),
  21. case file:read_file(lists:concat([Dir,HashKey])) of
  22. {ok,Binary} -> {ok,binary_to_term(Binary,[safe])};
  23. {error,Reason} -> {error,Reason} end.
  24. put(Records) when is_list(Records) -> lists:map(fun(Record) -> put(Record) end, Records);
  25. put(Record) ->
  26. TableName = element(1,Record),
  27. HashKey = encode(base64:encode(crypto:hash(sha, term_to_binary(element(2,Record))))),
  28. BinaryValue = term_to_binary(Record),
  29. Dir = lists:concat(["data/",TableName,"/"]),
  30. filelib:ensure_dir(Dir),
  31. File = lists:concat([Dir,HashKey]),
  32. file:write_file(File,BinaryValue,[write,raw,binary,sync]).
  33. delete(_Tab, _Key) -> case kvs:get(_Tab,_Key) of {ok,_} -> ok; {error,X} -> {error,X} end.
  34. count(RecordName) -> length(filelib:fold_files(lists:concat(["data/",RecordName]), "",true, fun(A,Acc)-> [A|Acc] end, [])).
  35. all(R) -> lists:flatten([ begin case file:read_file(File) of
  36. {ok,Binary} -> binary_to_term(Binary,[safe]);
  37. {error,_Reason} -> [] end end || File <-
  38. filelib:fold_files(lists:concat(["data/",R]), "",true, fun(A,Acc)-> [A|Acc] end, []) ]).
  39. seq(RecordName, Incr) -> kvs_mnesia:seq(RecordName, Incr).
  40. create_table(Name,_Options) -> filelib:ensure_dir(lists:concat(["data/",Name,"/"])).
  41. add_table_index(_Record, _Field) -> ok.
  42. % URL ENCODE
  43. encode(B) when is_binary(B) -> encode(binary_to_list(B));
  44. encode([C | Cs]) when C >= $a, C =< $z -> [C | encode(Cs)];
  45. encode([C | Cs]) when C >= $A, C =< $Z -> [C | encode(Cs)];
  46. encode([C | Cs]) when C >= $0, C =< $9 -> [C | encode(Cs)];
  47. encode([C | Cs]) when C == 16#20 -> [$+ | encode(Cs)];
  48. % unreserved
  49. encode([C = $- | Cs]) -> [C | encode(Cs)];
  50. encode([C = $_ | Cs]) -> [C | encode(Cs)];
  51. encode([C = 46 | Cs]) -> [C | encode(Cs)];
  52. encode([C = $! | Cs]) -> [C | encode(Cs)];
  53. encode([C = $~ | Cs]) -> [C | encode(Cs)];
  54. encode([C = $* | Cs]) -> [C | encode(Cs)];
  55. encode([C = 39 | Cs]) -> [C | encode(Cs)];
  56. encode([C = $( | Cs]) -> [C | encode(Cs)];
  57. encode([C = $) | Cs]) -> [C | encode(Cs)];
  58. encode([C | Cs]) when C =< 16#7f -> escape_byte(C) ++ encode(Cs);
  59. encode([C | Cs]) when (C >= 16#7f) and (C =< 16#07FF) ->
  60. escape_byte((C bsr 6) + 16#c0)
  61. ++ escape_byte(C band 16#3f + 16#80)
  62. ++ encode(Cs);
  63. encode([C | Cs]) when (C > 16#07FF) ->
  64. escape_byte((C bsr 12) + 16#e0) % (0xe0 | C >> 12)
  65. ++ escape_byte((16#3f band (C bsr 6)) + 16#80) % 0x80 | ((C >> 6) & 0x3f)
  66. ++ escape_byte(C band 16#3f + 16#80) % 0x80 | (C >> 0x3f)
  67. ++ encode(Cs);
  68. encode([C | Cs]) -> escape_byte(C) ++ encode(Cs);
  69. encode([]) -> [].
  70. hex_octet(N) when N =< 9 -> [$0 + N];
  71. hex_octet(N) when N > 15 -> hex_octet(N bsr 4) ++ hex_octet(N band 15);
  72. hex_octet(N) -> [N - 10 + $a].
  73. escape_byte(C) -> normalize(hex_octet(C)).
  74. normalize(H) when length(H) == 1 -> "%0" ++ H;
  75. normalize(H) -> "%" ++ H.
  76. dump() -> ok.