@@ -4,6 +4,8 @@ import std.array;
44import std.algorithm ;
55import std.conv ;
66import std.ascii ;
7+ import core.stdc.stdlib ;
8+ import core.stdc.string ;
79
810import mir.ser;
911import mir.ser.json;
@@ -14,13 +16,14 @@ import std.range.primitives;
1416
1517import glow.xbuf;
1618
17- import photon, photon.http;
19+ import photon, photon.http, photon.mustache ;
1820
1921import mir.random : unpredictableSeedOf;
2022import mir.random.variable : UniformVariable;
2123import mir.random.engine.xorshift : Xorshift;
2224
2325import dpq2;
26+ import dpq2.conv.to_d_types;
2427
2528struct Message {
2629 string message;
@@ -31,6 +34,11 @@ struct WorldResponse {
3134 int randomNumber;
3235}
3336
37+ struct FortuneResponse {
38+ int id;
39+ string message;
40+ }
41+
3442enum connectionInfo = " host=tfb-database port=5432 "
3543 ~ " dbname=hello_world user=benchmarkdbuser password=benchmarkdbpass" ;
3644enum worldSize = 10000 ;
@@ -41,7 +49,8 @@ shared Pool!Connection connectionPool;
4149class BenchmarkProcessor : HttpProcessor {
4250 HttpHeader [] plainTextHeaders = [HttpHeader (" Content-Type" , " text/plain; charset=utf-8" )];
4351 HttpHeader [] jsonHeaders = [HttpHeader (" Content-Type" , " application/json" )];
44- Buffer ! char jsonBuf;
52+ HttpHeader [] htmlHeaders = [HttpHeader (" Content-Type" , " text/html; charset=utf-8" )];
53+ Buffer ! char outBuf;
4554 Buffer ! WorldResponse worlds;
4655 UniformVariable! uint uniformVariable;
4756 Xorshift gen;
@@ -50,7 +59,7 @@ class BenchmarkProcessor : HttpProcessor {
5059 super (sock);
5160 gen = Xorshift(unpredictableSeed! uint );
5261 uniformVariable = UniformVariable! uint (1 , worldSize);
53- jsonBuf = Buffer ! char (256 );
62+ outBuf = Buffer ! char (256 );
5463 worlds = Buffer ! WorldResponse(500 );
5564 }
5665
@@ -65,8 +74,9 @@ class BenchmarkProcessor : HttpProcessor {
6574 queries(req.uri);
6675 } else if (req.uri.startsWith(" /updates" )) {
6776 updates(req.uri);
68- }
69- else {
77+ } else if (req.uri == " /fortunes" ) {
78+ fortunes();
79+ } else {
7080 respondWith(" Not found" , HttpStatus .NotFound, plainTextHeaders);
7181 }
7282 }
@@ -76,13 +86,13 @@ class BenchmarkProcessor : HttpProcessor {
7686 }
7787
7888 final void json () {
79- jsonBuf .clear();
80- serializeJsonPretty! " " (jsonBuf , Message(" Hello, World!" ));
81- respondWith(jsonBuf .data, HttpStatus .OK , jsonHeaders);
89+ outBuf .clear();
90+ serializeJsonPretty! " " (outBuf , Message(" Hello, World!" ));
91+ respondWith(outBuf .data, HttpStatus .OK , jsonHeaders);
8292 }
8393
8494 final void db () {
85- jsonBuf .clear();
95+ outBuf .clear();
8696 int id = uniformVariable(gen);
8797 auto c = connectionPool.acquire();
8898 scope (exit) connectionPool.release(c);
@@ -91,13 +101,13 @@ class BenchmarkProcessor : HttpProcessor {
91101 qp.argsVariadic(id);
92102 immutable result = c.execPrepared(qp).rangify.front;
93103 auto w = WorldResponse(id, result[0 ].as! PGinteger);
94- serializeJsonPretty! " " (jsonBuf , w);
95- respondWith(jsonBuf .data, HttpStatus .OK , jsonHeaders);
104+ serializeJsonPretty! " " (outBuf , w);
105+ respondWith(outBuf .data, HttpStatus .OK , jsonHeaders);
96106 }
97107
98108 // GET /queries?queries=...
99109 final void queries (const (char )[] uri) {
100- jsonBuf .clear();
110+ outBuf .clear();
101111 worlds.clear();
102112 auto c = connectionPool.acquire();
103113 scope (exit) connectionPool.release(c);
@@ -118,13 +128,13 @@ class BenchmarkProcessor : HttpProcessor {
118128 immutable result = c.execPrepared(qp).rangify.front;
119129 worlds.put(WorldResponse(id, result[0 ].as! PGinteger));
120130 }
121- serializeJsonPretty! " " (jsonBuf , worlds.data);
122- respondWith(jsonBuf .data, HttpStatus .OK , jsonHeaders);
131+ serializeJsonPretty! " " (outBuf , worlds.data);
132+ respondWith(outBuf .data, HttpStatus .OK , jsonHeaders);
123133 }
124134
125135 // GET /updates?queries=...
126136 final void updates (const (char )[] uri) {
127- jsonBuf .clear();
137+ outBuf .clear();
128138 worlds.clear();
129139 auto c = connectionPool.acquire();
130140 scope (exit) connectionPool.release(c);
@@ -157,11 +167,44 @@ class BenchmarkProcessor : HttpProcessor {
157167 c.execPrepared(qp_update);
158168 worlds.put(w);
159169 }
160- serializeJsonPretty! " " (jsonBuf, worlds.data);
161- respondWith(jsonBuf.data, HttpStatus .OK , jsonHeaders);
170+ serializeJsonPretty! " " (outBuf, worlds.data);
171+ respondWith(outBuf.data, HttpStatus .OK , jsonHeaders);
172+ }
173+
174+ final void fortunes () {
175+ outBuf.clear();
176+ auto c = connectionPool.acquire();
177+ scope (exit) connectionPool.release(c);
178+ import std.algorithm : map, sort;
179+
180+ auto buf = Buffer ! FortuneResponse(20 );
181+ QueryParams qp;
182+ qp.preparedStatementName(" fortune_prpq" );
183+ auto result = c.execPrepared(qp).rangify;
184+ foreach (ref f; result) {
185+ buf.put(FortuneResponse(f[0 ].as! PGinteger, f[1 ].data.alloced));
186+ }
187+ buf.put(FortuneResponse(0 , " Additional fortune added at request time." ));
188+ auto data = buf.data;
189+ data.sort! ((a, b) => a.message < b.message);
190+ mustache! (import (" template.mustache" ))(data, outBuf);
191+ foreach (ref v; data) {
192+ if (v.id != 0 ) dealloc(v.message);
193+ }
194+ respondWith(outBuf.data, HttpStatus .OK , htmlHeaders);
162195 }
163196}
164197
198+ string alloced (const (ubyte )[] data) {
199+ void * ptr = malloc(data.length);
200+ memcpy(ptr, data.ptr, data.length);
201+ return (cast (immutable (char )* )ptr)[0 .. data.length];
202+ }
203+
204+ void dealloc (const (char )[] slice) {
205+ free(cast (void * )slice.ptr);
206+ }
207+
165208void server_worker (Socket client) {
166209 scope processor = new BenchmarkProcessor(client);
167210 try {
@@ -201,6 +244,7 @@ void main() {
201244 initPhoton();
202245 connectionPool = pool(poolSize, 15. seconds, () {
203246 auto c = new Connection(connectionInfo);
247+ c.prepareEx(" fortune_prpq" , " SELECT id, message::text FROM Fortune" );
204248 c.prepareEx(" db_prpq" , " SELECT randomNumber, id FROM world WHERE id = $1" );
205249 c.prepareEx(" db_update_prpq" , " UPDATE world SET randomNumber = $1 WHERE id = $2" );
206250 return c;
0 commit comments