| 1 |
|
%% Copyright (c) 2022 Peter Morgan <peter.james.morgan@gmail.com> |
| 2 |
|
%% |
| 3 |
|
%% Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 |
|
%% you may not use this file except in compliance with the License. |
| 5 |
|
%% You may obtain a copy of the License at |
| 6 |
|
%% |
| 7 |
|
%% http://www.apache.org/licenses/LICENSE-2.0 |
| 8 |
|
%% |
| 9 |
|
%% Unless required by applicable law or agreed to in writing, software |
| 10 |
|
%% distributed under the License is distributed on an "AS IS" BASIS, |
| 11 |
|
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 |
|
%% See the License for the specific language governing permissions and |
| 13 |
|
%% limitations under the License. |
| 14 |
|
|
| 15 |
|
|
| 16 |
|
-module(mcd_emulator_binary). |
| 17 |
|
|
| 18 |
|
|
| 19 |
|
-export([recv/1]). |
| 20 |
|
-include_lib("kernel/include/logger.hrl"). |
| 21 |
|
-include_lib("stdlib/include/ms_transform.hrl"). |
| 22 |
|
-include("mcd_emulator.hrl"). |
| 23 |
|
|
| 24 |
|
|
| 25 |
|
recv(#{message := #{extra := #{expiration := Expiry, |
| 26 |
|
flags := Flags}, |
| 27 |
|
header := #{magic := request, |
| 28 |
|
cas := 0, |
| 29 |
|
opcode := set} = Header, |
| 30 |
|
key := Key, |
| 31 |
|
value := Value}, |
| 32 |
|
data := #{table := Table}}) -> |
| 33 |
|
|
| 34 |
4 |
case mcd_config:maximum(value_size) of |
| 35 |
|
Maximum when byte_size(Value) > Maximum -> |
| 36 |
:-( |
ets:delete(Table, Key), |
| 37 |
:-( |
{continue, |
| 38 |
|
{encode, #{header => response_header(Header, server_error)}}}; |
| 39 |
|
|
| 40 |
|
_SmallerThanMaximum -> |
| 41 |
4 |
ets:insert(Table, |
| 42 |
|
#entry{key = Key, |
| 43 |
|
flags = Flags, |
| 44 |
|
expiry = Expiry, |
| 45 |
|
data = Value}), |
| 46 |
4 |
{continue, |
| 47 |
|
[{encode, |
| 48 |
|
#{header => response_header(Header, no_error)}}, |
| 49 |
|
{expire, #{key => Key, seconds => Expiry}}]} |
| 50 |
|
end; |
| 51 |
|
|
| 52 |
|
recv(#{message := #{header := #{magic := request, |
| 53 |
|
cas := 0, |
| 54 |
|
opcode := get} = Header, |
| 55 |
|
key := Key}, |
| 56 |
|
data := #{table := Table}}) -> |
| 57 |
6 |
case ets:lookup(Table, Key) of |
| 58 |
|
[#entry{data = Data, flags = Flags}] -> |
| 59 |
3 |
{continue, |
| 60 |
|
{encode, |
| 61 |
|
#{header => response_header(Header, no_error), |
| 62 |
|
extra => #{flags => Flags}, |
| 63 |
|
value => Data}}}; |
| 64 |
|
|
| 65 |
|
[] -> |
| 66 |
3 |
{continue, |
| 67 |
|
{encode, |
| 68 |
|
#{header => response_header(Header, key_not_found)}}} |
| 69 |
|
end; |
| 70 |
|
|
| 71 |
|
recv(#{message := #{header := #{magic := request, |
| 72 |
|
cas := 0, |
| 73 |
|
opcode := delete} = Header, |
| 74 |
|
key := Key}, |
| 75 |
|
data := #{table := Table}}) -> |
| 76 |
2 |
ets:delete(Table, Key), |
| 77 |
2 |
{continue, {encode, #{header => response_header(Header, no_error)}}}; |
| 78 |
|
|
| 79 |
|
recv(#{message := #{header := #{magic := request, |
| 80 |
|
opcode := no_op} = Header}}) -> |
| 81 |
1 |
{continue, {encode, #{header => response_header(Header)}}}; |
| 82 |
|
|
| 83 |
|
recv(#{message := #{header := #{magic := request, |
| 84 |
|
opcode := stat} = Header}}) -> |
| 85 |
:-( |
{continue, |
| 86 |
|
lists:foldl( |
| 87 |
|
fun |
| 88 |
|
({Key, Value}, A) when is_integer(Value) -> |
| 89 |
:-( |
[{encode, #{header => response_header(Header), |
| 90 |
|
key => atom_to_binary(Key), |
| 91 |
|
value => integer_to_binary(Value)}} | A] |
| 92 |
|
end, |
| 93 |
|
[{encode, #{header => response_header(Header)}}], |
| 94 |
|
mcd_stat:all())}; |
| 95 |
|
|
| 96 |
|
recv(#{message := #{header := #{magic := request, |
| 97 |
|
opcode := flush} = Header}, |
| 98 |
|
data := #{table := Table}}) -> |
| 99 |
2 |
ets:delete_all_objects(Table), |
| 100 |
2 |
{continue, {encode, #{header => response_header(Header)}}}; |
| 101 |
|
|
| 102 |
|
recv(#{message := #{header := #{magic := request, |
| 103 |
|
opcode := version} = Header}}) -> |
| 104 |
:-( |
{continue, |
| 105 |
|
{encode, |
| 106 |
|
#{header => response_header(Header), value => <<"1.3.1">>}}}. |
| 107 |
|
|
| 108 |
|
|
| 109 |
|
response_header(RequestHeader) -> |
| 110 |
3 |
?FUNCTION_NAME(RequestHeader, no_error). |
| 111 |
|
|
| 112 |
|
|
| 113 |
|
response_header(RequestHeader, Status) -> |
| 114 |
15 |
maps:without( |
| 115 |
|
[vbucket_id], |
| 116 |
|
RequestHeader#{magic := response, |
| 117 |
|
status => Status}). |