hdb
Version:
SAP HANA Database Client for Node
125 lines (109 loc) • 3.84 kB
JavaScript
// Copyright 2013 SAP AG.
//
// 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.
;
var util = require('../util');
var common = require('./common');
var debug = util.debuglog('hdb_conn');
module.exports = ConnectionManager;
function ConnectionManager(options) {
this._options = options;
}
ConnectionManager.prototype.openConnection = function openConnection(conn, cb) {
var opts = this._options;
var dbHosts = (Array.isArray(opts.hosts) && opts.hosts.slice()) || [{ host: opts.host, port: opts.port }];
debug('Opening connection. Hosts:', dbHosts);
var errorStats = [];
var self = this;
function tryConnect() {
if (dbHosts.length === 0) {
return cb(couldNotOpenConnectionError(errorStats));
}
var options = util.extend({}, self._options, dbHosts.shift());
self._openConnection(conn, options, function (err) {
if (err) {
debug('Connection to %s:%d failed with:', options.host, options.port, err.message);
errorStats.push({ host: options.host, port: options.port, err: err });
tryConnect();
} else {
debug('Successful connection to %s:%d', options.host, options.port);
return cb(null);
}
});
}
tryConnect();
};
ConnectionManager.prototype._openConnection = function _openConnection(conn, options, cb) {
var dbName = options.databaseName;
if (util.isString(dbName) && dbName.length) {
this._openConnectionMultiDbCase(conn, options, cb);
} else {
conn.open(options, cb);
}
};
ConnectionManager.prototype._openConnectionMultiDbCase = function _openConnectionMultiDbCase(conn, options, cb) {
if (!options.port) {
var instanceNum = extractInstanceNumber(options.instanceNumber);
if (isNaN(instanceNum)) {
return cb(new Error('Instance Number is not valid'));
} else {
options.port = 30013 + (instanceNum * 100);
}
}
function handleError(err) {
conn.close();
cb(err);
}
conn.open(options, function (err) {
if (err) {
return handleError(err);
}
conn.fetchDbConnectInfo({databaseName: options.databaseName}, function (err, info) {
if (err) {
return handleError(err);
}
if (info.isConnected) {
cb(null);
} else {
var initialHost = conn.host;
var initialPort = conn.port;
conn._closeSilently();
options.host = info.host;
options.port = info.port;
conn.setInitialHostAndPort(initialHost, initialPort);
conn.setRedirectHostAndPort(options.host, options.port);
conn.setRedirectType(common.RedirectType.REDIRECTION_DBNAMEBASED);
debug('Connecting to tenant-db %s on %s:%d', options.databaseName, options.host, options.port);
conn.open(options, cb);
}
});
});
};
function extractInstanceNumber(instanceNumber) {
if (util.isNumber(instanceNumber)) {
return instanceNumber;
}
if (util.isString(instanceNumber) && instanceNumber.length) {
return parseInt(instanceNumber, 10);
}
return NaN;
}
function couldNotOpenConnectionError(errorStats) {
var message = 'Could not connect to any host:';
errorStats.forEach(function (stats) {
message += util.format(' [ %s:%d - %s ]', stats.host, stats.port, stats.err.message);
});
var err = new Error(message);
err.code = 'EHDBOPENCONN';
return err;
}