Skip to content
Browse files

[enhance] stdlib: Added errno handling, updated option names, added e…

…val function, added insert_result etc.
  • Loading branch information...
1 parent cc4c0eb commit 7c8a67593f74412ea01e84a5e9fbd2caace55c87 @nrs135 nrs135 committed Nov 24, 2011
Showing with 115 additions and 31 deletions.
  1. +13 −2 stdlib/apis/mongo/bson.opa
  2. +16 −19 stdlib/apis/mongo/commands.opa
  3. +32 −0 stdlib/apis/mongo/common.opa
  4. +54 −10 stdlib/apis/mongo/connection.opa
View
15 stdlib/apis/mongo/bson.opa
@@ -116,6 +116,7 @@ type Bson.error = {
ok: Bson.register(Bson.int32);
err: Bson.register(string);
code: Bson.register(Bson.int32);
+ errno: Bson.register(Bson.int32);
assertion: Bson.register(string);
assertionCode: Bson.register(Bson.int32);
n: Bson.register(Bson.int32);
@@ -158,6 +159,8 @@ Bson = {{
arr(n:string,d:Bson.document):Bson.element = {name=n; value={Array=d}}
docarr(n:string,l:list(Bson.document)):Bson.element =
{name=n; value={Array=List.mapi((i, d -> ({name="{i}"; value={Document=d}}:Bson.element)),l)}}
+ valarr(n:string,l:list(Bson.value)):Bson.element =
+ {name=n; value={Array=List.mapi((i, value -> ({name="{i}"; ~value}:Bson.element)),l)}}
binary(n:string,b:Bson.binary):Bson.element = {name=n; value={Binary=b}}
oid(n:string,id:string):Bson.element = {name=n; value={ObjectID=id}}
bool(n:string,b:bool):Bson.element = {name=n; value={Boolean=b}}
@@ -498,6 +501,7 @@ Bson = {{
| {none} -> "<unknown ok status>"
err = match find_string(doc, "err") with | {some=""} -> "" | {some=err} -> "<err=\"{err}\">" | {none} -> ""
code = match find_int(doc, "code") with | {some=code} -> "<code={code}>" | {none} -> ""
+ errno = match find_int(doc, "errno") with | {some=errno} -> "<errno={errno}>" | {none} -> ""
n = match find_int(doc, "n") with | {some=n} -> "<n={n}>" | {none} -> ""
errmsg = match find_string(doc, "errmsg") with | {some=""} -> "" | {some=errmsg} -> "<errmsg=\"{errmsg}\">" | {none} -> ""
assertion =
@@ -509,7 +513,7 @@ Bson = {{
match find_int(doc, "assertionCode") with
| {some=assertionCode} -> "<assertionCode={assertionCode}>"
| {none} -> ""
- String.concat(" ",List.filter((s -> s != ""),[ok,err,code,n,errmsg,assertion,assertionCode]))
+ String.concat(" ",List.filter((s -> s != ""),[ok,err,code,errno,n,errmsg,assertion,assertionCode]))
/**
* Decide if a document contains an error or not.
@@ -519,6 +523,7 @@ Bson = {{
(match find_int(doc,"ok") with {some=ok} -> ok != 1 | {none} -> false) ||
(match find_string(doc, "err") with {some=err} -> err != "" | {none} -> false) ||
(match find_int(doc, "code") with {some=code} -> code != 0 | {none} -> false) ||
+ (match find_int(doc, "errno") with {some=errno} -> errno != 0 | {none} -> false) ||
(match find_string(doc, "errmsg") with {some=errmsg} -> errmsg != "" | {none} -> false)
/**
@@ -528,6 +533,7 @@ Bson = {{
(match err.ok with {present=ok} -> ok != 1 | {absent} -> false) ||
(match err.err with {present=err} -> err != "" | {absent} -> false) ||
(match err.code with {present=code} -> code != 0 | {absent} -> false) ||
+ (match err.errno with {present=errno} -> errno != 0 | {absent} -> false) ||
(match err.errmsg with {present=errmsg} -> errmsg != "" | {absent} -> false)
/**
@@ -542,12 +548,13 @@ Bson = {{
| {absent} -> "<unknown ok status>"
err = match error.err with | {present=""} -> "" | {present=err} -> "<err=\"{err}\">" | {absent} -> ""
code = match error.code with | {present=code} -> "<code={code}>" | {absent} -> ""
+ errno = match error.errno with | {present=errno} -> "<errno={errno}>" | {absent} -> ""
assertion =
match error.assertion with | {present=""} -> "" | {present=assertion} -> "<assertion=\"{assertion}\">" | {absent} -> ""
assertionCode = match error.assertionCode with | {present=assertionCode} -> "<assertionCode={assertionCode}>" | {absent} -> ""
n = match error.n with | {present=n} -> "<n={n}>" | {absent} -> ""
errmsg = match error.errmsg with | {present=""} -> "" | {present=errmsg} -> "<errmsg=\"{errmsg}\">" | {absent} -> ""
- String.concat(" ",List.filter((s -> s != ""),[ok,err,code,assertion,assertionCode,n,errmsg]))
+ String.concat(" ",List.filter((s -> s != ""),[ok,err,code,errno,assertion,assertionCode,n,errmsg]))
/**
* We can't always use [bson_to_opa] to extract the error-relevant
@@ -569,6 +576,10 @@ Bson = {{
match find_int(doc,"code") with
| {some=code} -> {present=code}
| {none} -> {absent};
+ errno=
+ match find_int(doc,"errno") with
+ | {some=errno} -> {present=errno}
+ | {none} -> {absent};
assertion=
match find_string(doc, "assertion") with
| {some=assertion} -> {present=assertion}
View
35 stdlib/apis/mongo/commands.opa
@@ -500,21 +500,6 @@ MongoCommands = {{
removeShard(m:Mongo.mongodb, shard:string): Mongo.result =
simple_str_command(m, "admin", "removeShard", shard)
- /* Map a list of outcomes onto an outcome of a list. */
- @private
- Outcome_map(f:'a->outcome('b,'c), l:list('a)): outcome(list('b),'c) =
- rec aux(l) =
- match l with
- | [a|t] ->
- (match f(a) with
- | {success=b} ->
- (match aux(t) with
- | {success=l} -> {success=[b|l]}
- | {~failure} -> {~failure})
- | {~failure} -> {~failure})
- | [] -> {success=[]}
- aux(l)
-
/**
* Find a non-draining shard in a list of shards.
* You get the list of shards from the "config.shards" collection.
@@ -567,10 +552,10 @@ MongoCommands = {{
(match find_non_draining_shard(shards) with
| {some=shardid} ->
do println("shardid={shardid}")
- res = Outcome_map((dbdoc ->
- (match Bson.find_string(dbdoc,"_id") with
- | {some=dbname} -> movePrimary(m, dbname, shardid)
- | {none} -> {failure={Error="no db _id"}})),dbs)
+ res = MongoCommon.Outcome_list((dbdoc ->
+ (match Bson.find_string(dbdoc,"_id") with
+ | {some=dbname} -> movePrimary(m, dbname, shardid)
+ | {none} -> {failure={Error="no db _id"}})),dbs)
(match res with
| {success=_} -> aux(retryTime,retries+1)
| {~failure} -> {~failure})
@@ -748,6 +733,18 @@ MongoCommands = {{
(match verbose_opt with | {some=verbose} -> [H.bool("verbose",verbose)] | {none} -> [])])
run_command(m, m.dbname, cmd)
+ /**
+ * Evaluate Javascript code.
+ *
+ * Example: [eval(mongodb, dbname, code, args_opt, nolock_opt)]
+ **/
+ eval(m:Mongo.mongodb, dbname:string, code:Bson.code, args_opt:option(list(Bson.value)), nolock_opt:option(bool))
+ : Mongo.result =
+ cmd = List.flatten([[H.code("$eval",code)],
+ (match args_opt with | {some=args} -> [H.valarr("args",args)] | {none} -> []),
+ (match nolock_opt with | {some=nolock} -> [H.bool("nolock",nolock)] | {none} -> [])])
+ run_command(m, dbname, cmd)
+
@private pass_digest(user:string, pass:string): string = Crypto.Hash.md5("{user}:mongo:{pass}")
/**
View
32 stdlib/apis/mongo/common.opa
@@ -154,6 +154,20 @@ MongoCommon = {{
| {~success} -> sfn(success)
| {~failure} -> ffn(failure)
+ /* Map a list of outcomes onto an outcome of a list. */
+ Outcome_list(f:'a->outcome('b,'c), l:list('a)): outcome(list('b),'c) =
+ rec aux(l) =
+ match l with
+ | [a|t] ->
+ (match f(a) with
+ | {success=b} ->
+ (match aux(t) with
+ | {success=l} -> {success=[b|l]}
+ | {~failure} -> {~failure})
+ | {~failure} -> {~failure})
+ | [] -> {success=[]}
+ aux(l)
+
/** Same as [outcome_map] but coerced to string **/
string_of_outcome = (outcome_map:outcome('s,'f), ('s->string), ('f->string) -> string)
@@ -446,6 +460,24 @@ MongoCommon = {{
| {none} -> failErr("{from}: no document in reply"))
| {none} -> failErr("{from}: no reply")
+ /**
+ * Extract all documents from a reply.
+ *
+ * Example: [reply_to_results(from, reply_opt)]
+ *
+ * @param from A string included in failure messages.
+ * @param reply_opt The optional reply (this is what most query operations return).
+ **/
+ reply_to_results(from:string, reply_opt: option(Mongo.reply)): Mongo.results =
+ match reply_opt with
+ | {some=reply} ->
+ Outcome_list((n ->
+ match reply_document(reply,n) with
+ | {some=doc} -> {success=doc}
+ | {none} -> failErr("{from}: no document in reply")),
+ List.init((n -> n),reply_numberReturned(reply)))
+ | {none} -> failErr("{from}: no reply")
+
}}
//End of file common.opa
View
64 stdlib/apis/mongo/connection.opa
@@ -149,28 +149,28 @@ MongoConnection = {{
anonymous = [];
parsers = [
{CommandLine.default_parser with
- names = ["--mongo-name", "--mongoname", "-mn"]
+ names = ["--mongo-name", "--mongoname", "--mn", "-mn"]
description = "Name for the MongoDB server connection"
param_doc = "<string>"
on_param(p) = parser name={Rule.consume} ->
do last_name.set(name)
{no_params = add_param((p -> { p with ~name }),p)}
},
{CommandLine.default_parser with
- names = ["--mongo-repl-name", "--mongoreplname", "-mr"]
+ names = ["--mongo-repl-name", "--mongoreplname", "--mr", "-mr"]
description = "Replica set name for the MongoDB server"
param_doc = "<string>"
on_param(p) = parser s={Rule.consume} ->
{no_params = add_param((p -> { p with replname={some=s} }),p)}
},
{CommandLine.default_parser with
- names = ["--mongo-buf-size", "--mongobufsize", "-mb"]
+ names = ["--mongo-buf-size", "--mongobufsize", "--mb", "-mb"]
description = "Hint for initial MongoDB connection buffer size"
param_doc = "<int>"
on_param(p) = parser n={Rule.natural} -> {no_params = add_param((p -> { p with bufsize = n }),p)}
},
{CommandLine.default_parser with
- names = ["--mongo-concurrency", "--mongoconcurrency", "-mx"]
+ names = ["--mongo-concurrency", "--mongoconcurrency", "--mx", "-mx"]
description = "Concurrency type, 'pool', 'cell' or 'singlethreaded'"
param_doc = "<string>"
on_param(p) = parser s={Rule.consume} ->
@@ -183,25 +183,25 @@ MongoConnection = {{
{no_params = add_param((p -> { p with ~concurrency }),p)}
},
{CommandLine.default_parser with
- names = ["--mongo-socket-pool", "--mongosocketpool", "-mp"]
+ names = ["--mongo-socket-pool", "--mongosocketpool", "--mp", "-mp"]
description = "Number of sockets in socket pool (>=2 enables socket pool)"
param_doc = "<int>"
on_param(p) = parser n={Rule.natural} -> {no_params = add_param((p -> { p with pool_max = n }),p)}
},
{CommandLine.default_parser with
- names = ["--mongo-close-socket", "--mongoclosesocket", "-mc"]
+ names = ["--mongo-close-socket", "--mongoclosesocket", "--mc", "-mc"]
description = "Maintain MongoDB server sockets in a closed state"
param_doc = "<bool>"
on_param(p) = parser b={Rule.bool} -> {no_params = add_param((p -> { p with close_socket = b }),p)}
},
{CommandLine.default_parser with
- names = ["--mongo-log", "--mongolog", "-ml"]
+ names = ["--mongo-log", "--mongolog", "--ml", "-ml"]
description = "Enable MongoLog logging"
param_doc = "<bool>"
on_param(p) = parser b={Rule.bool} -> {no_params = add_param((p -> { p with log = b }),p)}
},
{CommandLine.default_parser with
- names = ["--mongo-seed", "--mongoseed", "-ms"]
+ names = ["--mongo-seed", "--mongoseed", "--ms", "-ms"]
description = "Add a seed to a replica set, allows multiple seeds"
param_doc = "<host>\{:<port>\}"
on_param(p) =
@@ -211,7 +211,7 @@ MongoConnection = {{
{ p with seeds=[MongoReplicaSet.mongo_host_of_string(s)|seeds] }),p)}
},
{CommandLine.default_parser with
- names = ["--mongo-host", "--mongohost", "-mh"]
+ names = ["--mongo-host", "--mongohost", "--mh", "-mh"]
description = "Host name of a MongoDB server, overwrites any previous addresses for this name"
param_doc = "<host>\{:<port>\}"
on_param(p) =
@@ -220,7 +220,7 @@ MongoConnection = {{
{ p with seeds=[MongoReplicaSet.mongo_host_of_string(s)] }),p)}
},
{CommandLine.default_parser with
- names = ["--mongo-log-type", "--mongologtype", "-mt"]
+ names = ["--mongo-log-type", "--mongologtype", "--mt", "-mt"]
description = "Type of logging: stdout, stderr, logger, none"
param_doc = "<string>"
on_param(p) = parser s={Rule.consume} ->
@@ -504,6 +504,11 @@ MongoConnection = {{
inserte(m:Mongo.mongodb, documents:Bson.document): option(Mongo.reply) =
MongoDriver.inserte(m.mongo, m.insert_flags, "{m.dbname}.{m.collection}", m.dbname, documents)
+ /** Insert document with getlasterror converted into a result into the defined database with inbuilt flags **/
+ insert_result(m:Mongo.mongodb, documents:Bson.document): Mongo.result =
+ MongoCommon.reply_to_result("MongoConnection.insert_result",0,
+ MongoDriver.inserte(m.mongo, m.insert_flags, "{m.dbname}.{m.collection}", m.dbname, documents))
+
/** Insert batch of documents into the defined database with inbuilt flags **/
insert_batch(m:Mongo.mongodb, documents:list(Bson.document)): bool =
MongoDriver.insert_batch(m.mongo, m.insert_flags, "{m.dbname}.{m.collection}", documents)
@@ -512,6 +517,12 @@ MongoConnection = {{
insert_batche(m:Mongo.mongodb, documents:list(Bson.document)): option(Mongo.reply) =
MongoDriver.insert_batche(m.mongo, m.insert_flags, "{m.dbname}.{m.collection}", m.dbname, documents)
+ /** Insert batch of documents with getlasterror converted into a result into the defined database with inbuilt flags **/
+ insert_batch_result(m:Mongo.mongodb, documents:list(Bson.document)): Mongo.result =
+ MongoCommon.reply_to_result("MongoConnection.insert_batch_result",0,
+ MongoDriver.insert_batche(m.mongo, m.insert_flags, "{m.dbname}.{m.collection}",
+ m.dbname, documents))
+
/** Update document in the defined database with inbuilt flags **/
update(m:Mongo.mongodb, selector:Bson.document, update:Bson.document): bool =
MongoDriver.update(m.mongo, m.update_flags, "{m.dbname}.{m.collection}", selector, update)
@@ -520,6 +531,12 @@ MongoConnection = {{
updatee(m:Mongo.mongodb, selector:Bson.document, update:Bson.document): option(Mongo.reply) =
MongoDriver.updatee(m.mongo, m.update_flags, "{m.dbname}.{m.collection}", m.dbname, selector, update)
+ /** Update document with getlasterror converted into a result in the defined database with inbuilt flags **/
+ update_result(m:Mongo.mongodb, selector:Bson.document, update:Bson.document): Mongo.result =
+ MongoCommon.reply_to_result("MongoConnection.update_result",0,
+ MongoDriver.updatee(m.mongo, m.update_flags, "{m.dbname}.{m.collection}",
+ m.dbname, selector, update))
+
/** Perform a query using inbuilt parameters.
* The functions to handle [Mongo.reply] are in [MongoDriver].
**/
@@ -541,6 +558,11 @@ MongoConnection = {{
deletee(m:Mongo.mongodb, selector:Bson.document): option(Mongo.reply) =
MongoDriver.deletee(m.mongo, m.delete_flags, "{m.dbname}.{m.collection}", m.dbname, selector)
+ /** Delete documents with getlasterror converted into a result from the defined database with inbuilt flags **/
+ delete_result(m:Mongo.mongodb, selector:Bson.document): Mongo.result =
+ MongoCommon.reply_to_result("MongoConnection.delete_result",0,
+ MongoDriver.deletee(m.mongo, m.delete_flags, "{m.dbname}.{m.collection}", m.dbname, selector))
+
/** Perform a kill_cursors operation **/
kill_cursors(m:Mongo.mongodb, cursors:list(Mongo.cursorID)): bool =
MongoDriver.kill_cursors(m.mongo, cursors)
@@ -549,6 +571,11 @@ MongoConnection = {{
kill_cursorse(m:Mongo.mongodb, cursors:list(Mongo.cursorID)): option(Mongo.reply) =
MongoDriver.kill_cursorse(m.mongo, m.dbname, cursors)
+ /** Perform a kill_cursors operation with getlasterror converted into a result **/
+ kill_cursors_result(m:Mongo.mongodb, cursors:list(Mongo.cursorID)): Mongo.result =
+ MongoCommon.reply_to_result("MongoConnection.kill_cursors_result",0,
+ MongoDriver.kill_cursorse(m.mongo, m.dbname, cursors))
+
/** Perform a msg operation **/
msg(m:Mongo.mongodb, msg:string): bool =
MongoDriver.msg(m.mongo, msg)
@@ -557,6 +584,11 @@ MongoConnection = {{
msge(m:Mongo.mongodb, msg:string): option(Mongo.reply) =
MongoDriver.msge(m.mongo, m.dbname, msg)
+ /** Perform a msg operation with getlasterror converted into a result **/
+ msg_result(m:Mongo.mongodb, msg:string): Mongo.result =
+ MongoCommon.reply_to_result("MongoConnection.msg_result",0,
+ MongoDriver.msge(m.mongo, m.dbname, msg))
+
/** Add an index to the inbuilt collection **/
create_index(m:Mongo.mongodb, key:Bson.document): bool =
MongoDriver.create_index(m.mongo, "{m.dbname}.{m.collection}", key, m.index_flags)
@@ -606,6 +638,18 @@ MongoConnection = {{
}} // Cursor
+ /**
+ * Save a function into the system.js collection for the named database.
+ *
+ * Example: [save_function(mongodb, dbname, name, code)]
+ * @param mongodb The mongo connection
+ * @param dbname The name of the database
+ * @param name The name of the function
+ * @param code The code for the function
+ **/
+ save_function(m:Mongo.mongodb, dbname:string, name:string, code:Bson.code): Mongo.result =
+ insert_result(namespace(m,dbname,"system.js"),Bson.opa2doc({_id=name; value=code}))
+
}}
// End of file connection.opa

0 comments on commit 7c8a675

Please sign in to comment.
Something went wrong with that request. Please try again.