Permalink
Browse files

[cleanup] stdlib: Finish cleanout of MongoDb.opa, document connection…

….opa, partial document view.opa, exit now @fail.
  • Loading branch information...
nrs135 committed Nov 8, 2011
1 parent e94af28 commit 0fdc78f973b3d0cba0be4bba4c2a56efd5c30f07
Showing with 109 additions and 137 deletions.
  1. +2 −110 stdlib/apis/mongo/MongoDb.opa
  2. +72 −2 stdlib/apis/mongo/connection.opa
  3. +1 −1 stdlib/apis/mongo/log.opa
  4. +34 −24 stdlib/apis/mongo/view.opa
@@ -17,116 +17,8 @@
*/
/**
- *
- * Firstly, as an aside, note that we could very easily implement a MongoDB backend
- * for db-light using only the OCaml-based bson.ml and mongo.ml code.
- *
- * Design goals for the new high-level MongoDB code are simple, I think:
- *
- * 1) We want a generalisation of the existing Db interface, for example we don't
- * want to be restricted to int and string maps.
- *
- * 2) We want a MongoDB interface which allows as much of the work, searches etc.
- * to be carried out by the MongoDB server.
- *
- * 3) We want to be able to implement or emulate foreign keys efficiently.
- *
- * 4) We want to handle maps as objects without reading the entire database to
- * construct the map. I am assuming here that the Map interface will continue
- * to be the "standard" way of viewing a database in OPA.
- *
- * 5) We want the Db interface to be a subset of this module, or at least emulatable
- * using the constructs in this module.
- *
- * The following are what I would call "side-conditions" rather than subgoals:
- *
- * a) We are prepared to tolerate a naive mapping of recursive types into nested BSON
- * documents. We can accept that a 10^6 element list will map to a document
- * nested 10^6 deep which MongoDB may or may not be able to handle.
- *
- * b) We will make an effort to map naturally onto MongoDB's types, for example, MongoDB
- * provides many useful functions which operate over arrays so it would seem to make
- * sense to map lists onto arrays. Other special cases could be handled for efficiency.
- *
- * c) Initially, the dbGen syntax can be ignored in the assumption that it can be
- * implemented later using a dedicated syntax-based compiler phase generating calls
- * to the MongoDb module.
- *
- * I am proposing to use the existing OPA to BSON module which currently only exists
- * in the dbMongo code but which could be factored out for use here. An initial design
- * might be:
- *
- * Revised design <Thu Oct 6 10:02:54 CEST 2011>
- *
- * Note:
- *
- * A map is:
- * { label -> value; label2 -> value2; ... }
- *
- * A set can be viewed as a degenerate map:
- * { label -> ; label2 -> ; ... }
- *
- * A map can be implemented within a set:
- * { (label,value) -> ; (label2,value2) ->; ... }
- *
- * An array can be viewed as a specialisation of a map:
- * { 0 -> value; 1 -> value2; ... }
- *
- * A map can be implemented within an array:
- * { 0 -> (label,value); 1 -> (label2,value2); ... }
- *
- * etc. etc. (set within array):
- * { 0 -> (label,()); 1 -> (label2,()); ... }
- *
- * The main difference between these is the computational complexity of the basic ops.
- *
- * Now MongoDB implements heterogeneous sets (collections) of (labeled) Bson documents:
- * { {"label":value}, {"label2":value2} }
- * (where value, value2 can be documents) which is, in effect, a map from keys to values
- *
- * The current "standard" OPA type to Bson implementation is simple:
- * {a:'a; b:'b} -> { a: 'a, b: 'b }
- * 'a -> { value: 'a }
- * where we use a "natural" mapping of constant types: int -> Int64, string -> String etc.
- * special cases:
- * list('a) -> { Array=(<label>,{ 0:'a; 1:'a; ... }) }
- * Bson.document -> Bson.document (verbatim, including labels)
- *
- * An update is:
- * update(db,select,update)
- * where select defines the the values to be updated and update
- * specifies the new values.
- *
- * A query is:
- * query(num_to_skip,num_to_return,select,field_select)
- * where select defines the values to return, field_select
- * says which fields in the value to return (_id is always included).
- *
- * The current schema for mapping dbGen syntax to MongoDB documents is:
- *
- * file: prog.opa
- * definitions:
- * db /coll/x : t
- * db /coll/y : u
- * db /coll/...
- *
- * Leads to:
- *
- * database name: "prog_exe" (or whatever is defined in the program)
- * collection name: "coll"
- * OPA type: {x:t} / {y:u} / ...
- * MongoDB: the OPA to Bson schema above.
- *
- * Notes:
- *
- * - This is different from the existing dbGen syntax since
- * multiple db definitions at the root of the path now map to sum
- * types instead of records. This allows storage of multiple types
- * in the same collection.
- **/
-
-
-/** Later:
+ * This file is no longer used, this is just a reminder of
+ * features which will appear in future releases.
*
* MongoMap = {{
* // Implementation of map using underlying MongoDB.
@@ -45,6 +45,7 @@
* of a MongoDB query built in.
**/
// TODO: Possibly arrange a map of address:port values to connections?
+@abstract
type Mongo.mongodb = {
mongo: Mongo.db;
bufsize: int;
@@ -93,23 +94,54 @@ MongoConnection = {{
| {none} -> {failure={Error="MongoConnection.open: no primary"}})
| {~failure} -> {~failure}
+ /**
+ * Open a connection to a single server. No check for primary status is
+ * carried out and no reconnection is attempted.
+ *
+ * Example: [open(bufsize, host, port)]
+ **/
open(bufsize:int, addr:string, port:int): outcome(Mongo.mongodb,Mongo.failure) =
open_(MongoDriver.open(bufsize,addr,port,false))
+ /**
+ * Open a connection to a replica set starting from the given list of seeds.
+ *
+ * Example: [open(name, bufsize, seeds)]
+ *
+ * This routine causes a serach for the current host list among the seeds
+ * and then seraches for the primary among the hosts. Rconnection logic
+ * is enabled.
+ **/
repl(name:string, bufsize:int, seeds:list(Mongo.mongo_host)): outcome(Mongo.mongodb,Mongo.failure) =
open_(MongoReplicaSet.connect(MongoReplicaSet.init(name,bufsize,false,seeds)))
+ /**
+ * Clone a connection. We actually just bump the link count. On close
+ * the connection itself is only closed once the link count drops to zero.
+ **/
clone(db:Mongo.mongodb): Mongo.mongodb =
do db.link_count.set(db.link_count.get()+1)
db
+ /**
+ * Change the namespace built into the connection. The defaults are:
+ * db="db" and collection="collection". Chemging the namespace bumps
+ * the link count.
+ **/
namespace(db:Mongo.mongodb, dbname:string, collection:string): Mongo.mongodb =
do db.link_count.set(db.link_count.get()+1)
{ db with ~dbname; ~collection }
+ /**
+ * Enable/disable logging for the given connection. Only applies to
+ * the connection returned.
+ **/
log(db:Mongo.mongodb, log:bool): Mongo.mongodb =
{ db with mongo={ db.mongo with ~log } }
+ /**
+ * Decrement the link count on a connection and close when zero.
+ **/
close(db:Mongo.mongodb): void =
lc = db.link_count.get()
if lc > 0
@@ -123,37 +155,75 @@ MongoConnection = {{
else void
else void
+ /**
+ * Return the last error on the given connection.
+ **/
getLastError(db:Mongo.mongodb): Mongo.result = MongoCommands.getLastError(db.mongo, db.dbname)
- err(db:Mongo.mongodb, n:string): void =
+ /**
+ * A simple error report. Check the last error on the given database and log an error
+ * if the reply is an actual error.
+ **/
+ err(db:Mongo.mongodb, msg:string): bool =
err = MongoCommands.getLastError(db.mongo, db.dbname)
- if MongoDriver.isError(err) then println("Error({n})={MongoDriver.string_of_result(err)}")
+ status = MongoDriver.isError(err)
+ do if db.mongo.log && status
+ then ML.error("MongoConnection.err({db})","msg={msg}) err={MongoDriver.string_of_result(err)}",void)
+ status
+ /** Set the "skip" number on the given connection. **/
skip(db:Mongo.mongodb, skip:int): Mongo.mongodb = { db with ~skip }
+
+ /** Set the "limit" number on the given connection. **/
limit(db:Mongo.mongodb, limit:int): Mongo.mongodb = { db with ~limit }
+
+ /** Set the "fields" document on the given connection. **/
fields(db:Mongo.mongodb, fields:option(Bson.document)): Mongo.mongodb = { db with ~fields }
+
+ /** Set the "orderby" document on the given connection. **/
orderby(db:Mongo.mongodb, orderby:option(Bson.document)): Mongo.mongodb = { db with ~orderby }
+ /** Set the "continueOnError" flag for all [insert] calls. **/
continueOnError(db:Mongo.mongodb): Mongo.mongodb =
{ db with insert_flags=Bitwise.lor(db.insert_flags,MongoDriver.ContinueOnErrorBit) }
+
+ /** Set the "Upsert" flag for all [update] calls. **/
upsert(db:Mongo.mongodb): Mongo.mongodb =
{ db with update_flags=Bitwise.lor(db.update_flags,MongoDriver.UpsertBit) }
+
+ /** Set the "multiUpdate" flag for all [update] calls. **/
multiUpdate(db:Mongo.mongodb): Mongo.mongodb =
{ db with update_flags=Bitwise.lor(db.update_flags,MongoDriver.MultiUpdateBit) }
+
+ /** Set the "singleRemove" flag for all [delete] calls. **/
singleRemove(db:Mongo.mongodb): Mongo.mongodb =
{ db with delete_flags=Bitwise.lor(db.delete_flags,MongoDriver.SingleRemoveBit) }
+
+ /** Set the "tailableCursor" flag for all [query] calls. **/
tailableCursor(db:Mongo.mongodb): Mongo.mongodb =
{ db with query_flags=Bitwise.lor(db.query_flags,MongoDriver.TailableCursorBit) }
+
+ /** Set the "slaveOk" flag for all [query] calls. **/
slaveOk(db:Mongo.mongodb): Mongo.mongodb =
{ db with query_flags=Bitwise.lor(db.query_flags,MongoDriver.SlaveOkBit) }
+
+ /** Set the "oplogReplay" flag for all [query] calls. **/
oplogReplay(db:Mongo.mongodb): Mongo.mongodb =
{ db with query_flags=Bitwise.lor(db.query_flags,MongoDriver.OplogReplayBit) }
+
+ /** Set the "noCursorTimeout" flag for all [query] calls. **/
noCursorTimeout(db:Mongo.mongodb): Mongo.mongodb =
{ db with query_flags=Bitwise.lor(db.query_flags,MongoDriver.NoCursorTimeoutBit) }
+
+ /** Set the "awaitData" flag for all [query] calls. **/
awaitData(db:Mongo.mongodb): Mongo.mongodb =
{ db with query_flags=Bitwise.lor(db.query_flags,MongoDriver.AwaitDataBit) }
+
+ /** Set the "exhaust" flag for all [query] calls. **/
exhaust(db:Mongo.mongodb): Mongo.mongodb =
{ db with query_flags=Bitwise.lor(db.query_flags,MongoDriver.ExhaustBit) }
+
+ /** Set the "partial" flag for all [query] calls. **/
partial(db:Mongo.mongodb): Mongo.mongodb =
{ db with query_flags=Bitwise.lor(db.query_flags,MongoDriver.PartialBit) }
@@ -76,7 +76,7 @@ MongoLog = {{
| {stderr} -> prerrln("Fatal{if from=="" then "" else "({from})"}: {str}")
| {logger} -> Log.fatal(from,str)
| {nomongolog} -> void
- System.exit(v)
+ @fail("{v}")
}}
Oops, something went wrong.

0 comments on commit 0fdc78f

Please sign in to comment.