-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathgarbage.erl
107 lines (105 loc) · 3.96 KB
/
garbage.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
%choices on how to fix garbage_leaves
%1 we could cycle through every stem in the trie, check every pointer, and see if it is deleted.
%2 we could rethink how garbage and garbage_leaves work, so keepers is combined with delete_stuff. Instead of cycling through every stem, we walk down the
-module(garbage).
-export([garbage/2, garbage_leaves/2]).
garbage_leaves(KeeperLeaves, CFG) ->
{KeeperStems, KL} = keepers_backwards(KeeperLeaves, CFG),
%We need to update all the Keeper stems, so that the empty things aren't pointed to.
DeletedLeaves = delete_stuff(1, KL, ids:leaf(CFG)),
DeletedStems = delete_stuff(1, [1|KeeperStems], ids:stem(CFG)),%maybe delete_stuff should return the locations of all deleted stems and leaves, that way we know what to replace with 0s.
remove_bad_pointers(1, [1|KeeperStems], DeletedStems, CFG),%1 is for stems
remove_bad_pointers(2, [1|KeeperStems], DeletedLeaves, CFG),%2 is for leaves
ok.
remove_bad_pointers(_, [], _, _) -> ok;
remove_bad_pointers(PT, [K|KT], DS, CFG) ->
Stem = stem:get(K, CFG),
Pointers = stem:pointers(Stem),
Types = stem:types(Stem),
NewPointers = rbp2(PT, Pointers, Types, DS),
Stem2 = stem:update_pointers(Stem, NewPointers),
stem:update(K, Stem2, CFG),
remove_bad_pointers(PT, KT, DS, CFG).
rbp2(PT, Pointers, Types, DS) ->
X = rbp3(tuple_to_list(Pointers),
tuple_to_list(Types),
DS, PT),
list_to_tuple(X).
rbp3([], [], _, _) -> [];
rbp3([P|PT], [T|TT], DS, PointerType) ->
B = (lists:member(P, DS)) and (T == PointerType),
case B of
true ->
[0|rbp3(PT, TT, DS, PointerType)];
false -> [P|rbp3(PT, TT, DS, PointerType)]
end.
-spec garbage([stem:stem_p()], cfg:cfg()) -> ok.
garbage(KeeperRoots, CFG) ->
{KeeperStems, KeeperLeaves} = keepers(KeeperRoots, CFG),
delete_stuff(1, KeeperStems, ids:stem(CFG)),
delete_stuff(1, KeeperLeaves, ids:leaf(CFG)),
ok.
keepers_backwards(X, CFG) -> keepers_backwards(X, {[],[]}, CFG).
keepers_backwards([], X, _) -> X;
keepers_backwards([{Path, Root}|Leaves], {KS, KL}, CFG) ->
S = stem:get(Root, CFG),
{Stems, Leaf} = kb2(Path, S, [Root], CFG),
keepers_backwards(Leaves,
{append_no_repeats(Stems, KS),
append_no_repeats([Leaf], KL)},
CFG).
kb2([<<N:4>> | Path], Stem, Keepers, CFG) ->
NextType = stem:type(N+1, Stem),
PN = stem:pointer(N+1, Stem),
case NextType of
1 -> %another stem
Next = stem:get(PN, CFG),
kb2(Path, Next, append_no_repeats([PN], Keepers), CFG);
2 -> %leaf
{Keepers, PN}
end.
keepers([], _) -> {[], []};
keepers([R|Roots], CFG) -> %returns {keeperstems, keeperleaves}
case stem:get(R, CFG) of
error ->
{A, B} = keepers(Roots, CFG),
{[R|A],B};
S ->
{X, Y, MoreRoots} = stem_keepers(S),
{A, B} = keepers(MoreRoots++Roots, CFG),
{[R|append_no_repeats(X, A)],
append_no_repeats(Y, B)}
end.
append_no_repeats([],X) -> X;
append_no_repeats([A|Ta],X) ->
Bool2 = lists:member(A, X),
if
Bool2 -> append_no_repeats(Ta, X);
true -> append_no_repeats(Ta, [A|X])
end.
stem_keepers(S) ->
stem_keepers(S, 1, [], [], []).
stem_keepers(_, 17, Stems, Leaves, Roots) -> {Stems,Leaves, Roots};
stem_keepers(S, N, Stems, Leaves, MoreRoots) ->
P = stem:pointer(N, S),
{NewStems, NewLeaves, NewMoreRoots} =
case stem:type(N, S) of
0 -> {Stems, Leaves, MoreRoots};
1 ->
{[P|Stems], Leaves,[P|MoreRoots]};
2 -> {Stems, [P|Leaves], MoreRoots}
end,
stem_keepers(S, N+1, NewStems, NewLeaves, NewMoreRoots).
delete_stuff(_, Keepers, ID) ->
S = dump:highest(ID) div dump:word(ID),
delete_stuff(S, 1, Keepers, ID, []).
delete_stuff(S, N, Keepers, Id, Out) ->
Bool = lists:member(N, Keepers),
if
N>S -> Out;%we should go through the list of keepers and update any pointers that point to deleted data to instead point to 0.
Bool ->
delete_stuff(S, N+1, Keepers, Id, Out);
true ->
dump:delete(N, Id),
delete_stuff(S, N+1, Keepers, Id, [N|Out])
end.