Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 154 lines (105 sloc) 6.079 kB
ddfa023 adding digraph exporter
Ryan Maclear authored
1 h1. Exporting to an Erlang digraph
2
3 +Contributed By:+ [[Ryan Maclear|https://github.com/ryanmaclear]]
4
15771f6 Fixing spelling
Ryan Maclear authored
5 [[Source File on GitHub|https://github.com/basho/riak_function_contrib/blob/master/other/erlang/digraph_exporter.erl]]
ddfa023 adding digraph exporter
Ryan Maclear authored
6
6f769bc checking documentation
Ryan Maclear authored
7 This Erlang module allows you to construct an Erlang digraph from objects in a bucket. Each object will result in a vertex being created, identified by the key, and optionally, the object value will be used for the vertex label. Links on objects will result in edges being created as specified by each link. An optional filter list can be specified which will result in only specific objects matching the filter being used to construct the digraph. If the filter list is omitted, the entire bucket will be used.
ddfa023 adding digraph exporter
Ryan Maclear authored
8
836dc90 Documenting digraph_exporter
Ryan Maclear authored
9 This function can be used to recreate digraphs stored in a bucket using [[Digraph Importer|digraph_importer]] found elsewhere on this site.
ddfa023 adding digraph exporter
Ryan Maclear authored
10
836dc90 Documenting digraph_exporter
Ryan Maclear authored
11 The function takes 5 or 6 parameters:
80f50b5 fixing doc layout
Ryan Maclear authored
12 # digraph_exporter:export_digraph(server, port, bucket, digraph, use object value). or
13 # digraph_exporter:export_digraph(server, port, bucket, filter_list, digraph, use object value).
ddfa023 adding digraph exporter
Ryan Maclear authored
14
836dc90 Documenting digraph_exporter
Ryan Maclear authored
15 h3. Notes
9d5aef8 fixing layout
Ryan Maclear authored
16
6f769bc checking documentation
Ryan Maclear authored
17 The function uses the Erlang Protocol Buffer client, so the correct ip address and port must be specified.
18
836dc90 Documenting digraph_exporter
Ryan Maclear authored
19 The digraph needs to be passed into the function, so it needs to exist and have the correct properties (eg. [cyclic, protected]).
20
21 Since digraphs are created in ETS, there is a finite limit on the number of vertices and edges that can be created, so be sure that you use filter lists where necessary.
22
23 Unfortunately, edges cannot be added to digraphs unless both vertices exist, so all the vertices are created first, and then only are the edges added. This means that the list of objects is traversed twice, and might have an impact on performance. Edges that cannot be created due to one or both vertices missing will be ignored.
24
25 The content-type of the object is used when creating the digraph label. If the content-type is application/x-erlang-binary, the label will be an erlang term, otherwise it will be a string (list).
26
27 Setting the last parameter of the function to false will result in all vetices having a label of [].
28
29 h3. Examples
30
fd8d8cc wip
Ryan Maclear authored
31 (*Note*: The cluster used for the example below is the dev cluster used in the Fast Track, so the port number used is 8082, and not the default port of 8087).
94fd0ce adding notes on port number
Ryan Maclear authored
32
836dc90 Documenting digraph_exporter
Ryan Maclear authored
33 To create a digraph from an entire bucket, using the object values for the label:
34
35 ```erlang
9d5aef8 fixing layout
Ryan Maclear authored
36 A = digraph:new([cyclic, protected]).
836dc90 Documenting digraph_exporter
Ryan Maclear authored
37
38 digraph_exporter:export_digraph("127.0.0.1", 8082, <<"networks">>, A, true).
39 ```
40
41 To create a digraph from an entire bucket, with vetex labels:
42
43 ```erlang
9d5aef8 fixing layout
Ryan Maclear authored
44 A = digraph:new([cyclic, protected]).
836dc90 Documenting digraph_exporter
Ryan Maclear authored
45
46 digraph_exporter:export_digraph("127.0.0.1", 8082, <<"networks">>, A, false).
47 ```
48
80f50b5 fixing doc layout
Ryan Maclear authored
49 To create a digraph from a bucket, using only objects with keys starting with &quot;home&quot;, using the object values for the label:
836dc90 Documenting digraph_exporter
Ryan Maclear authored
50
51 ```erlang
52 A= digraph:new([cyclic, protected]).
53
54 digraph_exporter:export_digraph("127.0.0.1", 8082, <<"networks">>, [<<"starts_with">>,<<"home">>], A, true).
55 ```
56
57 h3. Source
58
59 ```erlang
60 -module(digraph_exporter).
61
62 -export([export_digraph/5, export_digraph/6]).
63
64 %% @spec export_digraph(Server :: ip_address(),
65 %% Port :: integer(),
66 %% Bucket :: bucket(),
67 %% Ref :: digraph(),
68 %% UseValue :: boolean()) -> ok.
69
70 export_digraph(Server, Port, Bucket, Ref, UseValue) ->
71 export_digraph(Server, Port, Bucket, undefined, Ref, UseValue).
72
73 %% @spec export_digraph(Server :: ip_address(),
74 %% Port :: integer(),
75 %% Bucket :: bucket(),
76 %% FilterList :: list(),
77 %% Ref :: digraph(),
78 %% UseValue :: boolean()) -> ok.
79
80 export_digraph(Server, Port, Bucket, FilterList, Ref, UseValue) ->
81 {ok, Client} = riakc_pb_socket:start(Server, Port),
82
83 Input =
84 case FilterList of
85 undefined ->
86 Bucket;
87 _ ->
88 {Bucket, [FilterList]}
89 end,
90
91 MapFun = build_map_fun(),
92
93 MapPhase = {map, {qfun, MapFun}, notused, true},
94 Query = [MapPhase],
95
96 {ok, [{_, Data}]} = riakc_pb_socket:mapred(Client, Input, Query),
97
98 build_vertices(Ref, UseValue, Data),
99 add_edges(Ref, Data).
100
101
102 build_vertices(_Ref, _UseValue, []) -> ok;
103 build_vertices(Ref, UseValue, [{Key, Value, ContentType, _}|T]) ->
104 Label =
105 case UseValue of
106 true ->
107 case ContentType of
108 "application/x-erlang-binary" ->
109 binary_to_term(Value);
110 _ ->
111 binary_to_list(Value)
112 end;
113 false -> ""
114 end,
115
116 Vertex = binary_to_list(Key),
117
118 digraph:add_vertex(Ref, Vertex, Label),
119 io:format("vertex: ~s~n", [Vertex]),
120 build_vertices(Ref, UseValue, T).
121
122
123 add_edges(_Ref, []) -> ok;
124 add_edges(Ref, [{Key, _, _, Links}|T]) ->
125 lists:foreach(fun({{_, Dest}, Tag}) ->
126 Edge = binary_to_list(Tag),
127 VSrc = binary_to_list(Key),
128 VDest = binary_to_list(Dest),
129 digraph:add_edge(Ref, Edge, VSrc, VDest, ""),
130 io:format("edge: ~s~n", [Edge])
131 end, Links),
132 add_edges(Ref, T).
133
134
135 build_map_fun() ->
136 MapFun = "fun(Object, _KeyData, _Args) ->
137 [{MetaDataDict, Value}] = riak_object:get_contents(Object),
138
139 MetaData = dict:to_list(MetaDataDict),
140
9d5aef8 fixing layout
Ryan Maclear authored
141 ContentType = proplists:get_value(<<\\"content-type\\">>, MetaData, \\"\\"),
142 Links = proplists:get_value(<<\\"Links\\">>, MetaData, []),
836dc90 Documenting digraph_exporter
Ryan Maclear authored
143
144 [{riak_object:key(Object), Value, ContentType, Links}]
145 end.",
146
147 {ok, Tokens, _} = erl_scan:string(MapFun),
148 {ok, [Form]} = erl_parse:parse_exprs(Tokens),
149 Bindings = erl_eval:new_bindings(),
150 {value, Fun, _} = erl_eval:expr(Form, Bindings),
151 Fun.
152 ```
ddfa023 adding digraph exporter
Ryan Maclear authored
153
Something went wrong with that request. Please try again.