-
Notifications
You must be signed in to change notification settings - Fork 33
/
tileserver.js
143 lines (127 loc) · 3.19 KB
/
tileserver.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
node-tileserver Copyright (C) 2014 Alexander Matheisen
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it under certain conditions.
See https://github.com/rurseekatze/node-tileserver for details.
*/
// include necessary modules
var cluster = require('cluster');
var os = require('os');
var rbush = require('rbush');
var assert = require('assert');
var http = require("http");
var url = require("url");
var toobusy = require('toobusy-js');
var byline = require('byline');
var touch = require("touch");
var Canvas = require('canvas');
var events = require('events');
var log4js = require('log4js');
var fs = require('graceful-fs');
var pgPass = require('pgpass');
var Pool = require('pg-pool');
// load configuraion file
configuration = require('./config.json');
// configure logging
log4js.configure(
{
appenders:
[
{
"type": "logLevelFilter",
"level": "ERROR",
"appender":
{
"type": "file",
"filename": 'tileserver.log',
'maxLogSize': 20480,
'backups': 0
}
},
{
"type": "logLevelFilter",
"level": "DEBUG",
"appender":
{
"type": "console"
}
}
]
});
logger = log4js.getLogger();
logger.setLevel('INFO');
Tile = require('./tile.js');
Tilerequest = require('./tilerequest.js');
Tilequeue = require('./queue.js');
// number of cpus
var cpus = os.cpus().length;
// maximum count of concurrent http connections
http.globalAgent.maxSockets = configuration.maxsockets;
// request password from pgpass only once at startup, not for each process or even each request
var connectionDetails =
{
'host' : 'localhost',
'port': configuration.port,
'database': configuration.database,
'user' : configuration.username,
'max': parseInt(configuration.maxPoolSize / cpus),
'idleTimeoutMillis': 10000
};
pgPass(connectionDetails, function(password)
{
if (typeof password == 'undefined')
{
logger.fatal('PGPASS file cannot be read or no matching line for given connection info found');
process.exit(1);
}
logger.debug('Successfully read password using PGPASS');
configuration.password = password;
// fork workers
if (cluster.isMaster)
{
for (var i=0; i<cpus; i++)
cluster.fork();
cluster.on("exit", function(worker, code, signal)
{
logger.fatal("WORKER STOPPED");
cluster.fork();
});
logger.info('Master has started.');
}
// start tile server instance
else
{
// handle exceptions
process.on('uncaughtException', function(err)
{
logger.fatal('An uncaughtException occurred:');
logger.fatal(err);
process.exit(1);
});
// rendering queue for expired tiles
queue = new Tilequeue();
pool = new Pool(connectionDetails);
pool.on('error', function (err, client)
{
logger.error('Idle database client error: ' + err.message)
});
function onRequest(request, response)
{
if (toobusy())
{
logger.info('Server too busy. Aborting.');
response.writeHead(503, {'Content-Type': 'text/plain'});
response.end();
return;
}
else
{
var tilerequest = new Tilerequest(request, response);
tilerequest.getTile();
tilerequest = null;
}
}
http.createServer(onRequest).listen(configuration.tileserverPort);
logger.info('Worker has started.');
}
});