Skip to content
This repository has been archived by the owner on Oct 22, 2021. It is now read-only.

Commit

Permalink
lots of unrelated stuff jammed in one commit to upset people.
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert Newson committed Mar 14, 2011
1 parent 73c9bd6 commit 33f6f65
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 162 deletions.
20 changes: 10 additions & 10 deletions include/monic.hrl
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
-define(BUFFER_SIZE, 64*1024).

-record(index, {
key,
cookie,
location,
size,
key :: binary(),
cookie :: integer(),
location :: integer(),
size :: integer(),
last_modified,
deleted=false
deleted=false :: boolean()
}).

-record(header, {
key,
cookie,
size,
key :: binary(),
cookie :: integer(),
size :: integer(),
last_modified,
deleted=false
deleted=false :: boolean()
}).

-record(footer, {
sha
sha :: binary()
}).
4 changes: 2 additions & 2 deletions priv/dispatch.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
%%-*- mode: erlang -*-

{[file], monic_file_resource, [{root, "tmp"}]}.
{[file, key, cookie], monic_item_resource, [{root, "tmp"}]}.
{[file], monic_container_resource, [{root, "tmp"}]}.
{[file, cookie, key], monic_item_resource, [{root, "tmp"}]}.
57 changes: 57 additions & 0 deletions src/monic_container_resource.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
%% Copyright 2011 Cloudant
%%
%% Licensed under the Apache License, Version 2.0 (the "License"); you may not
%% use this file except in compliance with the License. You may obtain a copy of
%% the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
%% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
%% License for the specific language governing permissions and limitations under
%% the License.

-module(monic_container_resource).
-export([init/1,
allowed_methods/2,
content_types_accepted/2,
content_types_provided/2,
delete_resource/2,
is_conflict/2,
resource_exists/2]).
-export([get_container/2, put_container/2]).

-include_lib("webmachine/include/webmachine.hrl").
-include("monic.hrl").

-define(CONTAINER_MIME_TYPE, "application/vnd.com.cloudant.monic.container+json").

init(ConfigProps) ->
{ok, ConfigProps}.

allowed_methods(ReqData, Context) ->
{['DELETE', 'GET', 'PUT'], ReqData, Context}.

content_types_accepted(ReqData, Context) ->
{[{?CONTAINER_MIME_TYPE, put_container}], ReqData, Context}.

content_types_provided(ReqData, Context) ->
{[{?CONTAINER_MIME_TYPE, get_container}], ReqData, Context}.

delete_resource(ReqData, Context) ->
{file:delete(monic_utils:path(ReqData, Context)) == ok, ReqData, Context}.

is_conflict(ReqData, Context) ->
{monic_utils:exists(ReqData, Context), ReqData, Context}.

resource_exists(ReqData, Context) ->
{monic_utils:exists(ReqData, Context), ReqData, Context}.

%% private functions

get_container(ReqData, Context) ->
{"{\"ok\": true}", ReqData, Context}.

put_container(ReqData, Context) ->
{file:write_file(monic_utils:path(ReqData, Context), <<>>, [exclusive]) == ok, ReqData, Context}.
56 changes: 36 additions & 20 deletions src/monic_file.erl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
-include("monic.hrl").

%% public API
-export([open/1, open_new/1, close/1, add/4, info/3, read/3]).
-export([open/1, open_new/1, close/1, add/5, info/3, read/3]).

%% gen_server API
-export([init/1, terminate/2, code_change/3,handle_call/3, handle_cast/2, handle_info/2]).
Expand All @@ -29,12 +29,16 @@
main_fd=nil,
next_index,
reset_pos,
sha,
write_pos,
writer=nil
}).

-type streambody() :: fun((binary(), fun() | done) -> streambody()).

%% public functions

-spec open(list()) -> {ok, pid()} | {error, term()}.
open(Path) ->
case open_new(Path) of
{ok, Pid} ->
Expand All @@ -51,17 +55,20 @@ open_new(Path) ->
close(Pid) ->
gen_server:call(Pid, close, infinity).

add(Pid, Key, Size, StreamBody) when is_binary(Key) andalso is_integer(Size) ->
case gen_server:call(Pid, {start_writing, Key, Size}) of
-spec add(pid(), binary(), integer(), integer(), streambody()) -> ok | {error, term()}.
add(Pid, Key, Cookie, Size, StreamBody) ->
case gen_server:call(Pid, {start_writing, Key, Cookie, Size}) of
{ok, Ref} ->
stream_in(Pid, Ref, StreamBody);
Else ->
Else
end.

-spec info(pid(), binary(), integer()) -> {ok, {integer(), integer(), integer()}} | {error, term()}.
info(Pid, Key, Cookie) ->
gen_server:call(Pid, {info, Key, Cookie}).

-spec read(pid(), binary(), integer()) -> ok | {error, term()}.
read(Pid, Key, Cookie) ->
case gen_server:call(Pid, {read, Key, Cookie}) of
{ok, StreamBodyFun} ->
Expand Down Expand Up @@ -92,24 +99,23 @@ init(Path) ->
{stop, Else}
end.

handle_call({start_writing, Key, Size}, _From,
handle_call({start_writing, Key, Cookie, Size}, _From,
#state{main_fd=MainFd, write_pos=Pos, writer=nil}=State) ->
Ref = make_ref(),
Cookie = monic_utils:new_cookie(),
LastModified = now(),
Header = #header{cookie=Cookie, key=Key, size=Size, last_modified=LastModified},
Index = #index{cookie=Cookie, key=Key, location=Pos, size=Size, last_modified=LastModified},
case monic_utils:pwrite_term(MainFd, Pos, Header) of
{ok, HeaderSize} ->
{reply, {ok, Ref}, State#state{data_start_pos=Pos + HeaderSize,
{reply, {ok, Ref}, State#state{data_start_pos=Pos + HeaderSize, sha=crypto:sha_init(),
next_index=Index, write_pos=Pos + HeaderSize, writer=Ref}};
Else ->
{reply, Else, abandon_write(State)}
end;
handle_call({start_writing, _Size}, _From, State) ->
handle_call({start_writing, _Key, _Cookie, _Size}, _From, State) ->
{reply, {error, already_writing}, State};

handle_call({write, Ref, {Bin, Next}}, _From, #state{main_fd=Fd, write_pos=Pos, writer=Ref}=State) ->
handle_call({write, Ref, {Bin, Next}}, _From, #state{main_fd=Fd, sha=Sha, write_pos=Pos, writer=Ref}=State) ->
Index = State#state.next_index,
Size = iolist_size(Bin),
Remaining = Index#index.size - (Pos + Size - State#state.data_start_pos),
Expand All @@ -121,22 +127,28 @@ handle_call({write, Ref, {Bin, Next}}, _From, #state{main_fd=Fd, write_pos=Pos,
_ ->
file:pwrite(Fd, Pos, Bin)
end,
Sha1 = crypto:sha_update(Sha, Bin),
case {Next, Write} of
{done, ok} ->
case file:datasync(Fd) of
ok ->
{ok, IndexPos} = file:position(Fd, cur), %% TODO track this in state.
monic_utils:pwrite_term(State#state.index_fd, IndexPos, Index),
ets:insert(State#state.tid, {Index#index.key, Index#index.cookie,
Index#index.location, Index#index.size, Index#index.last_modified}),
{reply, {ok, Index#index.cookie},
State#state{next_index=nil, reset_pos=Pos + Size,
write_pos=Pos + Size, writer=nil}};
Footer = #footer{sha=crypto:sha_final(Sha1)},
case monic_utils:pwrite_term(Fd, Pos + Size, Footer) of
{ok, FooterSize} ->
case file:datasync(Fd) of
ok ->
{ok, IndexPos} = file:position(Fd, cur), %% TODO track this in state.
monic_utils:pwrite_term(State#state.index_fd, IndexPos, Index),
ets:insert(State#state.tid, {Index#index.key, Index#index.cookie,
Index#index.location, Index#index.size, Index#index.last_modified}),
{reply, ok, State#state{next_index=nil, reset_pos=Pos + Size + FooterSize,
write_pos=Pos + Size + FooterSize, writer=nil}};
Else ->
{reply, Else, abandon_write(State)}
end;
Else ->
{reply, Else, abandon_write(State)}
end;
{_, ok} ->
{reply, {continue, Next}, State#state{write_pos=Pos + Size}};
{reply, {continue, Next}, State#state{sha=Sha1, write_pos=Pos + Size}};
{_, Else} ->
{reply, Else, abandon_write(State)}
end;
Expand Down Expand Up @@ -226,8 +238,12 @@ load_main_items(Tid, Fd, Location) ->
false -> ets:insert(Tid, {Key, Cookie, Location, Size, LastModified});
true -> ets:delete(Tid, Key)
end,
{ok, FooterSize, _} = monic_utils:pread_term(Fd, Location + HeaderSize + Size),
load_main_items(Tid, Fd, Location + HeaderSize + Size + FooterSize);
case monic_utils:pread_term(Fd, Location + HeaderSize + Size) of
{ok, FooterSize, _} ->
load_main_items(Tid, Fd, Location + HeaderSize + Size + FooterSize);
eof ->
{ok, Location}
end;
eof ->
{ok, Location};
Else ->
Expand Down
107 changes: 0 additions & 107 deletions src/monic_file_resource.erl

This file was deleted.

Loading

0 comments on commit 33f6f65

Please sign in to comment.