Complete PB round-trip for #projection_v1{}, bleh
This commit is contained in:
parent
1b0cf06f1c
commit
725b10ba90
2 changed files with 285 additions and 50 deletions
180
src/machi.proto
180
src/machi.proto
|
@ -31,7 +31,7 @@ option java_outer_classname = "MachiPB";
|
||||||
|
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// enums
|
// Enums
|
||||||
//
|
//
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -52,9 +52,14 @@ enum Mpb_CSumType {
|
||||||
CSUM_TAG_SERVER_REGEN_SHA = 3;
|
CSUM_TAG_SERVER_REGEN_SHA = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Mpb_ProjType {
|
||||||
|
PRIVATE = 20;
|
||||||
|
PUBLIC = 21;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// basic data types
|
// Basic data types
|
||||||
//
|
//
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -72,7 +77,7 @@ message Mpb_ChunkCSum {
|
||||||
}
|
}
|
||||||
|
|
||||||
// epoch_id() type
|
// epoch_id() type
|
||||||
message Mpb_EpochId {
|
message Mpb_EpochID {
|
||||||
required uint32 epoch_num = 1;
|
required uint32 epoch_num = 1;
|
||||||
required bytes epoch_csum = 2;
|
required bytes epoch_csum = 2;
|
||||||
}
|
}
|
||||||
|
@ -94,7 +99,7 @@ message Mpb_P_Srvr {
|
||||||
|
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// requests & responses
|
// Requests & responses
|
||||||
//
|
//
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -108,7 +113,7 @@ message Mpb_ErrorResp {
|
||||||
|
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// High Level API requests:
|
// High level API requests:
|
||||||
//
|
//
|
||||||
// echo() : Mpb_EchoReq and Mpb_EchoResp
|
// echo() : Mpb_EchoReq and Mpb_EchoResp
|
||||||
// auth() : Mpb_AuthReq and Mpb_AuthResp
|
// auth() : Mpb_AuthReq and Mpb_AuthResp
|
||||||
|
@ -214,7 +219,7 @@ message Mpb_ListFilesResp {
|
||||||
|
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// request & response wrapper
|
// High level API request & response wrapper
|
||||||
//
|
//
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -248,7 +253,7 @@ message Mpb_Response {
|
||||||
// Generic error response, typically used when something quite
|
// Generic error response, typically used when something quite
|
||||||
// bad/unexpected happened within the server.
|
// bad/unexpected happened within the server.
|
||||||
// Clients should always check this response and, if defined,
|
// Clients should always check this response and, if defined,
|
||||||
// ignroe any request-specific response at codes 10+.
|
// ignore any request-specific response at codes 10+.
|
||||||
optional Mpb_ErrorResp generic = 2;
|
optional Mpb_ErrorResp generic = 2;
|
||||||
|
|
||||||
// Specific responses.
|
// Specific responses.
|
||||||
|
@ -260,3 +265,164 @@ message Mpb_Response {
|
||||||
optional Mpb_ChecksumListResp checksum_list = 15;
|
optional Mpb_ChecksumListResp checksum_list = 15;
|
||||||
optional Mpb_ListFilesResp list_files = 16;
|
optional Mpb_ListFilesResp list_files = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Low level API data types
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////
|
||||||
|
|
||||||
|
enum Mpb_Mode {
|
||||||
|
AP_MODE = 30;
|
||||||
|
CP_MODE = 31;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Mpb_Now {
|
||||||
|
required uint64 sec = 1;
|
||||||
|
required uint32 usec = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Mpb_MembersDictEntry {
|
||||||
|
required string key = 1;
|
||||||
|
required Mpb_P_Srvr val = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Mpb_ProjectionV1 {
|
||||||
|
required uint32 epoch_number = 1;
|
||||||
|
required bytes epoch_csum = 2;
|
||||||
|
required string author_server = 3;
|
||||||
|
repeated string all_members = 4;
|
||||||
|
required Mpb_Now creation_time = 5;
|
||||||
|
required Mpb_Mode mode = 6;
|
||||||
|
repeated string upi = 7;
|
||||||
|
repeated string repairing = 8;
|
||||||
|
repeated string down = 9;
|
||||||
|
optional bytes opaque_flap = 10;
|
||||||
|
optional bytes opaque_inner = 11;
|
||||||
|
required bytes opaque_dbg = 12;
|
||||||
|
required bytes opaque_dbg2 = 13;
|
||||||
|
repeated Mpb_MembersDictEntry members_dict = 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Low level API requests:
|
||||||
|
//
|
||||||
|
// echo() : Mpb_EchoReq and Mpb_EchoResp (reused from high level API)
|
||||||
|
// auth() : Mpb_AuthReq and Mpb_AuthResp (reused from high level API)
|
||||||
|
// get_latest_epochid() : Mpb_GetLatestEpochIDReq and Mpb_GetLatestEpochIDResp
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////
|
||||||
|
|
||||||
|
// Low level API: get_latest_epochid() request & response
|
||||||
|
|
||||||
|
message Mpb_LL_GetLatestEpochIDReq {
|
||||||
|
required Mpb_ProjType type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Mpb_LL_GetLatestEpochIDResp {
|
||||||
|
required uint32 Mpb_GeneralStatusCode = 1;
|
||||||
|
optional Mpb_EpochID epoch_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Low level API: read_latest_projection() request & response
|
||||||
|
|
||||||
|
message Mpb_LL_ReadLatestProjectionReq {
|
||||||
|
required Mpb_ProjType type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Mpb_LL_ReadLatestProjectionResp {
|
||||||
|
required uint32 Mpb_GeneralStatusCode = 1;
|
||||||
|
optional Mpb_ProjectionV1 proj = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Low level API: read_projection() request & response
|
||||||
|
|
||||||
|
message Mpb_LL_ReadProjectionReq {
|
||||||
|
required Mpb_ProjType type = 1;
|
||||||
|
required uint32 epoch_number = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Mpb_LL_ReadProjectionResp {
|
||||||
|
required uint32 Mpb_GeneralStatusCode = 1;
|
||||||
|
optional Mpb_ProjectionV1 proj = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Low level API: write_projection() request & response
|
||||||
|
|
||||||
|
message Mpb_LL_WriteProjectionReq {
|
||||||
|
required Mpb_ProjType type = 1;
|
||||||
|
required Mpb_ProjectionV1 proj = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Mpb_LL_WriteProjectionResp {
|
||||||
|
required uint32 Mpb_GeneralStatusCode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Low level API: get_all_projections() request & response
|
||||||
|
|
||||||
|
message Mpb_LL_GetAllProjectionsReq {
|
||||||
|
required Mpb_ProjType type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Mpb_LL_GetAllProjectionsResp {
|
||||||
|
required uint32 Mpb_GeneralStatusCode = 1;
|
||||||
|
repeated Mpb_ProjectionV1 proj = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Low level API: list_all_projections() request & response
|
||||||
|
|
||||||
|
message Mpb_LL_ListAllProjectionsReq {
|
||||||
|
required Mpb_ProjType type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Mpb_LL_ListAllProjectionsResp {
|
||||||
|
required uint32 Mpb_GeneralStatusCode = 1;
|
||||||
|
repeated uint32 epochs = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Low API request & response wrapper
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////
|
||||||
|
|
||||||
|
message Mpb_LL_Request {
|
||||||
|
// TODO: If we wish to support pipelined requests sometime in the
|
||||||
|
// future, this is the placeholder to do it.
|
||||||
|
required bytes req_id = 1;
|
||||||
|
|
||||||
|
// The client should only define one request message. If the client
|
||||||
|
// includes multiple requests here, the server may pick/choose an
|
||||||
|
// arbitrary one.
|
||||||
|
// NOTE: The erlang protobuffs compiler doesn't support 'oneof'.
|
||||||
|
// But 'oneof' appears to be a very tiny memory optimization
|
||||||
|
// that not all languages might care about? (Erlang doesn't)
|
||||||
|
optional Mpb_EchoReq echo = 10; // Re-use from high level API
|
||||||
|
optional Mpb_AuthReq auth = 11; // Re-use from high level API
|
||||||
|
optional Mpb_LL_GetLatestEpochIDReq = 12;
|
||||||
|
optional Mpb_LL_ReadLatestProjectionReq = 13;
|
||||||
|
optional Mpb_LL_ReadProjectionReq = 14;
|
||||||
|
optional Mpb_LL_WriteProjectionReq = 15;
|
||||||
|
optional Mpb_LL_GetAllProjectionsReq = 16;
|
||||||
|
optional Mpb_LL_ListAllProjectionsReq = 17;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Mpb_LL_Response {
|
||||||
|
// TODO: If we wish to support pipelined requests sometime in the
|
||||||
|
// future, this is the placeholder to do it.
|
||||||
|
required bytes req_id = 1;
|
||||||
|
|
||||||
|
// The server will define only one of the optional responses below.
|
||||||
|
|
||||||
|
// Generic error response, typically used when something quite
|
||||||
|
// bad/unexpected happened within the server.
|
||||||
|
// Clients should always check this response and, if defined,
|
||||||
|
// ignore any request-specific response at codes 10+.
|
||||||
|
optional Mpb_ErrorResp generic = 2;
|
||||||
|
|
||||||
|
// Specific responses.
|
||||||
|
optional Mpb_EchoResp echo = 10; // Re-use from high level API
|
||||||
|
optional Mpb_AuthResp auth = 11; // Re-use from high level API
|
||||||
|
optional Mpb_LL_GetLatestEpochIDResp = 12;
|
||||||
|
}
|
||||||
|
|
|
@ -30,70 +30,131 @@
|
||||||
-compile(export_all).
|
-compile(export_all).
|
||||||
-endif. % TEST
|
-endif. % TEST
|
||||||
|
|
||||||
enc_p_srvr(#p_srvr{name=Name,
|
enc_p_srvr(P) ->
|
||||||
|
machi_pb:encode_mpb_p_srvr(conv_from_p_srvr(P)).
|
||||||
|
|
||||||
|
dec_p_srvr(Bin) ->
|
||||||
|
conv_to_p_srvr(machi_pb:decode_mpb_p_srvr(Bin)).
|
||||||
|
|
||||||
|
conv_from_p_srvr(#p_srvr{name=Name,
|
||||||
proto_mod=ProtoMod,
|
proto_mod=ProtoMod,
|
||||||
address=Address,
|
address=Address,
|
||||||
port=Port,
|
port=Port,
|
||||||
props=Props}) ->
|
props=Props}) ->
|
||||||
machi_pb:encode_mpb_p_srvr(#mpb_p_srvr{name=to_list(Name),
|
#mpb_p_srvr{name=to_list(Name),
|
||||||
proto_mod=to_list(ProtoMod),
|
proto_mod=to_list(ProtoMod),
|
||||||
address=to_list(Address),
|
address=to_list(Address),
|
||||||
port=to_list(Port),
|
port=to_list(Port),
|
||||||
props=todo_enc_opaque(Props)}).
|
props=enc_sexp(Props)}.
|
||||||
|
|
||||||
dec_p_srvr(Bin) ->
|
conv_to_p_srvr(#mpb_p_srvr{name=Name,
|
||||||
#mpb_p_srvr{name=Name,
|
proto_mod=ProtoMod,
|
||||||
proto_mod=ProtoMod,
|
address=Address,
|
||||||
address=Address,
|
port=Port,
|
||||||
port=Port,
|
props=Props}) ->
|
||||||
props=Props} = machi_pb:decode_mpb_p_srvr(Bin),
|
|
||||||
#p_srvr{name=to_atom(Name),
|
#p_srvr{name=to_atom(Name),
|
||||||
proto_mod=to_atom(ProtoMod),
|
proto_mod=to_atom(ProtoMod),
|
||||||
address=to_list(Address),
|
address=to_list(Address),
|
||||||
port=to_integer(Port),
|
port=to_integer(Port),
|
||||||
props=todo_dec_opaque(Props)}.
|
props=dec_sexp(to_list(Props))}.
|
||||||
|
|
||||||
enc_projection_v1(#projection_v1{dbg=Dbg,
|
enc_projection_v1(P) ->
|
||||||
dbg2=Dbg2,
|
%% Awww, flatten it here
|
||||||
members_dict=MembersDict} = P) ->
|
list_to_binary(
|
||||||
term_to_binary(P#projection_v1{dbg=enc_sexp(Dbg),
|
machi_pb:encode_mpb_projectionv1(conv_from_projection_v1(P))).
|
||||||
dbg2=enc_sexp(Dbg2),
|
|
||||||
members_dict=enc_members_dict(MembersDict)}).
|
|
||||||
|
|
||||||
dec_projection_v1(Bin) ->
|
dec_projection_v1(Bin) ->
|
||||||
P = #projection_v1{dbg=Dbg,
|
conv_to_projection_v1(machi_pb:decode_mpb_projectionv1(Bin)).
|
||||||
dbg2=Dbg2,
|
|
||||||
members_dict=MembersDict} = binary_to_term(Bin),
|
conv_from_projection_v1(#projection_v1{epoch_number=Epoch,
|
||||||
P#projection_v1{dbg=dec_sexp(Dbg),
|
epoch_csum=CSum,
|
||||||
dbg2=dec_sexp(Dbg2),
|
author_server=Author,
|
||||||
members_dict=dec_members_dict(MembersDict)}.
|
all_members=AllMembers,
|
||||||
|
creation_time=CTime,
|
||||||
|
mode=Mode,
|
||||||
|
upi=UPI,
|
||||||
|
repairing=Repairing,
|
||||||
|
down=Down,
|
||||||
|
flap=Flap,
|
||||||
|
inner=Inner,
|
||||||
|
dbg=Dbg,
|
||||||
|
dbg2=Dbg2,
|
||||||
|
members_dict=MembersDict}) ->
|
||||||
|
#mpb_projectionv1{epoch_number=Epoch,
|
||||||
|
epoch_csum=CSum,
|
||||||
|
author_server=to_list(Author),
|
||||||
|
all_members=[to_list(X) || X <- AllMembers],
|
||||||
|
creation_time=conv_from_now(CTime),
|
||||||
|
mode=conv_from_mode(Mode),
|
||||||
|
upi=[to_list(X) || X <- UPI],
|
||||||
|
repairing=[to_list(X) || X <- Repairing],
|
||||||
|
down=[to_list(X) || X <- Down],
|
||||||
|
opaque_flap=enc_optional_sexp(Flap),
|
||||||
|
opaque_inner=enc_optional_sexp(Inner),
|
||||||
|
opaque_dbg=enc_sexp(Dbg),
|
||||||
|
opaque_dbg2=enc_sexp(Dbg2),
|
||||||
|
members_dict=conv_from_members_dict(MembersDict)}.
|
||||||
|
|
||||||
|
conv_to_projection_v1(#mpb_projectionv1{epoch_number=Epoch,
|
||||||
|
epoch_csum=CSum,
|
||||||
|
author_server=Author,
|
||||||
|
all_members=AllMembers,
|
||||||
|
creation_time=CTime,
|
||||||
|
mode=Mode,
|
||||||
|
upi=UPI,
|
||||||
|
repairing=Repairing,
|
||||||
|
down=Down,
|
||||||
|
opaque_flap=Flap,
|
||||||
|
opaque_inner=Inner,
|
||||||
|
opaque_dbg=Dbg,
|
||||||
|
opaque_dbg2=Dbg2,
|
||||||
|
members_dict=MembersDict}) ->
|
||||||
|
#projection_v1{epoch_number=Epoch,
|
||||||
|
epoch_csum=CSum,
|
||||||
|
author_server=to_atom(Author),
|
||||||
|
all_members=[to_atom(X) || X <- AllMembers],
|
||||||
|
creation_time=conv_to_now(CTime),
|
||||||
|
mode=conv_to_mode(Mode),
|
||||||
|
upi=[to_atom(X) || X <- UPI],
|
||||||
|
repairing=[to_atom(X) || X <- Repairing],
|
||||||
|
down=[to_atom(X) || X <- Down],
|
||||||
|
flap=dec_optional_sexp(Flap),
|
||||||
|
inner=dec_optional_sexp(Inner),
|
||||||
|
dbg=dec_sexp(Dbg),
|
||||||
|
dbg2=dec_sexp(Dbg2),
|
||||||
|
members_dict=conv_to_members_dict(MembersDict)}.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
enc_sexp(T) ->
|
enc_sexp(T) ->
|
||||||
lists:flatten(io_lib:format("~w.", [T])).
|
lists:flatten(io_lib:format("~w.", [T])).
|
||||||
|
|
||||||
dec_sexp(String) ->
|
dec_sexp(Bin) when is_binary(Bin) ->
|
||||||
|
dec_sexp(binary_to_list(Bin));
|
||||||
|
dec_sexp(String) when is_list(String) ->
|
||||||
{ok,Tks,_} = erl_scan:string(String),
|
{ok,Tks,_} = erl_scan:string(String),
|
||||||
{ok,E} = erl_parse:parse_exprs(Tks),
|
{ok,E} = erl_parse:parse_exprs(Tks),
|
||||||
{value,Funs,_} = erl_eval:exprs(E,[]),
|
{value,Funs,_} = erl_eval:exprs(E,[]),
|
||||||
Funs.
|
Funs.
|
||||||
|
|
||||||
enc_members_dict(D) ->
|
enc_optional_sexp(undefined) ->
|
||||||
|
undefined;
|
||||||
|
enc_optional_sexp(T) ->
|
||||||
|
enc_sexp(T).
|
||||||
|
|
||||||
|
dec_optional_sexp(undefined) ->
|
||||||
|
undefined;
|
||||||
|
dec_optional_sexp(T) ->
|
||||||
|
dec_sexp(T).
|
||||||
|
|
||||||
|
conv_from_members_dict(D) ->
|
||||||
%% Use list_to_binary() here to "flatten" the serialized #p_srvr{}
|
%% Use list_to_binary() here to "flatten" the serialized #p_srvr{}
|
||||||
[{K, list_to_binary(enc_p_srvr(V))} || {K, V} <- orddict:to_list(D)].
|
[#mpb_membersdictentry{key=to_list(K), val=conv_from_p_srvr(V)} ||
|
||||||
|
{K, V} <- orddict:to_list(D)].
|
||||||
|
|
||||||
dec_members_dict(List) ->
|
conv_to_members_dict(List) ->
|
||||||
orddict:from_list([{K, dec_p_srvr(V)} || {K, V} <- List]).
|
orddict:from_list([{to_atom(K), conv_to_p_srvr(V)} ||
|
||||||
|
#mpb_membersdictentry{key=K, val=V} <- List]).
|
||||||
to_binary(X) when is_list(X) ->
|
|
||||||
list_to_binary(X);
|
|
||||||
to_binary(X) when is_integer(X) ->
|
|
||||||
list_to_binary(integer_to_list(X));
|
|
||||||
to_binary(X) when is_atom(X) ->
|
|
||||||
erlang:atom_to_binary(X, latin1);
|
|
||||||
to_binary(X) when is_binary(X) ->
|
|
||||||
X.
|
|
||||||
|
|
||||||
to_list(X) when is_atom(X) ->
|
to_list(X) when is_atom(X) ->
|
||||||
atom_to_list(X);
|
atom_to_list(X);
|
||||||
|
@ -118,8 +179,16 @@ to_integer(X) when is_binary(X) ->
|
||||||
to_integer(X) when is_integer(X) ->
|
to_integer(X) when is_integer(X) ->
|
||||||
X.
|
X.
|
||||||
|
|
||||||
todo_enc_opaque(X) ->
|
conv_from_now({A,B,C}) ->
|
||||||
erlang:term_to_binary(X).
|
#mpb_now{sec=(1000000 * A) + B,
|
||||||
|
usec=C}.
|
||||||
|
|
||||||
|
conv_to_now(#mpb_now{sec=Sec, usec=USec}) ->
|
||||||
|
{Sec div 1000000, Sec rem 1000000, USec}.
|
||||||
|
|
||||||
|
conv_from_mode(ap_mode) -> 'AP_MODE';
|
||||||
|
conv_from_mode(cp_mode) -> 'CP_MODE'.
|
||||||
|
|
||||||
|
conv_to_mode('AP_MODE') -> ap_mode;
|
||||||
|
conv_to_mode('CP_MODE') -> cp_mode.
|
||||||
|
|
||||||
todo_dec_opaque(X) ->
|
|
||||||
erlang:binary_to_term(X).
|
|
||||||
|
|
Loading…
Reference in a new issue