|
@@ -64,6 +64,7 @@ type
|
|
|
read fRandomNumber write fRandomNumber;
|
|
read fRandomNumber write fRandomNumber;
|
|
|
end;
|
|
end;
|
|
|
TOrmCachedWorld = class(TOrmWorld);
|
|
TOrmCachedWorld = class(TOrmWorld);
|
|
|
|
|
+ TOrmWorlds = array of TOrmWorld;
|
|
|
TOrmWorldClass = class of TOrmWorld;
|
|
TOrmWorldClass = class of TOrmWorld;
|
|
|
TOrmFortune = class(TOrm)
|
|
TOrmFortune = class(TOrm)
|
|
|
protected
|
|
protected
|
|
@@ -86,24 +87,24 @@ type
|
|
|
// as used by rawqueries and rawupdates
|
|
// as used by rawqueries and rawupdates
|
|
|
function getRawRandomWorlds(cnt: PtrInt; out res: TWorlds): boolean;
|
|
function getRawRandomWorlds(cnt: PtrInt; out res: TWorlds): boolean;
|
|
|
// implements /queries and /cached-queries endpoints
|
|
// implements /queries and /cached-queries endpoints
|
|
|
- function doqueries(ctxt: THttpServerRequestAbstract; orm: TOrmWorldClass;
|
|
|
|
|
|
|
+ function doqueries(ctxt: THttpServerRequest; orm: TOrmWorldClass;
|
|
|
const search: RawUtf8): cardinal;
|
|
const search: RawUtf8): cardinal;
|
|
|
public
|
|
public
|
|
|
constructor Create(threadCount: integer; flags: THttpServerOptions); reintroduce;
|
|
constructor Create(threadCount: integer; flags: THttpServerOptions); reintroduce;
|
|
|
destructor Destroy; override;
|
|
destructor Destroy; override;
|
|
|
published
|
|
published
|
|
|
// all service URI are implemented by these published methods using RTTI
|
|
// all service URI are implemented by these published methods using RTTI
|
|
|
- function plaintext(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
- function json(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
- function db(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
- function queries(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
- function cached_queries(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
- function fortunes(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
- function updates(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
- function rawdb(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
- function rawqueries(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
- function rawfortunes(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
- function rawupdates(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
|
|
+ function plaintext(ctxt: THttpServerRequest): cardinal;
|
|
|
|
|
+ function json(ctxt: THttpServerRequest): cardinal;
|
|
|
|
|
+ function db(ctxt: THttpServerRequest): cardinal;
|
|
|
|
|
+ function queries(ctxt: THttpServerRequest): cardinal;
|
|
|
|
|
+ function cached_queries(ctxt: THttpServerRequest): cardinal;
|
|
|
|
|
+ function fortunes(ctxt: THttpServerRequest): cardinal;
|
|
|
|
|
+ function updates(ctxt: THttpServerRequest): cardinal;
|
|
|
|
|
+ function rawdb(ctxt: THttpServerRequest): cardinal;
|
|
|
|
|
+ function rawqueries(ctxt: THttpServerRequest): cardinal;
|
|
|
|
|
+ function rawfortunes(ctxt: THttpServerRequest): cardinal;
|
|
|
|
|
+ function rawupdates(ctxt: THttpServerRequest): cardinal;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
const
|
|
const
|
|
@@ -137,7 +138,7 @@ begin
|
|
|
result := Random32(WORLD_COUNT) + 1;
|
|
result := Random32(WORLD_COUNT) + 1;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
-function getQueriesParamValue(ctxt: THttpServerRequestAbstract;
|
|
|
|
|
|
|
+function getQueriesParamValue(ctxt: THttpServerRequest;
|
|
|
const search: RawUtf8 = 'QUERIES='): cardinal;
|
|
const search: RawUtf8 = 'QUERIES='): cardinal;
|
|
|
begin
|
|
begin
|
|
|
if not ctxt.UrlParam(search, result) then
|
|
if not ctxt.UrlParam(search, result) then
|
|
@@ -157,17 +158,28 @@ begin
|
|
|
inherited Create;
|
|
inherited Create;
|
|
|
fDbPool := TSqlDBPostgresConnectionProperties.Create(
|
|
fDbPool := TSqlDBPostgresConnectionProperties.Create(
|
|
|
'tfb-database:5432', 'hello_world', 'benchmarkdbuser', 'benchmarkdbpass');
|
|
'tfb-database:5432', 'hello_world', 'benchmarkdbuser', 'benchmarkdbpass');
|
|
|
|
|
+ // customize JSON serialization for TFB expectations
|
|
|
|
|
+ TOrmWorld.OrmProps.Fields.JsonRenameProperties([
|
|
|
|
|
+ 'ID', 'id',
|
|
|
|
|
+ 'RandomNumber', 'randomNumber']);
|
|
|
|
|
+ TOrmCachedWorld.OrmProps.Fields.JsonRenameProperties([
|
|
|
|
|
+ 'ID', 'id',
|
|
|
|
|
+ 'RandomNumber', 'randomNumber']);
|
|
|
|
|
+ // setup the ORM data model
|
|
|
fModel := TOrmModel.Create([TOrmWorld, TOrmFortune, TOrmCachedWorld]);
|
|
fModel := TOrmModel.Create([TOrmWorld, TOrmFortune, TOrmCachedWorld]);
|
|
|
OrmMapExternal(fModel, [TOrmWorld, TOrmFortune], fDbPool);
|
|
OrmMapExternal(fModel, [TOrmWorld, TOrmFortune], fDbPool);
|
|
|
// CachedWorld table doesn't exists in DB, but should as read in requirements.
|
|
// CachedWorld table doesn't exists in DB, but should as read in requirements.
|
|
|
// Use world table as in other implementations.
|
|
// Use world table as in other implementations.
|
|
|
OrmMapExternal(fModel, TOrmCachedWorld, fDbPool, 'world');
|
|
OrmMapExternal(fModel, TOrmCachedWorld, fDbPool, 'world');
|
|
|
|
|
+ // setup the main ORM store
|
|
|
fStore := TRestServerDB.Create(fModel, SQLITE_MEMORY_DATABASE_NAME);
|
|
fStore := TRestServerDB.Create(fModel, SQLITE_MEMORY_DATABASE_NAME);
|
|
|
fStore.NoAjaxJson := true;
|
|
fStore.NoAjaxJson := true;
|
|
|
fStore.Server.CreateMissingTables; // create SQlite3 virtual tables
|
|
fStore.Server.CreateMissingTables; // create SQlite3 virtual tables
|
|
|
if fStore.Server.Cache.SetCache(TOrmCachedWorld) then
|
|
if fStore.Server.Cache.SetCache(TOrmCachedWorld) then
|
|
|
fStore.Server.Cache.FillFromQuery(TOrmCachedWorld, '', []);
|
|
fStore.Server.Cache.FillFromQuery(TOrmCachedWorld, '', []);
|
|
|
|
|
+ // initialize the mustache template for /fortunes
|
|
|
fTemplate := TSynMustache.Parse(FORTUNES_TPL);
|
|
fTemplate := TSynMustache.Parse(FORTUNES_TPL);
|
|
|
|
|
+ // setup the HTTP server
|
|
|
fHttpServer := THttpAsyncServer.Create(
|
|
fHttpServer := THttpAsyncServer.Create(
|
|
|
'8080', nil, nil, '', threadCount,
|
|
'8080', nil, nil, '', threadCount,
|
|
|
5 * 60 * 1000, // 5 minutes keep alive connections
|
|
5 * 60 * 1000, // 5 minutes keep alive connections
|
|
@@ -182,6 +194,7 @@ begin
|
|
|
hsoIncludeDateHeader // required by TPW General Test Requirements #5
|
|
hsoIncludeDateHeader // required by TPW General Test Requirements #5
|
|
|
] + flags);
|
|
] + flags);
|
|
|
fHttpServer.HttpQueueLength := 10000; // needed e.g. from wrk/ab benchmarks
|
|
fHttpServer.HttpQueueLength := 10000; // needed e.g. from wrk/ab benchmarks
|
|
|
|
|
+ // use default routing using RTTI on the TRawAsyncServer published methods
|
|
|
fHttpServer.Route.RunMethods([urmGet], self);
|
|
fHttpServer.Route.RunMethods([urmGet], self);
|
|
|
// writeln(fHttpServer.Route.Tree[urmGet].ToText);
|
|
// writeln(fHttpServer.Route.Tree[urmGet].ToText);
|
|
|
fHttpServer.WaitStarted; // raise exception e.g. on binding issue
|
|
fHttpServer.WaitStarted; // raise exception e.g. on binding issue
|
|
@@ -196,23 +209,23 @@ begin
|
|
|
inherited Destroy;
|
|
inherited Destroy;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
-function TRawAsyncServer.plaintext(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
|
|
+function TRawAsyncServer.plaintext(ctxt: THttpServerRequest): cardinal;
|
|
|
begin
|
|
begin
|
|
|
ctxt.OutContentType := TEXT_CONTENT_TYPE_NO_ENCODING;
|
|
ctxt.OutContentType := TEXT_CONTENT_TYPE_NO_ENCODING;
|
|
|
ctxt.OutContent := HELLO_WORLD;
|
|
ctxt.OutContent := HELLO_WORLD;
|
|
|
result := HTTP_SUCCESS;
|
|
result := HTTP_SUCCESS;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
-function TRawAsyncServer.json(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
|
|
+function TRawAsyncServer.json(ctxt: THttpServerRequest): cardinal;
|
|
|
var
|
|
var
|
|
|
msgRec: TMessageRec;
|
|
msgRec: TMessageRec;
|
|
|
begin
|
|
begin
|
|
|
msgRec.message := HELLO_WORLD;
|
|
msgRec.message := HELLO_WORLD;
|
|
|
- ctxt.SetOutJson(SaveJson(msgRec, TypeInfo(TMessageRec)));
|
|
|
|
|
|
|
+ ctxt.SetOutJson(@msgRec, TypeInfo(TMessageRec));
|
|
|
result := HTTP_SUCCESS;
|
|
result := HTTP_SUCCESS;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
-function TRawAsyncServer.rawdb(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
|
|
+function TRawAsyncServer.rawdb(ctxt: THttpServerRequest): cardinal;
|
|
|
var
|
|
var
|
|
|
conn: TSqlDBConnection;
|
|
conn: TSqlDBConnection;
|
|
|
stmt: ISQLDBStatement;
|
|
stmt: ISQLDBStatement;
|
|
@@ -232,25 +245,25 @@ begin
|
|
|
stmt := nil;
|
|
stmt := nil;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
-function TRawAsyncServer.db(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
|
|
+function TRawAsyncServer.db(ctxt: THttpServerRequest): cardinal;
|
|
|
var
|
|
var
|
|
|
w: TOrmWorld;
|
|
w: TOrmWorld;
|
|
|
begin
|
|
begin
|
|
|
w := TOrmWorld.Create(fStore.Orm, RandomWorld);
|
|
w := TOrmWorld.Create(fStore.Orm, RandomWorld);
|
|
|
try
|
|
try
|
|
|
- ctxt.SetOutJson('{"id":%,"randomNumber":%}', [w.IDValue, w.randomNumber]);
|
|
|
|
|
|
|
+ ctxt.SetOutJson(w);
|
|
|
result := HTTP_SUCCESS;
|
|
result := HTTP_SUCCESS;
|
|
|
finally
|
|
finally
|
|
|
w.Free;
|
|
w.Free;
|
|
|
end;
|
|
end;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
-function TRawAsyncServer.queries(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
|
|
+function TRawAsyncServer.queries(ctxt: THttpServerRequest): cardinal;
|
|
|
begin
|
|
begin
|
|
|
result := doqueries(ctxt, TOrmWorld, 'QUERIES=');
|
|
result := doqueries(ctxt, TOrmWorld, 'QUERIES=');
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
-function TRawAsyncServer.cached_queries(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
|
|
+function TRawAsyncServer.cached_queries(ctxt: THttpServerRequest): cardinal;
|
|
|
begin
|
|
begin
|
|
|
result := doqueries(ctxt, TOrmCachedWorld, 'COUNT=');
|
|
result := doqueries(ctxt, TOrmCachedWorld, 'COUNT=');
|
|
|
end;
|
|
end;
|
|
@@ -266,18 +279,16 @@ begin
|
|
|
result := false;
|
|
result := false;
|
|
|
SetLength(res{%H-}, cnt);
|
|
SetLength(res{%H-}, cnt);
|
|
|
conn := fDbPool.ThreadSafeConnection;
|
|
conn := fDbPool.ThreadSafeConnection;
|
|
|
- if not conn.IsConnected then
|
|
|
|
|
- conn.Connect;
|
|
|
|
|
// specific code to use PostgresSQL pipelining mode
|
|
// specific code to use PostgresSQL pipelining mode
|
|
|
// see test_multi_pipelines in
|
|
// see test_multi_pipelines in
|
|
|
// https://github.com/postgres/postgres/blob/master/src/test/modules/libpq_pipeline/libpq_pipeline.c
|
|
// https://github.com/postgres/postgres/blob/master/src/test/modules/libpq_pipeline/libpq_pipeline.c
|
|
|
stmt := conn.NewStatementPrepared(WORLD_READ_SQL, true, true);
|
|
stmt := conn.NewStatementPrepared(WORLD_READ_SQL, true, true);
|
|
|
//conn.StartTransaction;
|
|
//conn.StartTransaction;
|
|
|
pConn.EnterPipelineMode;
|
|
pConn.EnterPipelineMode;
|
|
|
- pStmt := (stmt as TSqlDBPostgresStatement);
|
|
|
|
|
|
|
+ pStmt := TSqlDBPostgresStatement(stmt.Instance);
|
|
|
for i := 0 to cnt - 1 do
|
|
for i := 0 to cnt - 1 do
|
|
|
begin
|
|
begin
|
|
|
- stmt.Bind(1, RandomWorld);
|
|
|
|
|
|
|
+ pStmt.Bind(1, RandomWorld);
|
|
|
pStmt.SendPipelinePrepared;
|
|
pStmt.SendPipelinePrepared;
|
|
|
pConn.PipelineSync;
|
|
pConn.PipelineSync;
|
|
|
end;
|
|
end;
|
|
@@ -296,7 +307,7 @@ begin
|
|
|
result := true;
|
|
result := true;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
-function TRawAsyncServer.rawqueries(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
|
|
+function TRawAsyncServer.rawqueries(ctxt: THttpServerRequest): cardinal;
|
|
|
var
|
|
var
|
|
|
cnt: PtrInt;
|
|
cnt: PtrInt;
|
|
|
res: TWorlds;
|
|
res: TWorlds;
|
|
@@ -304,33 +315,27 @@ begin
|
|
|
cnt := getQueriesParamValue(ctxt);
|
|
cnt := getQueriesParamValue(ctxt);
|
|
|
if not getRawRandomWorlds(cnt, res) then
|
|
if not getRawRandomWorlds(cnt, res) then
|
|
|
exit(HTTP_SERVERERROR);
|
|
exit(HTTP_SERVERERROR);
|
|
|
- ctxt.SetOutJson(SaveJson(res, TypeInfo(TWorlds)));
|
|
|
|
|
|
|
+ ctxt.SetOutJson(@res, TypeInfo(TWorlds));
|
|
|
result := HTTP_SUCCESS;
|
|
result := HTTP_SUCCESS;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
-function TRawAsyncServer.doqueries(ctxt: THttpServerRequestAbstract;
|
|
|
|
|
|
|
+function TRawAsyncServer.doqueries(ctxt: THttpServerRequest;
|
|
|
orm: TOrmWorldClass; const search: RawUtf8): cardinal;
|
|
orm: TOrmWorldClass; const search: RawUtf8): cardinal;
|
|
|
var
|
|
var
|
|
|
cnt, i: PtrInt;
|
|
cnt, i: PtrInt;
|
|
|
- res: TWorlds;
|
|
|
|
|
- w: TOrmWorld;
|
|
|
|
|
|
|
+ res: TOrmWorlds;
|
|
|
begin
|
|
begin
|
|
|
result := HTTP_SERVERERROR;
|
|
result := HTTP_SERVERERROR;
|
|
|
cnt := getQueriesParamValue(ctxt, search);
|
|
cnt := getQueriesParamValue(ctxt, search);
|
|
|
SetLength(res, cnt);
|
|
SetLength(res, cnt);
|
|
|
- w := orm.Create; // TOrmWorld or TOrmCachedWorld
|
|
|
|
|
- try
|
|
|
|
|
- for i := 0 to cnt - 1 do
|
|
|
|
|
- begin
|
|
|
|
|
- if not fStore.Orm.Retrieve(RandomWorld, w) then
|
|
|
|
|
- exit;
|
|
|
|
|
- res[i].id := w.IDValue;
|
|
|
|
|
- res[i].randomNumber := w.RandomNumber;
|
|
|
|
|
- end;
|
|
|
|
|
- finally
|
|
|
|
|
- w.Free;
|
|
|
|
|
|
|
+ for i := 0 to cnt - 1 do
|
|
|
|
|
+ begin
|
|
|
|
|
+ res[i] := orm.Create; // TOrmWorld or TOrmCachedWorld
|
|
|
|
|
+ if not fStore.Orm.Retrieve(RandomWorld, res[i]) then
|
|
|
|
|
+ exit;
|
|
|
end;
|
|
end;
|
|
|
- ctxt.SetOutJson(SaveJson(res, TypeInfo(TWorlds)));
|
|
|
|
|
|
|
+ ctxt.SetOutJson(@res, TypeInfo(TOrmWorlds));
|
|
|
|
|
+ ObjArrayClear(res);
|
|
|
result := HTTP_SUCCESS;
|
|
result := HTTP_SUCCESS;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
@@ -339,7 +344,7 @@ begin
|
|
|
result := StrComp(pointer(TOrmFortune(A).Message), pointer(TOrmFortune(B).Message));
|
|
result := StrComp(pointer(TOrmFortune(A).Message), pointer(TOrmFortune(B).Message));
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
-function TRawAsyncServer.fortunes(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
|
|
+function TRawAsyncServer.fortunes(ctxt: THttpServerRequest): cardinal;
|
|
|
var
|
|
var
|
|
|
list: TOrmFortunes;
|
|
list: TOrmFortunes;
|
|
|
new: TOrmFortune;
|
|
new: TOrmFortune;
|
|
@@ -366,7 +371,7 @@ begin
|
|
|
result := StrComp(pointer(TFortune(A).message), pointer(TFortune(B).message));
|
|
result := StrComp(pointer(TFortune(A).message), pointer(TFortune(B).message));
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
-function TRawAsyncServer.rawfortunes(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
|
|
+function TRawAsyncServer.rawfortunes(ctxt: THttpServerRequest): cardinal;
|
|
|
var
|
|
var
|
|
|
conn: TSqlDBConnection;
|
|
conn: TSqlDBConnection;
|
|
|
stmt: ISQLDBStatement;
|
|
stmt: ISQLDBStatement;
|
|
@@ -394,10 +399,10 @@ begin
|
|
|
result := HTTP_SUCCESS;
|
|
result := HTTP_SUCCESS;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
-function TRawAsyncServer.updates(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
|
|
+function TRawAsyncServer.updates(ctxt: THttpServerRequest): cardinal;
|
|
|
var
|
|
var
|
|
|
cnt, i: PtrInt;
|
|
cnt, i: PtrInt;
|
|
|
- res: TWorlds;
|
|
|
|
|
|
|
+ res: TOrmWorlds;
|
|
|
w: TOrmWorld;
|
|
w: TOrmWorld;
|
|
|
b: TRestBatch;
|
|
b: TRestBatch;
|
|
|
begin
|
|
begin
|
|
@@ -406,28 +411,26 @@ begin
|
|
|
SetLength(res, cnt);
|
|
SetLength(res, cnt);
|
|
|
b := TRestBatch.Create(fStore.ORM, TOrmWorld, {transrows=}0,
|
|
b := TRestBatch.Create(fStore.ORM, TOrmWorld, {transrows=}0,
|
|
|
[boExtendedJson, boNoModelEncoding, boPutNoCacheFlush]);
|
|
[boExtendedJson, boNoModelEncoding, boPutNoCacheFlush]);
|
|
|
- w := TOrmWorld.Create;
|
|
|
|
|
try
|
|
try
|
|
|
for i := 0 to cnt - 1 do
|
|
for i := 0 to cnt - 1 do
|
|
|
begin
|
|
begin
|
|
|
|
|
+ w := TOrmWorld.Create;
|
|
|
|
|
+ res[i] := w;
|
|
|
if not fStore.Orm.Retrieve(RandomWorld, w) then
|
|
if not fStore.Orm.Retrieve(RandomWorld, w) then
|
|
|
exit;
|
|
exit;
|
|
|
w.RandomNumber := RandomWorld;
|
|
w.RandomNumber := RandomWorld;
|
|
|
b.Update(w);
|
|
b.Update(w);
|
|
|
- res[i].id := w.IDValue;
|
|
|
|
|
- res[i].randomNumber := w.RandomNumber;
|
|
|
|
|
end;
|
|
end;
|
|
|
- result := fStore.Orm.BatchSend(b);
|
|
|
|
|
|
|
+ result := b.Send;
|
|
|
|
|
+ if result = HTTP_SUCCESS then
|
|
|
|
|
+ ctxt.SetOutJson(@res, TypeInfo(TOrmWorlds));
|
|
|
finally
|
|
finally
|
|
|
- w.Free;
|
|
|
|
|
b.Free;
|
|
b.Free;
|
|
|
|
|
+ ObjArrayClear(res);
|
|
|
end;
|
|
end;
|
|
|
- if result <> HTTP_SUCCESS then
|
|
|
|
|
- exit;
|
|
|
|
|
- ctxt.SetOutJson(SaveJson(res, TypeInfo(TWorlds)));
|
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
-function TRawAsyncServer.rawupdates(ctxt: THttpServerRequestAbstract): cardinal;
|
|
|
|
|
|
|
+function TRawAsyncServer.rawupdates(ctxt: THttpServerRequest): cardinal;
|
|
|
var
|
|
var
|
|
|
cnt, i: PtrInt;
|
|
cnt, i: PtrInt;
|
|
|
words: TWorlds;
|
|
words: TWorlds;
|
|
@@ -453,8 +456,8 @@ begin
|
|
|
stmt.BindArray(1, ids);
|
|
stmt.BindArray(1, ids);
|
|
|
stmt.BindArray(2, nums);
|
|
stmt.BindArray(2, nums);
|
|
|
stmt.ExecutePrepared;
|
|
stmt.ExecutePrepared;
|
|
|
- //conn.Commit;
|
|
|
|
|
- ctxt.SetOutJson(SaveJson(words, TypeInfo(TWorlds)));
|
|
|
|
|
|
|
+ //conn.Commit; // autocommit
|
|
|
|
|
+ ctxt.SetOutJson(@words, TypeInfo(TWorlds));
|
|
|
result := HTTP_SUCCESS;
|
|
result := HTTP_SUCCESS;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
@@ -470,6 +473,8 @@ begin
|
|
|
TSynLog.Family.Level := LOG_VERBOSE; // disable logs for benchmarking
|
|
TSynLog.Family.Level := LOG_VERBOSE; // disable logs for benchmarking
|
|
|
TSynLog.Family.HighResolutionTimestamp := true;
|
|
TSynLog.Family.HighResolutionTimestamp := true;
|
|
|
TSynLog.Family.AutoFlushTimeOut := 1;
|
|
TSynLog.Family.AutoFlushTimeOut := 1;
|
|
|
|
|
+ {$else}
|
|
|
|
|
+ SynDBLog := nil; // slightly faster: no need to check log level
|
|
|
{$endif WITH_LOGS}
|
|
{$endif WITH_LOGS}
|
|
|
TSynLog.Family.PerThreadLog := ptIdentifiedInOneFile;
|
|
TSynLog.Family.PerThreadLog := ptIdentifiedInOneFile;
|
|
|
|
|
|
|
@@ -544,8 +549,7 @@ begin
|
|
|
writeln(ObjectToJsonDebug(rawServers[i].fHttpServer,
|
|
writeln(ObjectToJsonDebug(rawServers[i].fHttpServer,
|
|
|
[woDontStoreVoid, woHumanReadable]));
|
|
[woDontStoreVoid, woHumanReadable]));
|
|
|
finally
|
|
finally
|
|
|
- for i := 0 to servers - 1 do
|
|
|
|
|
- rawServers[i].Free;
|
|
|
|
|
|
|
+ ObjArrayClear(rawServers);
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
{$ifdef FPC_X64MM}
|
|
{$ifdef FPC_X64MM}
|