summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Kocoloski <adam@cloudant.com>2010-07-02 10:23:14 -0400
committerAdam Kocoloski <adam@cloudant.com>2010-08-12 01:23:42 -0400
commit56bdbc73f05e5450ff9c36f8e369f2399d113641 (patch)
treeeb9b77c3f476677d86ec4558ea63cb2c282e93d9
parentc02b2f9115d8d5a6bd48e9eaf644950bda14e29d (diff)
failover to reading dbs.couch directly when ets is MIA
-rw-r--r--src/mem3.erl17
-rw-r--r--src/mem3_util.erl21
2 files changed, 29 insertions, 9 deletions
diff --git a/src/mem3.erl b/src/mem3.erl
index 5116f008..5610f085 100644
--- a/src/mem3.erl
+++ b/src/mem3.erl
@@ -52,12 +52,13 @@ nodes() ->
shards(DbName) when is_list(DbName) ->
shards(list_to_binary(DbName));
shards(DbName) ->
- case ets:lookup(partitions, DbName) of
+ try ets:lookup(partitions, DbName) of
[] ->
- % TODO fall back to checking dbs.couch directly
- erlang:error(database_does_not_exist);
+ mem3_util:load_shards_from_disk(DbName);
Else ->
Else
+ catch error:badarg ->
+ mem3_util:load_shards_from_disk(DbName)
end.
-spec shards(DbName::iolist(), DocId::binary()) -> [#shard{}].
@@ -74,14 +75,14 @@ shards(DbName, DocId) ->
range = ['$1','$2'],
ref = '_'
},
- % TODO these conditions assume A < B, which we don't require
Conditions = [{'<', '$1', HashKey}, {'=<', HashKey, '$2'}],
- case ets:select(partitions, [{Head, Conditions, ['$_']}]) of
+ try ets:select(partitions, [{Head, Conditions, ['$_']}]) of
[] ->
- % TODO fall back to checking dbs.couch directly
- erlang:error(database_does_not_exist);
+ mem3_util:load_shards_from_disk(DbName, DocId);
Shards ->
Shards
+ catch error:badarg ->
+ mem3_util:load_shards_from_disk(DbName, DocId)
end.
-spec choose_shards(DbName::iolist(), Options::list()) -> [#shard{}].
@@ -89,7 +90,7 @@ choose_shards(DbName, Options) when is_list(DbName) ->
choose_shards(list_to_binary(DbName), Options);
choose_shards(DbName, Options) ->
try shards(DbName)
- catch error:database_does_not_exist ->
+ catch error:E when E==database_does_not_exist; E==badarg ->
Nodes = mem3:nodes(),
NodeCount = length(Nodes),
N = mem3_util:n_val(couch_util:get_value(n, Options), NodeCount),
diff --git a/src/mem3_util.erl b/src/mem3_util.erl
index b05faa15..e58bbd4c 100644
--- a/src/mem3_util.erl
+++ b/src/mem3_util.erl
@@ -2,7 +2,8 @@
-author('brad@cloudant.com').
-export([hash/1, name_shard/1, create_partition_map/4, build_shards/2,
- n_val/2, to_atom/1, to_integer/1, write_db_doc/1, delete_db_doc/1]).
+ n_val/2, to_atom/1, to_integer/1, write_db_doc/1, delete_db_doc/1,
+ load_shards_from_disk/1, load_shards_from_disk/2]).
-define(RINGTOP, 2 bsl 31). % CRC32 space
@@ -114,3 +115,21 @@ n_val(N, NodeCount) when N > NodeCount ->
NodeCount;
n_val(N, _) ->
N.
+
+load_shards_from_disk(DbName) when is_binary(DbName) ->
+ {ok, Db} = couch_db:open(<<"dbs">>, []),
+ try load_shards_from_db(Db, DbName) after couch_db:close(Db) end.
+
+load_shards_from_db(#db{} = ShardDb, DbName) ->
+ case couch_db:open_doc(ShardDb, DbName, []) of
+ {ok, #doc{body = {Props}}} ->
+ ?LOG_INFO("dbs cache miss for ~s", [DbName]),
+ build_shards(DbName, Props);
+ {not_found, _} ->
+ erlang:error(database_does_not_exist)
+ end.
+
+load_shards_from_disk(DbName, DocId)->
+ Shards = load_shards_from_disk(DbName),
+ HashKey = hash(DocId),
+ [S || #shard{range = [B,E]} = S <- Shards, B < HashKey, HashKey =< E].