1 var comb = require("comb");
  2 
  3 
  4 /**
  5  * @class Base class for all connection pools
  6  *
  7  * @name ConnectionPool
  8  * @augments comb.collections.Pool
  9  * @memberOf moose.adapters.client
 10  */
 11 var ConnectionPool = comb.define(comb.collections.Pool, {
 12 
 13     instance : {
 14 	    /**@lends moose.adapters.client.ConnectionPool.prototype*/
 15 
 16         constructor : function(options) {
 17             options = options || {};
 18             if (!options.database) throw "moose.adapters.clients.ConnectionPool : a database is required to initialize the pool.";
 19             options.minObjects = options.minConnections || 0;
 20             options.maxObjects = options.maxConnections || 10;
 21             this.database = options.database;
 22             this.__deferredQueue = new comb.collections.Queue();
 23             this._options = options;
 24             this.super(arguments);
 25         },
 26 
 27         /**
 28          * Checks all deferred connection requests.
 29          */
 30         __checkQueries : function() {
 31             var fc = this.freeCount, def, defQueue = this.__deferredQueue;
 32             while (fc-- >= 0 && defQueue.count) {
 33                 def = defQueue.dequeue();
 34                 var conn = this.getObject();
 35                 if (conn) {
 36                     def.callback(conn);
 37                 } else {
 38                     //we didnt get a conneciton so assume we're out.
 39                     break;
 40                 }
 41                 fc--;
 42             }
 43         },
 44 
 45         /**
 46          * Performs a query on one of the connection in this Pool.
 47          *
 48          * @return {comb.Promise} A promise to called back with a connection.
 49          */
 50         getConnection : function() {
 51             var ret = new comb.Promise();
 52             var conn = this.getObject();
 53             if (!conn) {
 54                 //we need to deffer it
 55                 this.__deferredQueue.enqueue(ret);
 56             } else {
 57                 ret.callback(conn);
 58             }
 59             return ret;
 60         },
 61 
 62         /**
 63          * Override comb.collections.Pool to allow async validation to allow
 64          * pools to do any calls to reset a connection if it needs to be done.
 65          *
 66          * @param {*} connection the connection to return.
 67          *
 68          */
 69         returnObject : function(obj) {
 70             if (this.count <= this.__maxObjects) {
 71                 this.validate(obj).then(comb.hitch(this, function(valid) {
 72                     if (valid) {
 73                         this.__freeObjects.enqueue(obj);
 74                         var index;
 75                         if ((index = this.__inUseObjects.indexOf(obj)) > -1)
 76                             this.__inUseObjects.splice(index, 1);
 77                         this.__checkQueries();
 78                     } else {
 79                         this.removeObject(obj);
 80                     }
 81                 }));
 82             } else {
 83                 this.removeObject(obj);
 84             }
 85         },
 86 
 87 	    /**
 88 	     * Removes a connection from the pool.
 89 	     * @param conn
 90 	     */
 91 	    removeConnection : function(conn){
 92 		    this.removeObject(conn);
 93 	    },
 94 
 95         /**
 96          * Return a connection to the pool.
 97          *
 98          * @param {*} connection the connection to return.
 99          *
100          * @return {*} an adapter specific connection.
101          */
102         returnConnection : function(connection) {
103             this.returnObject(connection);
104         },
105 
106         createObject : function() {
107             return this.createConnection();
108         },
109 
110         /**
111          * Override to implement the closing of all connections.
112          *
113          * @return {comb.Promise} called when all connections are closed.
114          */
115         endAll : function() {
116             this.__ending = true;
117             var conn, fQueue = this.__freeObjects, count = this.count, ps = [];
118             while ((conn = this.__freeObjects.dequeue()) != undefined) {
119                 ps.push(this.closeConnection(conn));
120             }
121             var inUse = this.__inUseObjects;
122             for (var i = inUse.length - 1; i >= 0; i--) {
123                 ps.push(this.closeConnection(inUse[i]));
124             }
125             this.__inUseObjects.length = 0;
126             var pls = new comb.PromiseList(ps);
127             return pls;
128         },
129 
130 
131         /**
132          * Override to provide any additional validation. By default the promise is called back with true.
133          *
134          * @param {*} connection the conneciton to validate.
135          *
136          * @return {comb.Promise} called back with a valid or invalid state.
137          */
138         validate : function(conn) {
139             var ret = new comb.Promise();
140             ret.callback(true);
141             return ret;
142         },
143 
144         /**
145          * Override to create connections to insert into this ConnectionPool.
146          */
147         createConnection : function() {
148             throw "moose.adapters.clients.ConnectionPool : createConnection not implemented.";
149         },
150 
151         /**
152          * Override to implement close connection functionality;
153          * @param {*} conn the connection to close;
154          *
155          * @return {comb.Promise} called back when the connection is closed.
156          */
157         closeConnection : function(conn) {
158             throw "moose.adapters.clients.ConnectionPool : closeConnection not implemented.";
159         }
160     }
161 
162 });
163 exports = module.exports = ConnectionPool;