@itwin/core-backend 3.7.0 → 3.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -1
- package/lib/cjs/AliCloudStorageService.d.ts +23 -23
- package/lib/cjs/AliCloudStorageService.js +71 -71
- package/lib/cjs/AliCloudStorageService.js.map +1 -1
- package/lib/cjs/BackendHubAccess.d.ts +224 -224
- package/lib/cjs/BackendHubAccess.js +41 -41
- package/lib/cjs/BackendHubAccess.js.map +1 -1
- package/lib/cjs/BackendLoggerCategory.d.ts +91 -91
- package/lib/cjs/BackendLoggerCategory.js +99 -99
- package/lib/cjs/BackendLoggerCategory.js.map +1 -1
- package/lib/cjs/BisCoreSchema.d.ts +21 -21
- package/lib/cjs/BisCoreSchema.js +60 -60
- package/lib/cjs/BisCoreSchema.js.map +1 -1
- package/lib/cjs/BriefcaseManager.d.ts +170 -170
- package/lib/cjs/BriefcaseManager.js +414 -414
- package/lib/cjs/BriefcaseManager.js.map +1 -1
- package/lib/cjs/Category.d.ts +153 -153
- package/lib/cjs/Category.js +243 -243
- package/lib/cjs/Category.js.map +1 -1
- package/lib/cjs/ChangeSummaryManager.d.ts +187 -187
- package/lib/cjs/ChangeSummaryManager.js +447 -447
- package/lib/cjs/ChangeSummaryManager.js.map +1 -1
- package/lib/cjs/ChangedElementsDb.d.ts +99 -99
- package/lib/cjs/ChangedElementsDb.js +165 -165
- package/lib/cjs/ChangedElementsDb.js.map +1 -1
- package/lib/cjs/ChangedElementsManager.d.ts +39 -39
- package/lib/cjs/ChangedElementsManager.js +88 -88
- package/lib/cjs/ChangedElementsManager.js.map +1 -1
- package/lib/cjs/CheckpointManager.d.ts +121 -121
- package/lib/cjs/CheckpointManager.js +349 -349
- package/lib/cjs/CheckpointManager.js.map +1 -1
- package/lib/cjs/ClassRegistry.d.ts +79 -79
- package/lib/cjs/ClassRegistry.js +250 -250
- package/lib/cjs/ClassRegistry.js.map +1 -1
- package/lib/cjs/CloudSqlite.d.ts +350 -350
- package/lib/cjs/CloudSqlite.js +153 -153
- package/lib/cjs/CloudSqlite.js.map +1 -1
- package/lib/cjs/CloudStorageBackend.d.ts +58 -58
- package/lib/cjs/CloudStorageBackend.js +173 -173
- package/lib/cjs/CloudStorageBackend.js.map +1 -1
- package/lib/cjs/CodeService.d.ts +396 -396
- package/lib/cjs/CodeService.js +63 -63
- package/lib/cjs/CodeService.js.map +1 -1
- package/lib/cjs/CodeSpecs.d.ts +55 -55
- package/lib/cjs/CodeSpecs.js +124 -124
- package/lib/cjs/CodeSpecs.js.map +1 -1
- package/lib/cjs/ConcurrentQuery.d.ts +13 -13
- package/lib/cjs/ConcurrentQuery.js +36 -36
- package/lib/cjs/ConcurrentQuery.js.map +1 -1
- package/lib/cjs/CustomViewState3dCreator.d.ts +21 -21
- package/lib/cjs/CustomViewState3dCreator.js +82 -82
- package/lib/cjs/CustomViewState3dCreator.js.map +1 -1
- package/lib/cjs/DevTools.d.ts +71 -71
- package/lib/cjs/DevTools.js +154 -154
- package/lib/cjs/DevTools.js.map +1 -1
- package/lib/cjs/DisplayStyle.d.ts +106 -106
- package/lib/cjs/DisplayStyle.js +256 -256
- package/lib/cjs/DisplayStyle.js.map +1 -1
- package/lib/cjs/ECDb.d.ts +194 -194
- package/lib/cjs/ECDb.js +355 -355
- package/lib/cjs/ECDb.js.map +1 -1
- package/lib/cjs/ECSchemaXmlContext.d.ts +18 -18
- package/lib/cjs/ECSchemaXmlContext.js +41 -41
- package/lib/cjs/ECSchemaXmlContext.js.map +1 -1
- package/lib/cjs/ECSqlStatement.d.ts +473 -473
- package/lib/cjs/ECSqlStatement.js +791 -791
- package/lib/cjs/ECSqlStatement.js.map +1 -1
- package/lib/cjs/Element.d.ts +1109 -1109
- package/lib/cjs/Element.js +1427 -1427
- package/lib/cjs/Element.js.map +1 -1
- package/lib/cjs/ElementAspect.d.ts +179 -179
- package/lib/cjs/ElementAspect.js +211 -211
- package/lib/cjs/ElementAspect.js.map +1 -1
- package/lib/cjs/ElementGraphics.d.ts +9 -9
- package/lib/cjs/ElementGraphics.js +41 -41
- package/lib/cjs/ElementGraphics.js.map +1 -1
- package/lib/cjs/ElementTreeWalker.d.ts +162 -162
- package/lib/cjs/ElementTreeWalker.js +409 -409
- package/lib/cjs/ElementTreeWalker.js.map +1 -1
- package/lib/cjs/Entity.d.ts +106 -106
- package/lib/cjs/Entity.js +134 -134
- package/lib/cjs/Entity.js.map +1 -1
- package/lib/cjs/EntityReferences.d.ts +49 -49
- package/lib/cjs/EntityReferences.js +95 -95
- package/lib/cjs/EntityReferences.js.map +1 -1
- package/lib/cjs/ExportGraphics.d.ts +317 -317
- package/lib/cjs/ExportGraphics.js +208 -208
- package/lib/cjs/ExportGraphics.js.map +1 -1
- package/lib/cjs/ExternalSource.d.ts +96 -96
- package/lib/cjs/ExternalSource.js +131 -131
- package/lib/cjs/ExternalSource.js.map +1 -1
- package/lib/cjs/GeoCoordConfig.d.ts +19 -19
- package/lib/cjs/GeoCoordConfig.js +85 -85
- package/lib/cjs/GeoCoordConfig.js.map +1 -1
- package/lib/cjs/GeometrySummary.d.ts +4 -4
- package/lib/cjs/GeometrySummary.js +380 -380
- package/lib/cjs/GeometrySummary.js.map +1 -1
- package/lib/cjs/HubMock.d.ts +94 -94
- package/lib/cjs/HubMock.js +222 -222
- package/lib/cjs/HubMock.js.map +1 -1
- package/lib/cjs/IModelCloneContext.d.ts +8 -8
- package/lib/cjs/IModelCloneContext.js +15 -15
- package/lib/cjs/IModelCloneContext.js.map +1 -1
- package/lib/cjs/IModelDb.d.ts +1213 -1213
- package/lib/cjs/IModelDb.js +2392 -2392
- package/lib/cjs/IModelDb.js.map +1 -1
- package/lib/cjs/IModelElementCloneContext.d.ts +89 -89
- package/lib/cjs/IModelElementCloneContext.js +159 -159
- package/lib/cjs/IModelElementCloneContext.js.map +1 -1
- package/lib/cjs/IModelHost.d.ts +369 -369
- package/lib/cjs/IModelHost.js +496 -496
- package/lib/cjs/IModelHost.js.map +1 -1
- package/lib/cjs/IModelJsFs.d.ts +62 -62
- package/lib/cjs/IModelJsFs.js +140 -140
- package/lib/cjs/IModelJsFs.js.map +1 -1
- package/lib/cjs/IpcHost.d.ts +104 -104
- package/lib/cjs/IpcHost.js +278 -278
- package/lib/cjs/IpcHost.js.map +1 -1
- package/lib/cjs/LineStyle.d.ts +311 -311
- package/lib/cjs/LineStyle.js +295 -295
- package/lib/cjs/LineStyle.js.map +1 -1
- package/lib/cjs/LocalHub.d.ts +162 -162
- package/lib/cjs/LocalHub.js +585 -585
- package/lib/cjs/LocalHub.js.map +1 -1
- package/lib/cjs/LocalhostIpcHost.d.ts +20 -20
- package/lib/cjs/LocalhostIpcHost.js +81 -81
- package/lib/cjs/LocalhostIpcHost.js.map +1 -1
- package/lib/cjs/Material.d.ts +131 -131
- package/lib/cjs/Material.js +181 -181
- package/lib/cjs/Material.js.map +1 -1
- package/lib/cjs/Model.d.ts +392 -392
- package/lib/cjs/Model.js +485 -485
- package/lib/cjs/Model.js.map +1 -1
- package/lib/cjs/NativeAppStorage.d.ts +51 -51
- package/lib/cjs/NativeAppStorage.js +202 -202
- package/lib/cjs/NativeAppStorage.js.map +1 -1
- package/lib/cjs/NativeHost.d.ts +52 -52
- package/lib/cjs/NativeHost.js +163 -163
- package/lib/cjs/NativeHost.js.map +1 -1
- package/lib/cjs/NavigationRelationship.d.ts +156 -156
- package/lib/cjs/NavigationRelationship.js +225 -225
- package/lib/cjs/NavigationRelationship.js.map +1 -1
- package/lib/cjs/PromiseMemoizer.d.ts +51 -51
- package/lib/cjs/PromiseMemoizer.js +101 -101
- package/lib/cjs/PromiseMemoizer.js.map +1 -1
- package/lib/cjs/PropertyStore.d.ts +132 -132
- package/lib/cjs/PropertyStore.js +11 -11
- package/lib/cjs/PropertyStore.js.map +1 -1
- package/lib/cjs/Relationship.d.ts +416 -416
- package/lib/cjs/Relationship.js +494 -494
- package/lib/cjs/Relationship.js.map +1 -1
- package/lib/cjs/RpcBackend.d.ts +5 -5
- package/lib/cjs/RpcBackend.js +32 -32
- package/lib/cjs/RpcBackend.js.map +1 -1
- package/lib/cjs/SQLiteDb.d.ts +219 -219
- package/lib/cjs/SQLiteDb.js +214 -214
- package/lib/cjs/SQLiteDb.js.map +1 -1
- package/lib/cjs/Schema.d.ts +55 -55
- package/lib/cjs/Schema.js +83 -83
- package/lib/cjs/Schema.js.map +1 -1
- package/lib/cjs/ServerBasedLocks.d.ts +57 -57
- package/lib/cjs/ServerBasedLocks.js +168 -168
- package/lib/cjs/ServerBasedLocks.js.map +1 -1
- package/lib/cjs/SqliteStatement.d.ts +360 -360
- package/lib/cjs/SqliteStatement.js +586 -586
- package/lib/cjs/SqliteStatement.js.map +1 -1
- package/lib/cjs/Texture.d.ts +58 -58
- package/lib/cjs/Texture.js +82 -82
- package/lib/cjs/Texture.js.map +1 -1
- package/lib/cjs/TileStorage.d.ts +18 -18
- package/lib/cjs/TileStorage.d.ts.map +1 -1
- package/lib/cjs/TileStorage.js +90 -90
- package/lib/cjs/TileStorage.js.map +1 -1
- package/lib/cjs/TxnManager.d.ts +202 -202
- package/lib/cjs/TxnManager.js +356 -356
- package/lib/cjs/TxnManager.js.map +1 -1
- package/lib/cjs/ViewDefinition.d.ts +439 -439
- package/lib/cjs/ViewDefinition.js +646 -646
- package/lib/cjs/ViewDefinition.js.map +1 -1
- package/lib/cjs/ViewStateHydrator.d.ts +13 -13
- package/lib/cjs/ViewStateHydrator.js +103 -103
- package/lib/cjs/ViewStateHydrator.js.map +1 -1
- package/lib/cjs/assets/IModelChange.02.00.00.ecschema.xml +90 -90
- package/lib/cjs/assets/Settings/Schemas/Cloud.Schema.json +67 -67
- package/lib/cjs/assets/Settings/Schemas/Gcs.schema.json +31 -31
- package/lib/cjs/assets/Settings/Schemas/Workspace.Schema.json +52 -52
- package/lib/cjs/assets/Settings/backend.setting.json5 +138 -138
- package/lib/cjs/core-backend.d.ts +184 -184
- package/lib/cjs/core-backend.js +204 -204
- package/lib/cjs/core-backend.js.map +1 -1
- package/lib/cjs/domains/FunctionalElements.d.ts +101 -101
- package/lib/cjs/domains/FunctionalElements.js +145 -145
- package/lib/cjs/domains/FunctionalElements.js.map +1 -1
- package/lib/cjs/domains/FunctionalSchema.d.ts +13 -13
- package/lib/cjs/domains/FunctionalSchema.js +40 -40
- package/lib/cjs/domains/FunctionalSchema.js.map +1 -1
- package/lib/cjs/domains/GenericElements.d.ts +177 -177
- package/lib/cjs/domains/GenericElements.js +263 -263
- package/lib/cjs/domains/GenericElements.js.map +1 -1
- package/lib/cjs/domains/GenericSchema.d.ts +10 -10
- package/lib/cjs/domains/GenericSchema.js +28 -28
- package/lib/cjs/domains/GenericSchema.js.map +1 -1
- package/lib/cjs/rpc/multipart.d.ts +11 -11
- package/lib/cjs/rpc/multipart.js +71 -71
- package/lib/cjs/rpc/multipart.js.map +1 -1
- package/lib/cjs/rpc/tracing.d.ts +28 -28
- package/lib/cjs/rpc/tracing.js +74 -74
- package/lib/cjs/rpc/tracing.js.map +1 -1
- package/lib/cjs/rpc/web/logging.d.ts +9 -9
- package/lib/cjs/rpc/web/logging.js +43 -43
- package/lib/cjs/rpc/web/logging.js.map +1 -1
- package/lib/cjs/rpc/web/request.d.ts +6 -6
- package/lib/cjs/rpc/web/request.js +74 -74
- package/lib/cjs/rpc/web/request.js.map +1 -1
- package/lib/cjs/rpc/web/response.d.ts +6 -6
- package/lib/cjs/rpc/web/response.js +106 -106
- package/lib/cjs/rpc/web/response.js.map +1 -1
- package/lib/cjs/rpc-impl/DevToolsRpcImpl.d.ts +15 -15
- package/lib/cjs/rpc-impl/DevToolsRpcImpl.js +32 -32
- package/lib/cjs/rpc-impl/DevToolsRpcImpl.js.map +1 -1
- package/lib/cjs/rpc-impl/IModelReadRpcImpl.d.ts +47 -47
- package/lib/cjs/rpc-impl/IModelReadRpcImpl.js +294 -294
- package/lib/cjs/rpc-impl/IModelReadRpcImpl.js.map +1 -1
- package/lib/cjs/rpc-impl/IModelTileRpcImpl.d.ts +22 -22
- package/lib/cjs/rpc-impl/IModelTileRpcImpl.js +205 -205
- package/lib/cjs/rpc-impl/IModelTileRpcImpl.js.map +1 -1
- package/lib/cjs/rpc-impl/RpcBriefcaseUtility.d.ts +36 -36
- package/lib/cjs/rpc-impl/RpcBriefcaseUtility.js +168 -168
- package/lib/cjs/rpc-impl/RpcBriefcaseUtility.js.map +1 -1
- package/lib/cjs/rpc-impl/SnapshotIModelRpcImpl.d.ts +16 -16
- package/lib/cjs/rpc-impl/SnapshotIModelRpcImpl.js +43 -43
- package/lib/cjs/rpc-impl/SnapshotIModelRpcImpl.js.map +1 -1
- package/lib/cjs/rpc-impl/WipRpcImpl.d.ts +15 -15
- package/lib/cjs/rpc-impl/WipRpcImpl.js +37 -37
- package/lib/cjs/rpc-impl/WipRpcImpl.js.map +1 -1
- package/lib/cjs/workspace/Settings.d.ts +186 -186
- package/lib/cjs/workspace/Settings.js +155 -155
- package/lib/cjs/workspace/Settings.js.map +1 -1
- package/lib/cjs/workspace/SettingsSchemas.d.ts +75 -75
- package/lib/cjs/workspace/SettingsSchemas.js +191 -191
- package/lib/cjs/workspace/SettingsSchemas.js.map +1 -1
- package/lib/cjs/workspace/Workspace.d.ts +414 -414
- package/lib/cjs/workspace/Workspace.js +543 -543
- package/lib/cjs/workspace/Workspace.js.map +1 -1
- package/package.json +12 -12
package/lib/cjs/LocalHub.js
CHANGED
|
@@ -1,586 +1,586 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*---------------------------------------------------------------------------------------------
|
|
3
|
-
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
4
|
-
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
|
-
*--------------------------------------------------------------------------------------------*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.LocalHub = void 0;
|
|
8
|
-
const path_1 = require("path");
|
|
9
|
-
const core_bentley_1 = require("@itwin/core-bentley");
|
|
10
|
-
const core_common_1 = require("@itwin/core-common");
|
|
11
|
-
const BackendHubAccess_1 = require("./BackendHubAccess");
|
|
12
|
-
const BriefcaseManager_1 = require("./BriefcaseManager");
|
|
13
|
-
const IModelDb_1 = require("./IModelDb");
|
|
14
|
-
const IModelJsFs_1 = require("./IModelJsFs");
|
|
15
|
-
const SQLiteDb_1 = require("./SQLiteDb");
|
|
16
|
-
/**
|
|
17
|
-
* A "local" mock for IModelHub to provide access to a single iModel. Used by HubMock.
|
|
18
|
-
* @internal
|
|
19
|
-
*/
|
|
20
|
-
class LocalHub {
|
|
21
|
-
constructor(rootDir, arg) {
|
|
22
|
-
var _a, _b;
|
|
23
|
-
this.rootDir = rootDir;
|
|
24
|
-
this._nextBriefcaseId = core_common_1.BriefcaseIdValue.FirstValid;
|
|
25
|
-
this._latestChangesetIndex = 0;
|
|
26
|
-
this.iTwinId = arg.iTwinId;
|
|
27
|
-
this.iModelId = arg.iModelId;
|
|
28
|
-
this.iModelName = arg.iModelName;
|
|
29
|
-
this.description = arg.description;
|
|
30
|
-
this.cleanup();
|
|
31
|
-
IModelJsFs_1.IModelJsFs.recursiveMkDirSync(this.rootDir);
|
|
32
|
-
IModelJsFs_1.IModelJsFs.mkdirSync(this.changesetDir);
|
|
33
|
-
IModelJsFs_1.IModelJsFs.mkdirSync(this.checkpointDir);
|
|
34
|
-
const db = this._hubDb = new SQLiteDb_1.SQLiteDb();
|
|
35
|
-
db.createDb(this.mockDbName);
|
|
36
|
-
db.executeSQL("CREATE TABLE briefcases(id INTEGER PRIMARY KEY NOT NULL,user TEXT NOT NULL,alias TEXT NOT NULL,assigned INTEGER DEFAULT 1)");
|
|
37
|
-
db.executeSQL("CREATE TABLE timeline(csIndex INTEGER PRIMARY KEY NOT NULL,csId TEXT NOT NULL UNIQUE,description TEXT,user TEXT,size BIGINT,type INTEGER,pushDate TEXT,briefcaseId INTEGER,\
|
|
38
|
-
FOREIGN KEY(briefcaseId) REFERENCES briefcases(id))");
|
|
39
|
-
db.executeSQL("CREATE TABLE checkpoints(csIndex INTEGER PRIMARY KEY NOT NULL)");
|
|
40
|
-
db.executeSQL("CREATE TABLE versions(name TEXT PRIMARY KEY NOT NULL,csIndex TEXT,FOREIGN KEY(csIndex) REFERENCES timeline(csIndex))");
|
|
41
|
-
db.executeSQL("CREATE TABLE locks(id INTEGER PRIMARY KEY NOT NULL,level INTEGER NOT NULL,lastCSetIndex INTEGER,briefcaseId INTEGER)");
|
|
42
|
-
db.executeSQL("CREATE TABLE sharedLocks(lockId INTEGER NOT NULL,briefcaseId INTEGER NOT NULL,PRIMARY KEY(lockId,briefcaseId))");
|
|
43
|
-
db.executeSQL("CREATE INDEX LockIdx ON locks(briefcaseId)");
|
|
44
|
-
db.executeSQL("CREATE INDEX SharedLockIdx ON sharedLocks(briefcaseId)");
|
|
45
|
-
db.saveChanges();
|
|
46
|
-
const version0Root = `${rootDir}_version0`;
|
|
47
|
-
const version0 = (_a = arg.version0) !== null && _a !== void 0 ? _a : (0, path_1.join)(version0Root, "version0.bim");
|
|
48
|
-
if (!arg.version0) { // if they didn't supply a version0 file, create a blank one.
|
|
49
|
-
IModelJsFs_1.IModelJsFs.recursiveMkDirSync(version0Root);
|
|
50
|
-
IModelJsFs_1.IModelJsFs.removeSync(version0);
|
|
51
|
-
IModelDb_1.SnapshotDb.createEmpty(version0, { rootSubject: { name: (_b = arg.description) !== null && _b !== void 0 ? _b : arg.iModelName } }).close();
|
|
52
|
-
}
|
|
53
|
-
const path = this.uploadCheckpoint({ changesetIndex: 0, localFile: version0 });
|
|
54
|
-
if (!arg.version0)
|
|
55
|
-
IModelJsFs_1.IModelJsFs.removeSync(version0);
|
|
56
|
-
const nativeDb = IModelDb_1.IModelDb.openDgnDb({ path }, core_bentley_1.OpenMode.ReadWrite);
|
|
57
|
-
try {
|
|
58
|
-
nativeDb.setITwinId(this.iTwinId);
|
|
59
|
-
nativeDb.setIModelId(this.iModelId);
|
|
60
|
-
nativeDb.saveChanges();
|
|
61
|
-
nativeDb.deleteAllTxns(); // necessary before resetting briefcaseId
|
|
62
|
-
nativeDb.resetBriefcaseId(core_common_1.BriefcaseIdValue.Unassigned);
|
|
63
|
-
nativeDb.saveLocalValue(IModelDb_1.BriefcaseLocalValue.NoLocking, arg.noLocks ? "true" : undefined);
|
|
64
|
-
nativeDb.saveChanges();
|
|
65
|
-
}
|
|
66
|
-
finally {
|
|
67
|
-
nativeDb.closeIModel();
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
get latestChangesetIndex() { return this._latestChangesetIndex; }
|
|
71
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
72
|
-
get db() { return this._hubDb; } // eslint-disable-line @typescript-eslint/naming-convention
|
|
73
|
-
get changesetDir() { return (0, path_1.join)(this.rootDir, "changesets"); }
|
|
74
|
-
get checkpointDir() { return (0, path_1.join)(this.rootDir, "checkpoints"); }
|
|
75
|
-
get mockDbName() { return (0, path_1.join)(this.rootDir, "localHub.db"); }
|
|
76
|
-
/** Acquire the next available briefcaseId and assign it to the supplied user */
|
|
77
|
-
acquireNewBriefcaseId(user, alias) {
|
|
78
|
-
const db = this.db;
|
|
79
|
-
const newId = this._nextBriefcaseId++;
|
|
80
|
-
db.withSqliteStatement("INSERT INTO briefcases(id,user,alias) VALUES (?,?,?)", (stmt) => {
|
|
81
|
-
stmt.bindInteger(1, newId);
|
|
82
|
-
stmt.bindString(2, user);
|
|
83
|
-
stmt.bindString(3, alias !== null && alias !== void 0 ? alias : `${user} (${newId})`);
|
|
84
|
-
const rc = stmt.step();
|
|
85
|
-
if (core_bentley_1.DbResult.BE_SQLITE_DONE !== rc)
|
|
86
|
-
throw new core_common_1.IModelError(rc, "can't insert briefcaseId in mock database");
|
|
87
|
-
});
|
|
88
|
-
db.saveChanges();
|
|
89
|
-
return newId;
|
|
90
|
-
}
|
|
91
|
-
/** Release a briefcaseId */
|
|
92
|
-
releaseBriefcaseId(id) {
|
|
93
|
-
const db = this.db;
|
|
94
|
-
this.releaseAllLocks({ briefcaseId: id, changesetIndex: 0 });
|
|
95
|
-
db.withSqliteStatement("UPDATE briefcases SET assigned=0 WHERE id=?", (stmt) => {
|
|
96
|
-
stmt.bindInteger(1, id);
|
|
97
|
-
const rc = stmt.step();
|
|
98
|
-
if (core_bentley_1.DbResult.BE_SQLITE_DONE !== rc)
|
|
99
|
-
throw new core_common_1.IModelError(rc, `briefcaseId ${id} was not reserved`);
|
|
100
|
-
});
|
|
101
|
-
db.saveChanges();
|
|
102
|
-
}
|
|
103
|
-
/** Get an array of all of the currently assigned Briefcases */
|
|
104
|
-
getBriefcases(onlyAssigned = true) {
|
|
105
|
-
const briefcases = [];
|
|
106
|
-
let sql = "SELECT id,user,alias,assigned FROM briefcases";
|
|
107
|
-
if (onlyAssigned)
|
|
108
|
-
sql += " WHERE assigned=1";
|
|
109
|
-
this.db.withSqliteStatement(sql, (stmt) => {
|
|
110
|
-
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step()) {
|
|
111
|
-
briefcases.push({
|
|
112
|
-
id: stmt.getValueInteger(0),
|
|
113
|
-
user: stmt.getValueString(1),
|
|
114
|
-
alias: stmt.getValueString(2),
|
|
115
|
-
assigned: stmt.getValueInteger(3) !== 0,
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
return briefcases;
|
|
120
|
-
}
|
|
121
|
-
/** Get an array of all of the currently assigned BriefcaseIds for a user */
|
|
122
|
-
getBriefcaseIds(user) {
|
|
123
|
-
const briefcases = [];
|
|
124
|
-
this.db.withSqliteStatement("SELECT id FROM briefcases WHERE user=? AND assigned=1", (stmt) => {
|
|
125
|
-
stmt.bindString(1, user);
|
|
126
|
-
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
127
|
-
briefcases.push(stmt.getValueInteger(0));
|
|
128
|
-
});
|
|
129
|
-
return briefcases;
|
|
130
|
-
}
|
|
131
|
-
getBriefcase(id) {
|
|
132
|
-
return this.db.withSqliteStatement("SELECT user,alias,assigned FROM briefcases WHERE id=?", (stmt) => {
|
|
133
|
-
stmt.bindInteger(1, id);
|
|
134
|
-
if (core_bentley_1.DbResult.BE_SQLITE_ROW !== stmt.step())
|
|
135
|
-
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.NotFound, "no briefcase with that id");
|
|
136
|
-
return { id, user: stmt.getValueString(0), alias: stmt.getValueString(1), assigned: stmt.getValueInteger(2) !== 0 };
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
getChangesetFileName(index) {
|
|
140
|
-
return (0, path_1.join)(this.changesetDir, `changeset-${index}`);
|
|
141
|
-
}
|
|
142
|
-
/** Add a changeset to the timeline
|
|
143
|
-
* @return the changesetIndex of the added changeset
|
|
144
|
-
*/
|
|
145
|
-
addChangeset(changeset) {
|
|
146
|
-
const stats = IModelJsFs_1.IModelJsFs.lstatSync(changeset.pathname);
|
|
147
|
-
if (!stats)
|
|
148
|
-
throw new Error(`cannot read changeset file ${changeset.pathname}`);
|
|
149
|
-
const parentIndex = this.getChangesetById(changeset.parentId).index;
|
|
150
|
-
if (parentIndex !== this.latestChangesetIndex)
|
|
151
|
-
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.InvalidParent, "changeset parent is not latest changeset");
|
|
152
|
-
this.getBriefcase(changeset.briefcaseId); // throws if invalid id
|
|
153
|
-
const db = this.db;
|
|
154
|
-
changeset.index = this._latestChangesetIndex + 1;
|
|
155
|
-
db.withSqliteStatement("INSERT INTO timeline(csIndex,csId,description,size,type,pushDate,user,briefcaseId) VALUES (?,?,?,?,?,?,?,?)", (stmt) => {
|
|
156
|
-
var _a, _b, _c;
|
|
157
|
-
stmt.bindInteger(1, changeset.index);
|
|
158
|
-
stmt.bindString(2, changeset.id);
|
|
159
|
-
stmt.bindString(3, changeset.description);
|
|
160
|
-
stmt.bindInteger(4, stats.size);
|
|
161
|
-
stmt.bindInteger(5, (_a = changeset.changesType) !== null && _a !== void 0 ? _a : 0);
|
|
162
|
-
stmt.bindString(6, (_b = changeset.pushDate) !== null && _b !== void 0 ? _b : new Date().toISOString());
|
|
163
|
-
stmt.bindString(7, (_c = changeset.userCreated) !== null && _c !== void 0 ? _c : "");
|
|
164
|
-
stmt.bindInteger(8, changeset.briefcaseId);
|
|
165
|
-
const rc = stmt.step();
|
|
166
|
-
if (core_bentley_1.DbResult.BE_SQLITE_DONE !== rc)
|
|
167
|
-
throw new core_common_1.IModelError(rc, "can't insert changeset into mock db");
|
|
168
|
-
});
|
|
169
|
-
this._latestChangesetIndex = changeset.index; // only change this after insert succeeds
|
|
170
|
-
db.saveChanges();
|
|
171
|
-
IModelJsFs_1.IModelJsFs.copySync(changeset.pathname, this.getChangesetFileName(changeset.index));
|
|
172
|
-
return changeset.index;
|
|
173
|
-
}
|
|
174
|
-
getIndexFromChangeset(changeset) {
|
|
175
|
-
var _a;
|
|
176
|
-
return (_a = changeset.index) !== null && _a !== void 0 ? _a : this.getChangesetIndex(changeset.id);
|
|
177
|
-
}
|
|
178
|
-
/** Get the index of a changeset by its Id */
|
|
179
|
-
getChangesetIndex(id) {
|
|
180
|
-
if (id === "")
|
|
181
|
-
return 0;
|
|
182
|
-
return this.db.withPreparedSqliteStatement("SELECT csIndex FROM timeline WHERE csId=?", (stmt) => {
|
|
183
|
-
stmt.bindString(1, id);
|
|
184
|
-
const rc = stmt.step();
|
|
185
|
-
if (core_bentley_1.DbResult.BE_SQLITE_ROW !== rc)
|
|
186
|
-
throw new core_common_1.IModelError(rc, `changeset ${id} not found`);
|
|
187
|
-
return stmt.getValueInteger(0);
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
/** Get the properties of a changeset by its Id */
|
|
191
|
-
getChangesetById(id) {
|
|
192
|
-
return this.getChangesetByIndex(this.getChangesetIndex(id));
|
|
193
|
-
}
|
|
194
|
-
getPreviousIndex(index) {
|
|
195
|
-
return this.db.withPreparedSqliteStatement("SELECT max(csIndex) FROM timeline WHERE csIndex<?", (stmt) => {
|
|
196
|
-
stmt.bindInteger(1, index);
|
|
197
|
-
const rc = stmt.step();
|
|
198
|
-
if (core_bentley_1.DbResult.BE_SQLITE_ROW !== rc)
|
|
199
|
-
throw new core_common_1.IModelError(rc, `cannot get previous index`);
|
|
200
|
-
return stmt.getValueInteger(0);
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
getParentId(index) {
|
|
204
|
-
if (index === 0)
|
|
205
|
-
return "";
|
|
206
|
-
return this.db.withPreparedSqliteStatement("SELECT csId FROM timeline WHERE csIndex=?", (stmt) => {
|
|
207
|
-
stmt.bindInteger(1, this.getPreviousIndex(index));
|
|
208
|
-
stmt.step();
|
|
209
|
-
return stmt.getValueString(0);
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
/** Get the properties of a changeset by its index */
|
|
213
|
-
getChangesetByIndex(index) {
|
|
214
|
-
if (index <= 0)
|
|
215
|
-
return { id: "", changesType: 0, description: "version0", parentId: "", briefcaseId: 0, pushDate: "", userCreated: "", index: 0 };
|
|
216
|
-
return this.db.withPreparedSqliteStatement("SELECT description,size,type,pushDate,user,csId,briefcaseId FROM timeline WHERE csIndex=?", (stmt) => {
|
|
217
|
-
stmt.bindInteger(1, index);
|
|
218
|
-
const rc = stmt.step();
|
|
219
|
-
if (core_bentley_1.DbResult.BE_SQLITE_ROW !== rc)
|
|
220
|
-
throw new core_common_1.IModelError(rc, `changeset at index ${index} not found`);
|
|
221
|
-
return {
|
|
222
|
-
description: stmt.getValueString(0),
|
|
223
|
-
size: stmt.getValueDouble(1),
|
|
224
|
-
changesType: stmt.getValueInteger(2),
|
|
225
|
-
pushDate: stmt.getValueString(3),
|
|
226
|
-
userCreated: stmt.getValueString(4),
|
|
227
|
-
id: stmt.getValueString(5),
|
|
228
|
-
briefcaseId: stmt.getValueInteger(6),
|
|
229
|
-
index,
|
|
230
|
-
parentId: this.getParentId(index),
|
|
231
|
-
};
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
getLatestChangeset() {
|
|
235
|
-
return this.getChangesetByIndex(this.latestChangesetIndex);
|
|
236
|
-
}
|
|
237
|
-
getChangesetId(index) {
|
|
238
|
-
return this.getChangesetByIndex(index).id;
|
|
239
|
-
}
|
|
240
|
-
/** Get an array of changesets starting with first to last, by index */
|
|
241
|
-
queryChangesets(range) {
|
|
242
|
-
var _a, _b;
|
|
243
|
-
const changesets = [];
|
|
244
|
-
const first = (_a = range === null || range === void 0 ? void 0 : range.first) !== null && _a !== void 0 ? _a : 0;
|
|
245
|
-
const last = (_b = range === null || range === void 0 ? void 0 : range.end) !== null && _b !== void 0 ? _b : this.latestChangesetIndex;
|
|
246
|
-
this.db.withPreparedSqliteStatement("SELECT csIndex FROM timeline WHERE csIndex>=? AND csIndex<=? ORDER BY csIndex", (stmt) => {
|
|
247
|
-
stmt.bindInteger(1, first);
|
|
248
|
-
stmt.bindInteger(2, last);
|
|
249
|
-
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
250
|
-
changesets.push(this.getChangesetByIndex(stmt.getValueInteger(0)));
|
|
251
|
-
});
|
|
252
|
-
return changesets;
|
|
253
|
-
}
|
|
254
|
-
/** Name a version */
|
|
255
|
-
addNamedVersion(arg) {
|
|
256
|
-
const db = this.db;
|
|
257
|
-
db.withSqliteStatement("INSERT INTO versions(name,csIndex) VALUES (?,?)", (stmt) => {
|
|
258
|
-
stmt.bindString(1, arg.versionName);
|
|
259
|
-
stmt.bindInteger(2, arg.csIndex);
|
|
260
|
-
const rc = stmt.step();
|
|
261
|
-
if (core_bentley_1.DbResult.BE_SQLITE_DONE !== rc)
|
|
262
|
-
throw new core_common_1.IModelError(rc, "can't insert named version");
|
|
263
|
-
});
|
|
264
|
-
db.saveChanges();
|
|
265
|
-
}
|
|
266
|
-
/** Delete a named version */
|
|
267
|
-
deleteNamedVersion(versionName) {
|
|
268
|
-
const db = this.db;
|
|
269
|
-
db.withSqliteStatement("DELETE FROM versions WHERE name=?", (stmt) => {
|
|
270
|
-
stmt.bindString(1, versionName);
|
|
271
|
-
const rc = stmt.step();
|
|
272
|
-
if (core_bentley_1.DbResult.BE_SQLITE_DONE !== rc)
|
|
273
|
-
throw new core_common_1.IModelError(rc, "can't delete named version");
|
|
274
|
-
});
|
|
275
|
-
db.saveChanges();
|
|
276
|
-
}
|
|
277
|
-
/** find the changeset for a named version */
|
|
278
|
-
findNamedVersion(versionName) {
|
|
279
|
-
const index = this.db.withSqliteStatement("SELECT csIndex FROM versions WHERE name=?", (stmt) => {
|
|
280
|
-
stmt.bindString(1, versionName);
|
|
281
|
-
const rc = stmt.step();
|
|
282
|
-
if (core_bentley_1.DbResult.BE_SQLITE_ROW !== rc)
|
|
283
|
-
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.NotFound, `Named version ${versionName} not found`);
|
|
284
|
-
return stmt.getValueInteger(0);
|
|
285
|
-
});
|
|
286
|
-
return this.getChangesetByIndex(index);
|
|
287
|
-
}
|
|
288
|
-
checkpointNameFromIndex(csIndex) {
|
|
289
|
-
return `checkpoint-${csIndex}`;
|
|
290
|
-
}
|
|
291
|
-
/** "upload" a checkpoint */
|
|
292
|
-
uploadCheckpoint(arg) {
|
|
293
|
-
const db = this.db;
|
|
294
|
-
db.withSqliteStatement("INSERT INTO checkpoints(csIndex) VALUES (?)", (stmt) => {
|
|
295
|
-
stmt.bindInteger(1, arg.changesetIndex);
|
|
296
|
-
const res = stmt.step();
|
|
297
|
-
if (core_bentley_1.DbResult.BE_SQLITE_DONE !== res)
|
|
298
|
-
throw new core_common_1.IModelError(res, "can't insert checkpoint into mock db");
|
|
299
|
-
});
|
|
300
|
-
db.saveChanges();
|
|
301
|
-
const outName = (0, path_1.join)(this.checkpointDir, this.checkpointNameFromIndex(arg.changesetIndex));
|
|
302
|
-
IModelJsFs_1.IModelJsFs.copySync(arg.localFile, outName);
|
|
303
|
-
return outName;
|
|
304
|
-
}
|
|
305
|
-
/** Get an array of the indexes for a range of checkpoints */
|
|
306
|
-
getCheckpoints(range) {
|
|
307
|
-
var _a, _b;
|
|
308
|
-
const first = (_a = range === null || range === void 0 ? void 0 : range.first) !== null && _a !== void 0 ? _a : 0;
|
|
309
|
-
const last = (_b = range === null || range === void 0 ? void 0 : range.end) !== null && _b !== void 0 ? _b : this.latestChangesetIndex;
|
|
310
|
-
const checkpoints = [];
|
|
311
|
-
this.db.withSqliteStatement("SELECT csIndex FROM checkpoints WHERE csIndex>=? AND csIndex<=? ORDER BY csIndex", (stmt) => {
|
|
312
|
-
stmt.bindInteger(1, first);
|
|
313
|
-
stmt.bindInteger(2, last);
|
|
314
|
-
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
315
|
-
checkpoints.push(stmt.getValueInteger(0));
|
|
316
|
-
});
|
|
317
|
-
return checkpoints;
|
|
318
|
-
}
|
|
319
|
-
/** Find the checkpoint that is no newer than a changesetIndex */
|
|
320
|
-
queryPreviousCheckpoint(changesetIndex) {
|
|
321
|
-
if (changesetIndex <= 0)
|
|
322
|
-
return 0;
|
|
323
|
-
return this.db.withSqliteStatement("SELECT max(csIndex) FROM checkpoints WHERE csIndex <= ? ", (stmt) => {
|
|
324
|
-
stmt.bindInteger(1, changesetIndex);
|
|
325
|
-
const res = stmt.step();
|
|
326
|
-
if (core_bentley_1.DbResult.BE_SQLITE_ROW !== res)
|
|
327
|
-
throw new core_common_1.IModelError(res, "can't get previous checkpoint");
|
|
328
|
-
return stmt.getValueInteger(0);
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
/** "download" a checkpoint */
|
|
332
|
-
downloadCheckpoint(arg) {
|
|
333
|
-
const index = this.getIndexFromChangeset(arg.changeset);
|
|
334
|
-
const prev = this.queryPreviousCheckpoint(index);
|
|
335
|
-
IModelJsFs_1.IModelJsFs.copySync((0, path_1.join)(this.checkpointDir, this.checkpointNameFromIndex(prev)), arg.targetFile);
|
|
336
|
-
const changeset = this.getChangesetByIndex(index);
|
|
337
|
-
return { index, id: changeset.id };
|
|
338
|
-
}
|
|
339
|
-
copyChangeset(arg) {
|
|
340
|
-
IModelJsFs_1.IModelJsFs.copySync(this.getChangesetFileName(arg.index), arg.pathname);
|
|
341
|
-
return arg;
|
|
342
|
-
}
|
|
343
|
-
/** "download" a changeset */
|
|
344
|
-
downloadChangeset(arg) {
|
|
345
|
-
const cs = this.getChangesetByIndex(arg.index);
|
|
346
|
-
const csProps = { ...cs, pathname: (0, path_1.join)(arg.targetDir, cs.id), index: arg.index };
|
|
347
|
-
return this.copyChangeset(csProps);
|
|
348
|
-
}
|
|
349
|
-
/** "download" all the changesets in a given range */
|
|
350
|
-
downloadChangesets(arg) {
|
|
351
|
-
const cSets = this.queryChangesets(arg.range);
|
|
352
|
-
for (const cs of cSets) {
|
|
353
|
-
cs.pathname = (0, path_1.join)(arg.targetDir, cs.id);
|
|
354
|
-
this.copyChangeset(cs);
|
|
355
|
-
}
|
|
356
|
-
return cSets;
|
|
357
|
-
}
|
|
358
|
-
querySharedLockHolders(elementId) {
|
|
359
|
-
return this.db.withPreparedSqliteStatement("SELECT briefcaseId FROM sharedLocks WHERE lockId=?", (stmt) => {
|
|
360
|
-
stmt.bindId(1, elementId);
|
|
361
|
-
const briefcases = new Set();
|
|
362
|
-
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
363
|
-
briefcases.add(stmt.getValueInteger(0));
|
|
364
|
-
return briefcases;
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
queryAllLocks(briefcaseId) {
|
|
368
|
-
this.getBriefcase(briefcaseId); // throws if briefcaseId invalid.
|
|
369
|
-
const locks = [];
|
|
370
|
-
this.db.withPreparedSqliteStatement("SELECT id FROM locks WHERE briefcaseId=?", (stmt) => {
|
|
371
|
-
stmt.bindInteger(1, briefcaseId);
|
|
372
|
-
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
373
|
-
locks.push({ id: stmt.getValueId(0), state: BackendHubAccess_1.LockState.Exclusive });
|
|
374
|
-
});
|
|
375
|
-
this.db.withPreparedSqliteStatement("SELECT lockId FROM sharedLocks WHERE briefcaseId=?", (stmt) => {
|
|
376
|
-
stmt.bindInteger(1, briefcaseId);
|
|
377
|
-
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
378
|
-
locks.push({ id: stmt.getValueId(0), state: BackendHubAccess_1.LockState.Shared });
|
|
379
|
-
});
|
|
380
|
-
return locks;
|
|
381
|
-
}
|
|
382
|
-
queryLockStatus(elementId) {
|
|
383
|
-
return this.db.withPreparedSqliteStatement("SELECT lastCSetIndex,level,briefcaseId FROM locks WHERE id=?", (stmt) => {
|
|
384
|
-
stmt.bindId(1, elementId);
|
|
385
|
-
const rc = stmt.step();
|
|
386
|
-
if (core_bentley_1.DbResult.BE_SQLITE_ROW !== rc)
|
|
387
|
-
return { state: BackendHubAccess_1.LockState.None };
|
|
388
|
-
const lastCsVal = stmt.getValue(0);
|
|
389
|
-
const lock = {
|
|
390
|
-
lastCsIndex: lastCsVal.isNull ? undefined : lastCsVal.getInteger(),
|
|
391
|
-
state: stmt.getValueInteger(1),
|
|
392
|
-
};
|
|
393
|
-
switch (lock.state) {
|
|
394
|
-
case BackendHubAccess_1.LockState.None:
|
|
395
|
-
return lock;
|
|
396
|
-
case BackendHubAccess_1.LockState.Exclusive:
|
|
397
|
-
return { ...lock, briefcaseId: stmt.getValueInteger(2) };
|
|
398
|
-
case BackendHubAccess_1.LockState.Shared:
|
|
399
|
-
return { ...lock, sharedBy: this.querySharedLockHolders(elementId) };
|
|
400
|
-
default:
|
|
401
|
-
throw new Error("illegal lock state");
|
|
402
|
-
}
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
reserveLock(currStatus, props, briefcase) {
|
|
406
|
-
if (props.state === BackendHubAccess_1.LockState.Exclusive && currStatus.lastCsIndex && (currStatus.lastCsIndex > this.getIndexFromChangeset(briefcase.changeset)))
|
|
407
|
-
throw new core_common_1.IModelError(core_bentley_1.IModelHubStatus.PullIsRequired, "pull is required to obtain lock");
|
|
408
|
-
const wantShared = props.state === BackendHubAccess_1.LockState.Shared;
|
|
409
|
-
if (wantShared && (currStatus.state === BackendHubAccess_1.LockState.Exclusive))
|
|
410
|
-
throw new Error("cannot acquire shared lock because an exclusive lock is already held");
|
|
411
|
-
this.db.withPreparedSqliteStatement("INSERT INTO locks(id,level,briefcaseId) VALUES(?,?,?) ON CONFLICT(id) DO UPDATE SET briefcaseId=excluded.briefcaseId,level=excluded.level", (stmt) => {
|
|
412
|
-
stmt.bindId(1, props.id);
|
|
413
|
-
stmt.bindInteger(2, props.state);
|
|
414
|
-
stmt.bindValue(3, wantShared ? undefined : briefcase.briefcaseId);
|
|
415
|
-
const rc = stmt.step();
|
|
416
|
-
if (rc !== core_bentley_1.DbResult.BE_SQLITE_DONE)
|
|
417
|
-
throw new core_common_1.IModelError(rc, "cannot insert lock");
|
|
418
|
-
});
|
|
419
|
-
if (wantShared) {
|
|
420
|
-
this.db.withPreparedSqliteStatement("INSERT INTO sharedLocks(lockId,briefcaseId) VALUES(?,?)", (stmt) => {
|
|
421
|
-
stmt.bindId(1, props.id);
|
|
422
|
-
stmt.bindInteger(2, briefcase.briefcaseId);
|
|
423
|
-
const rc = stmt.step();
|
|
424
|
-
if (rc !== core_bentley_1.DbResult.BE_SQLITE_DONE)
|
|
425
|
-
throw new core_common_1.IModelError(rc, "cannot insert shared lock");
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
clearLock(id) {
|
|
430
|
-
this.db.withPreparedSqliteStatement("UPDATE locks SET level=0,briefcaseId=NULL WHERE id=?", (stmt) => {
|
|
431
|
-
stmt.bindId(1, id);
|
|
432
|
-
const rc = stmt.step();
|
|
433
|
-
if (rc !== core_bentley_1.DbResult.BE_SQLITE_DONE)
|
|
434
|
-
throw new core_common_1.IModelError(rc, "can't release lock");
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
updateLockChangeset(id, index) {
|
|
438
|
-
if (index <= 0)
|
|
439
|
-
return;
|
|
440
|
-
this.db.withPreparedSqliteStatement("UPDATE locks SET lastCSetIndex=? WHERE id=?", (stmt) => {
|
|
441
|
-
stmt.bindInteger(1, index);
|
|
442
|
-
stmt.bindId(2, id);
|
|
443
|
-
const rc = stmt.step();
|
|
444
|
-
if (rc !== core_bentley_1.DbResult.BE_SQLITE_DONE)
|
|
445
|
-
throw new core_common_1.IModelError(rc, "can't update lock changeSetId");
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
requestLock(props, briefcase) {
|
|
449
|
-
if (props.state === BackendHubAccess_1.LockState.None)
|
|
450
|
-
throw new Error("cannot request lock for LockState.None");
|
|
451
|
-
this.getBriefcase(briefcase.briefcaseId); // throws if briefcaseId invalid.
|
|
452
|
-
const lockStatus = this.queryLockStatus(props.id);
|
|
453
|
-
switch (lockStatus.state) {
|
|
454
|
-
case BackendHubAccess_1.LockState.None:
|
|
455
|
-
return this.reserveLock(lockStatus, props, briefcase);
|
|
456
|
-
case BackendHubAccess_1.LockState.Shared:
|
|
457
|
-
if (props.state === BackendHubAccess_1.LockState.Shared) {
|
|
458
|
-
if (!lockStatus.sharedBy.has(briefcase.briefcaseId))
|
|
459
|
-
this.reserveLock(lockStatus, props, briefcase);
|
|
460
|
-
}
|
|
461
|
-
else {
|
|
462
|
-
// if requester is the only one holding a shared lock, "upgrade" the lock from shared to exclusive
|
|
463
|
-
if (lockStatus.sharedBy.size > 1 || !lockStatus.sharedBy.has(briefcase.briefcaseId)) {
|
|
464
|
-
const id = lockStatus.sharedBy.values().next().value;
|
|
465
|
-
throw new BackendHubAccess_1.LockConflict(id, this.getBriefcase(id).alias, "shared lock is held");
|
|
466
|
-
}
|
|
467
|
-
this.removeSharedLock(props.id, briefcase.briefcaseId);
|
|
468
|
-
this.reserveLock(this.queryLockStatus(props.id), props, briefcase);
|
|
469
|
-
}
|
|
470
|
-
return;
|
|
471
|
-
case BackendHubAccess_1.LockState.Exclusive:
|
|
472
|
-
if (lockStatus.briefcaseId !== briefcase.briefcaseId)
|
|
473
|
-
throw new BackendHubAccess_1.LockConflict(lockStatus.briefcaseId, this.getBriefcase(lockStatus.briefcaseId).alias, "exclusive lock is already held");
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
removeSharedLock(lockId, briefcaseId) {
|
|
477
|
-
this.db.withPreparedSqliteStatement("DELETE FROM sharedLocks WHERE lockId=? AND briefcaseId=?", (stmt) => {
|
|
478
|
-
stmt.bindId(1, lockId);
|
|
479
|
-
stmt.bindInteger(2, briefcaseId);
|
|
480
|
-
const rc = stmt.step();
|
|
481
|
-
if (rc !== core_bentley_1.DbResult.BE_SQLITE_DONE)
|
|
482
|
-
throw new core_common_1.IModelError(rc, "can't remove shared lock");
|
|
483
|
-
});
|
|
484
|
-
}
|
|
485
|
-
releaseLock(props, arg) {
|
|
486
|
-
const lockId = props.id;
|
|
487
|
-
const lockStatus = this.queryLockStatus(lockId);
|
|
488
|
-
switch (lockStatus.state) {
|
|
489
|
-
case BackendHubAccess_1.LockState.None:
|
|
490
|
-
throw new core_common_1.IModelError(core_bentley_1.IModelHubStatus.LockDoesNotExist, "lock not held");
|
|
491
|
-
case BackendHubAccess_1.LockState.Exclusive:
|
|
492
|
-
if (lockStatus.briefcaseId !== arg.briefcaseId)
|
|
493
|
-
throw new core_common_1.IModelError(core_bentley_1.IModelHubStatus.LockOwnedByAnotherBriefcase, "lock not held by this briefcase");
|
|
494
|
-
this.updateLockChangeset(lockId, arg.changesetIndex);
|
|
495
|
-
this.clearLock(lockId);
|
|
496
|
-
break;
|
|
497
|
-
case BackendHubAccess_1.LockState.Shared:
|
|
498
|
-
if (!lockStatus.sharedBy.has(arg.briefcaseId))
|
|
499
|
-
throw new core_common_1.IModelError(core_bentley_1.IModelHubStatus.LockDoesNotExist, "shared lock not held by this briefcase");
|
|
500
|
-
this.removeSharedLock(lockId, arg.briefcaseId);
|
|
501
|
-
if (lockStatus.sharedBy.size === 1)
|
|
502
|
-
this.clearLock(lockId);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
/** Acquire a set of locks. If any lock cannot be acquired, no locks are acquired */
|
|
506
|
-
acquireLocks(locks, briefcase) {
|
|
507
|
-
try {
|
|
508
|
-
for (const lock of locks)
|
|
509
|
-
this.requestLock({ id: lock[0], state: lock[1] }, briefcase);
|
|
510
|
-
this.db.saveChanges(); // only after all locks have been acquired
|
|
511
|
-
}
|
|
512
|
-
catch (err) {
|
|
513
|
-
this.db.abandonChanges(); // abandon all locks that may have been acquired
|
|
514
|
-
throw err;
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
acquireLock(props, briefcase) {
|
|
518
|
-
const locks = new Map();
|
|
519
|
-
locks.set(props.id, props.state);
|
|
520
|
-
this.acquireLocks(locks, briefcase);
|
|
521
|
-
}
|
|
522
|
-
releaseLocks(locks, arg) {
|
|
523
|
-
for (const props of locks)
|
|
524
|
-
this.releaseLock(props, arg);
|
|
525
|
-
this.db.saveChanges();
|
|
526
|
-
}
|
|
527
|
-
releaseAllLocks(arg) {
|
|
528
|
-
const locks = this.queryAllLocks(arg.briefcaseId);
|
|
529
|
-
this.releaseLocks(locks, arg);
|
|
530
|
-
}
|
|
531
|
-
countTable(tableName) {
|
|
532
|
-
return this.db.withSqliteStatement(`SELECT count(*) from ${tableName}`, (stmt) => {
|
|
533
|
-
stmt.step();
|
|
534
|
-
return stmt.getValueInteger(0);
|
|
535
|
-
});
|
|
536
|
-
}
|
|
537
|
-
// for debugging
|
|
538
|
-
countSharedLocks() { return this.countTable("sharedLocks"); }
|
|
539
|
-
// for debugging
|
|
540
|
-
countLocks() { return this.countTable("locks"); }
|
|
541
|
-
// for debugging
|
|
542
|
-
queryAllSharedLocks() {
|
|
543
|
-
const locks = [];
|
|
544
|
-
this.db.withPreparedSqliteStatement("SELECT lockId,briefcaseId FROM sharedLocks", (stmt) => {
|
|
545
|
-
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
546
|
-
locks.push({ id: stmt.getValueId(0), briefcaseId: stmt.getValueInteger(1) });
|
|
547
|
-
});
|
|
548
|
-
return locks;
|
|
549
|
-
}
|
|
550
|
-
// for debugging
|
|
551
|
-
queryLocks() {
|
|
552
|
-
const locks = [];
|
|
553
|
-
this.db.withPreparedSqliteStatement("SELECT id,level,lastCSetIndex,briefcaseId FROM locks", (stmt) => {
|
|
554
|
-
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
555
|
-
locks.push({
|
|
556
|
-
id: stmt.getValueId(0),
|
|
557
|
-
level: stmt.getValueInteger(1),
|
|
558
|
-
lastCsIndex: stmt.getValue(2).isNull ? undefined : stmt.getValueInteger(2),
|
|
559
|
-
briefcaseId: stmt.getValue(3).isNull ? undefined : stmt.getValueInteger(3),
|
|
560
|
-
});
|
|
561
|
-
});
|
|
562
|
-
return locks;
|
|
563
|
-
}
|
|
564
|
-
removeDir(dirName) {
|
|
565
|
-
if (IModelJsFs_1.IModelJsFs.existsSync(dirName)) {
|
|
566
|
-
IModelJsFs_1.IModelJsFs.purgeDirSync(dirName);
|
|
567
|
-
IModelJsFs_1.IModelJsFs.rmdirSync(dirName);
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
cleanup() {
|
|
571
|
-
if (this._hubDb) {
|
|
572
|
-
this._hubDb.closeDb();
|
|
573
|
-
this._hubDb = undefined;
|
|
574
|
-
}
|
|
575
|
-
try {
|
|
576
|
-
this.removeDir(BriefcaseManager_1.BriefcaseManager.getIModelPath(this.iModelId));
|
|
577
|
-
this.removeDir(this.rootDir);
|
|
578
|
-
}
|
|
579
|
-
catch (err) {
|
|
580
|
-
// eslint-disable-next-line no-console
|
|
581
|
-
console.log(`ERROR: test left an iModel open for [${this.iModelName}]. LocalMock cannot clean up - make sure you call imodel.close() in your test`);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
exports.LocalHub = LocalHub;
|
|
1
|
+
"use strict";
|
|
2
|
+
/*---------------------------------------------------------------------------------------------
|
|
3
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
4
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
|
+
*--------------------------------------------------------------------------------------------*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.LocalHub = void 0;
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const core_bentley_1 = require("@itwin/core-bentley");
|
|
10
|
+
const core_common_1 = require("@itwin/core-common");
|
|
11
|
+
const BackendHubAccess_1 = require("./BackendHubAccess");
|
|
12
|
+
const BriefcaseManager_1 = require("./BriefcaseManager");
|
|
13
|
+
const IModelDb_1 = require("./IModelDb");
|
|
14
|
+
const IModelJsFs_1 = require("./IModelJsFs");
|
|
15
|
+
const SQLiteDb_1 = require("./SQLiteDb");
|
|
16
|
+
/**
|
|
17
|
+
* A "local" mock for IModelHub to provide access to a single iModel. Used by HubMock.
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
class LocalHub {
|
|
21
|
+
constructor(rootDir, arg) {
|
|
22
|
+
var _a, _b;
|
|
23
|
+
this.rootDir = rootDir;
|
|
24
|
+
this._nextBriefcaseId = core_common_1.BriefcaseIdValue.FirstValid;
|
|
25
|
+
this._latestChangesetIndex = 0;
|
|
26
|
+
this.iTwinId = arg.iTwinId;
|
|
27
|
+
this.iModelId = arg.iModelId;
|
|
28
|
+
this.iModelName = arg.iModelName;
|
|
29
|
+
this.description = arg.description;
|
|
30
|
+
this.cleanup();
|
|
31
|
+
IModelJsFs_1.IModelJsFs.recursiveMkDirSync(this.rootDir);
|
|
32
|
+
IModelJsFs_1.IModelJsFs.mkdirSync(this.changesetDir);
|
|
33
|
+
IModelJsFs_1.IModelJsFs.mkdirSync(this.checkpointDir);
|
|
34
|
+
const db = this._hubDb = new SQLiteDb_1.SQLiteDb();
|
|
35
|
+
db.createDb(this.mockDbName);
|
|
36
|
+
db.executeSQL("CREATE TABLE briefcases(id INTEGER PRIMARY KEY NOT NULL,user TEXT NOT NULL,alias TEXT NOT NULL,assigned INTEGER DEFAULT 1)");
|
|
37
|
+
db.executeSQL("CREATE TABLE timeline(csIndex INTEGER PRIMARY KEY NOT NULL,csId TEXT NOT NULL UNIQUE,description TEXT,user TEXT,size BIGINT,type INTEGER,pushDate TEXT,briefcaseId INTEGER,\
|
|
38
|
+
FOREIGN KEY(briefcaseId) REFERENCES briefcases(id))");
|
|
39
|
+
db.executeSQL("CREATE TABLE checkpoints(csIndex INTEGER PRIMARY KEY NOT NULL)");
|
|
40
|
+
db.executeSQL("CREATE TABLE versions(name TEXT PRIMARY KEY NOT NULL,csIndex TEXT,FOREIGN KEY(csIndex) REFERENCES timeline(csIndex))");
|
|
41
|
+
db.executeSQL("CREATE TABLE locks(id INTEGER PRIMARY KEY NOT NULL,level INTEGER NOT NULL,lastCSetIndex INTEGER,briefcaseId INTEGER)");
|
|
42
|
+
db.executeSQL("CREATE TABLE sharedLocks(lockId INTEGER NOT NULL,briefcaseId INTEGER NOT NULL,PRIMARY KEY(lockId,briefcaseId))");
|
|
43
|
+
db.executeSQL("CREATE INDEX LockIdx ON locks(briefcaseId)");
|
|
44
|
+
db.executeSQL("CREATE INDEX SharedLockIdx ON sharedLocks(briefcaseId)");
|
|
45
|
+
db.saveChanges();
|
|
46
|
+
const version0Root = `${rootDir}_version0`;
|
|
47
|
+
const version0 = (_a = arg.version0) !== null && _a !== void 0 ? _a : (0, path_1.join)(version0Root, "version0.bim");
|
|
48
|
+
if (!arg.version0) { // if they didn't supply a version0 file, create a blank one.
|
|
49
|
+
IModelJsFs_1.IModelJsFs.recursiveMkDirSync(version0Root);
|
|
50
|
+
IModelJsFs_1.IModelJsFs.removeSync(version0);
|
|
51
|
+
IModelDb_1.SnapshotDb.createEmpty(version0, { rootSubject: { name: (_b = arg.description) !== null && _b !== void 0 ? _b : arg.iModelName } }).close();
|
|
52
|
+
}
|
|
53
|
+
const path = this.uploadCheckpoint({ changesetIndex: 0, localFile: version0 });
|
|
54
|
+
if (!arg.version0)
|
|
55
|
+
IModelJsFs_1.IModelJsFs.removeSync(version0);
|
|
56
|
+
const nativeDb = IModelDb_1.IModelDb.openDgnDb({ path }, core_bentley_1.OpenMode.ReadWrite);
|
|
57
|
+
try {
|
|
58
|
+
nativeDb.setITwinId(this.iTwinId);
|
|
59
|
+
nativeDb.setIModelId(this.iModelId);
|
|
60
|
+
nativeDb.saveChanges();
|
|
61
|
+
nativeDb.deleteAllTxns(); // necessary before resetting briefcaseId
|
|
62
|
+
nativeDb.resetBriefcaseId(core_common_1.BriefcaseIdValue.Unassigned);
|
|
63
|
+
nativeDb.saveLocalValue(IModelDb_1.BriefcaseLocalValue.NoLocking, arg.noLocks ? "true" : undefined);
|
|
64
|
+
nativeDb.saveChanges();
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
nativeDb.closeIModel();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
get latestChangesetIndex() { return this._latestChangesetIndex; }
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
72
|
+
get db() { return this._hubDb; } // eslint-disable-line @typescript-eslint/naming-convention
|
|
73
|
+
get changesetDir() { return (0, path_1.join)(this.rootDir, "changesets"); }
|
|
74
|
+
get checkpointDir() { return (0, path_1.join)(this.rootDir, "checkpoints"); }
|
|
75
|
+
get mockDbName() { return (0, path_1.join)(this.rootDir, "localHub.db"); }
|
|
76
|
+
/** Acquire the next available briefcaseId and assign it to the supplied user */
|
|
77
|
+
acquireNewBriefcaseId(user, alias) {
|
|
78
|
+
const db = this.db;
|
|
79
|
+
const newId = this._nextBriefcaseId++;
|
|
80
|
+
db.withSqliteStatement("INSERT INTO briefcases(id,user,alias) VALUES (?,?,?)", (stmt) => {
|
|
81
|
+
stmt.bindInteger(1, newId);
|
|
82
|
+
stmt.bindString(2, user);
|
|
83
|
+
stmt.bindString(3, alias !== null && alias !== void 0 ? alias : `${user} (${newId})`);
|
|
84
|
+
const rc = stmt.step();
|
|
85
|
+
if (core_bentley_1.DbResult.BE_SQLITE_DONE !== rc)
|
|
86
|
+
throw new core_common_1.IModelError(rc, "can't insert briefcaseId in mock database");
|
|
87
|
+
});
|
|
88
|
+
db.saveChanges();
|
|
89
|
+
return newId;
|
|
90
|
+
}
|
|
91
|
+
/** Release a briefcaseId */
|
|
92
|
+
releaseBriefcaseId(id) {
|
|
93
|
+
const db = this.db;
|
|
94
|
+
this.releaseAllLocks({ briefcaseId: id, changesetIndex: 0 });
|
|
95
|
+
db.withSqliteStatement("UPDATE briefcases SET assigned=0 WHERE id=?", (stmt) => {
|
|
96
|
+
stmt.bindInteger(1, id);
|
|
97
|
+
const rc = stmt.step();
|
|
98
|
+
if (core_bentley_1.DbResult.BE_SQLITE_DONE !== rc)
|
|
99
|
+
throw new core_common_1.IModelError(rc, `briefcaseId ${id} was not reserved`);
|
|
100
|
+
});
|
|
101
|
+
db.saveChanges();
|
|
102
|
+
}
|
|
103
|
+
/** Get an array of all of the currently assigned Briefcases */
|
|
104
|
+
getBriefcases(onlyAssigned = true) {
|
|
105
|
+
const briefcases = [];
|
|
106
|
+
let sql = "SELECT id,user,alias,assigned FROM briefcases";
|
|
107
|
+
if (onlyAssigned)
|
|
108
|
+
sql += " WHERE assigned=1";
|
|
109
|
+
this.db.withSqliteStatement(sql, (stmt) => {
|
|
110
|
+
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step()) {
|
|
111
|
+
briefcases.push({
|
|
112
|
+
id: stmt.getValueInteger(0),
|
|
113
|
+
user: stmt.getValueString(1),
|
|
114
|
+
alias: stmt.getValueString(2),
|
|
115
|
+
assigned: stmt.getValueInteger(3) !== 0,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
return briefcases;
|
|
120
|
+
}
|
|
121
|
+
/** Get an array of all of the currently assigned BriefcaseIds for a user */
|
|
122
|
+
getBriefcaseIds(user) {
|
|
123
|
+
const briefcases = [];
|
|
124
|
+
this.db.withSqliteStatement("SELECT id FROM briefcases WHERE user=? AND assigned=1", (stmt) => {
|
|
125
|
+
stmt.bindString(1, user);
|
|
126
|
+
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
127
|
+
briefcases.push(stmt.getValueInteger(0));
|
|
128
|
+
});
|
|
129
|
+
return briefcases;
|
|
130
|
+
}
|
|
131
|
+
getBriefcase(id) {
|
|
132
|
+
return this.db.withSqliteStatement("SELECT user,alias,assigned FROM briefcases WHERE id=?", (stmt) => {
|
|
133
|
+
stmt.bindInteger(1, id);
|
|
134
|
+
if (core_bentley_1.DbResult.BE_SQLITE_ROW !== stmt.step())
|
|
135
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.NotFound, "no briefcase with that id");
|
|
136
|
+
return { id, user: stmt.getValueString(0), alias: stmt.getValueString(1), assigned: stmt.getValueInteger(2) !== 0 };
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
getChangesetFileName(index) {
|
|
140
|
+
return (0, path_1.join)(this.changesetDir, `changeset-${index}`);
|
|
141
|
+
}
|
|
142
|
+
/** Add a changeset to the timeline
|
|
143
|
+
* @return the changesetIndex of the added changeset
|
|
144
|
+
*/
|
|
145
|
+
addChangeset(changeset) {
|
|
146
|
+
const stats = IModelJsFs_1.IModelJsFs.lstatSync(changeset.pathname);
|
|
147
|
+
if (!stats)
|
|
148
|
+
throw new Error(`cannot read changeset file ${changeset.pathname}`);
|
|
149
|
+
const parentIndex = this.getChangesetById(changeset.parentId).index;
|
|
150
|
+
if (parentIndex !== this.latestChangesetIndex)
|
|
151
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.InvalidParent, "changeset parent is not latest changeset");
|
|
152
|
+
this.getBriefcase(changeset.briefcaseId); // throws if invalid id
|
|
153
|
+
const db = this.db;
|
|
154
|
+
changeset.index = this._latestChangesetIndex + 1;
|
|
155
|
+
db.withSqliteStatement("INSERT INTO timeline(csIndex,csId,description,size,type,pushDate,user,briefcaseId) VALUES (?,?,?,?,?,?,?,?)", (stmt) => {
|
|
156
|
+
var _a, _b, _c;
|
|
157
|
+
stmt.bindInteger(1, changeset.index);
|
|
158
|
+
stmt.bindString(2, changeset.id);
|
|
159
|
+
stmt.bindString(3, changeset.description);
|
|
160
|
+
stmt.bindInteger(4, stats.size);
|
|
161
|
+
stmt.bindInteger(5, (_a = changeset.changesType) !== null && _a !== void 0 ? _a : 0);
|
|
162
|
+
stmt.bindString(6, (_b = changeset.pushDate) !== null && _b !== void 0 ? _b : new Date().toISOString());
|
|
163
|
+
stmt.bindString(7, (_c = changeset.userCreated) !== null && _c !== void 0 ? _c : "");
|
|
164
|
+
stmt.bindInteger(8, changeset.briefcaseId);
|
|
165
|
+
const rc = stmt.step();
|
|
166
|
+
if (core_bentley_1.DbResult.BE_SQLITE_DONE !== rc)
|
|
167
|
+
throw new core_common_1.IModelError(rc, "can't insert changeset into mock db");
|
|
168
|
+
});
|
|
169
|
+
this._latestChangesetIndex = changeset.index; // only change this after insert succeeds
|
|
170
|
+
db.saveChanges();
|
|
171
|
+
IModelJsFs_1.IModelJsFs.copySync(changeset.pathname, this.getChangesetFileName(changeset.index));
|
|
172
|
+
return changeset.index;
|
|
173
|
+
}
|
|
174
|
+
getIndexFromChangeset(changeset) {
|
|
175
|
+
var _a;
|
|
176
|
+
return (_a = changeset.index) !== null && _a !== void 0 ? _a : this.getChangesetIndex(changeset.id);
|
|
177
|
+
}
|
|
178
|
+
/** Get the index of a changeset by its Id */
|
|
179
|
+
getChangesetIndex(id) {
|
|
180
|
+
if (id === "")
|
|
181
|
+
return 0;
|
|
182
|
+
return this.db.withPreparedSqliteStatement("SELECT csIndex FROM timeline WHERE csId=?", (stmt) => {
|
|
183
|
+
stmt.bindString(1, id);
|
|
184
|
+
const rc = stmt.step();
|
|
185
|
+
if (core_bentley_1.DbResult.BE_SQLITE_ROW !== rc)
|
|
186
|
+
throw new core_common_1.IModelError(rc, `changeset ${id} not found`);
|
|
187
|
+
return stmt.getValueInteger(0);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/** Get the properties of a changeset by its Id */
|
|
191
|
+
getChangesetById(id) {
|
|
192
|
+
return this.getChangesetByIndex(this.getChangesetIndex(id));
|
|
193
|
+
}
|
|
194
|
+
getPreviousIndex(index) {
|
|
195
|
+
return this.db.withPreparedSqliteStatement("SELECT max(csIndex) FROM timeline WHERE csIndex<?", (stmt) => {
|
|
196
|
+
stmt.bindInteger(1, index);
|
|
197
|
+
const rc = stmt.step();
|
|
198
|
+
if (core_bentley_1.DbResult.BE_SQLITE_ROW !== rc)
|
|
199
|
+
throw new core_common_1.IModelError(rc, `cannot get previous index`);
|
|
200
|
+
return stmt.getValueInteger(0);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
getParentId(index) {
|
|
204
|
+
if (index === 0)
|
|
205
|
+
return "";
|
|
206
|
+
return this.db.withPreparedSqliteStatement("SELECT csId FROM timeline WHERE csIndex=?", (stmt) => {
|
|
207
|
+
stmt.bindInteger(1, this.getPreviousIndex(index));
|
|
208
|
+
stmt.step();
|
|
209
|
+
return stmt.getValueString(0);
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
/** Get the properties of a changeset by its index */
|
|
213
|
+
getChangesetByIndex(index) {
|
|
214
|
+
if (index <= 0)
|
|
215
|
+
return { id: "", changesType: 0, description: "version0", parentId: "", briefcaseId: 0, pushDate: "", userCreated: "", index: 0 };
|
|
216
|
+
return this.db.withPreparedSqliteStatement("SELECT description,size,type,pushDate,user,csId,briefcaseId FROM timeline WHERE csIndex=?", (stmt) => {
|
|
217
|
+
stmt.bindInteger(1, index);
|
|
218
|
+
const rc = stmt.step();
|
|
219
|
+
if (core_bentley_1.DbResult.BE_SQLITE_ROW !== rc)
|
|
220
|
+
throw new core_common_1.IModelError(rc, `changeset at index ${index} not found`);
|
|
221
|
+
return {
|
|
222
|
+
description: stmt.getValueString(0),
|
|
223
|
+
size: stmt.getValueDouble(1),
|
|
224
|
+
changesType: stmt.getValueInteger(2),
|
|
225
|
+
pushDate: stmt.getValueString(3),
|
|
226
|
+
userCreated: stmt.getValueString(4),
|
|
227
|
+
id: stmt.getValueString(5),
|
|
228
|
+
briefcaseId: stmt.getValueInteger(6),
|
|
229
|
+
index,
|
|
230
|
+
parentId: this.getParentId(index),
|
|
231
|
+
};
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
getLatestChangeset() {
|
|
235
|
+
return this.getChangesetByIndex(this.latestChangesetIndex);
|
|
236
|
+
}
|
|
237
|
+
getChangesetId(index) {
|
|
238
|
+
return this.getChangesetByIndex(index).id;
|
|
239
|
+
}
|
|
240
|
+
/** Get an array of changesets starting with first to last, by index */
|
|
241
|
+
queryChangesets(range) {
|
|
242
|
+
var _a, _b;
|
|
243
|
+
const changesets = [];
|
|
244
|
+
const first = (_a = range === null || range === void 0 ? void 0 : range.first) !== null && _a !== void 0 ? _a : 0;
|
|
245
|
+
const last = (_b = range === null || range === void 0 ? void 0 : range.end) !== null && _b !== void 0 ? _b : this.latestChangesetIndex;
|
|
246
|
+
this.db.withPreparedSqliteStatement("SELECT csIndex FROM timeline WHERE csIndex>=? AND csIndex<=? ORDER BY csIndex", (stmt) => {
|
|
247
|
+
stmt.bindInteger(1, first);
|
|
248
|
+
stmt.bindInteger(2, last);
|
|
249
|
+
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
250
|
+
changesets.push(this.getChangesetByIndex(stmt.getValueInteger(0)));
|
|
251
|
+
});
|
|
252
|
+
return changesets;
|
|
253
|
+
}
|
|
254
|
+
/** Name a version */
|
|
255
|
+
addNamedVersion(arg) {
|
|
256
|
+
const db = this.db;
|
|
257
|
+
db.withSqliteStatement("INSERT INTO versions(name,csIndex) VALUES (?,?)", (stmt) => {
|
|
258
|
+
stmt.bindString(1, arg.versionName);
|
|
259
|
+
stmt.bindInteger(2, arg.csIndex);
|
|
260
|
+
const rc = stmt.step();
|
|
261
|
+
if (core_bentley_1.DbResult.BE_SQLITE_DONE !== rc)
|
|
262
|
+
throw new core_common_1.IModelError(rc, "can't insert named version");
|
|
263
|
+
});
|
|
264
|
+
db.saveChanges();
|
|
265
|
+
}
|
|
266
|
+
/** Delete a named version */
|
|
267
|
+
deleteNamedVersion(versionName) {
|
|
268
|
+
const db = this.db;
|
|
269
|
+
db.withSqliteStatement("DELETE FROM versions WHERE name=?", (stmt) => {
|
|
270
|
+
stmt.bindString(1, versionName);
|
|
271
|
+
const rc = stmt.step();
|
|
272
|
+
if (core_bentley_1.DbResult.BE_SQLITE_DONE !== rc)
|
|
273
|
+
throw new core_common_1.IModelError(rc, "can't delete named version");
|
|
274
|
+
});
|
|
275
|
+
db.saveChanges();
|
|
276
|
+
}
|
|
277
|
+
/** find the changeset for a named version */
|
|
278
|
+
findNamedVersion(versionName) {
|
|
279
|
+
const index = this.db.withSqliteStatement("SELECT csIndex FROM versions WHERE name=?", (stmt) => {
|
|
280
|
+
stmt.bindString(1, versionName);
|
|
281
|
+
const rc = stmt.step();
|
|
282
|
+
if (core_bentley_1.DbResult.BE_SQLITE_ROW !== rc)
|
|
283
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.NotFound, `Named version ${versionName} not found`);
|
|
284
|
+
return stmt.getValueInteger(0);
|
|
285
|
+
});
|
|
286
|
+
return this.getChangesetByIndex(index);
|
|
287
|
+
}
|
|
288
|
+
checkpointNameFromIndex(csIndex) {
|
|
289
|
+
return `checkpoint-${csIndex}`;
|
|
290
|
+
}
|
|
291
|
+
/** "upload" a checkpoint */
|
|
292
|
+
uploadCheckpoint(arg) {
|
|
293
|
+
const db = this.db;
|
|
294
|
+
db.withSqliteStatement("INSERT INTO checkpoints(csIndex) VALUES (?)", (stmt) => {
|
|
295
|
+
stmt.bindInteger(1, arg.changesetIndex);
|
|
296
|
+
const res = stmt.step();
|
|
297
|
+
if (core_bentley_1.DbResult.BE_SQLITE_DONE !== res)
|
|
298
|
+
throw new core_common_1.IModelError(res, "can't insert checkpoint into mock db");
|
|
299
|
+
});
|
|
300
|
+
db.saveChanges();
|
|
301
|
+
const outName = (0, path_1.join)(this.checkpointDir, this.checkpointNameFromIndex(arg.changesetIndex));
|
|
302
|
+
IModelJsFs_1.IModelJsFs.copySync(arg.localFile, outName);
|
|
303
|
+
return outName;
|
|
304
|
+
}
|
|
305
|
+
/** Get an array of the indexes for a range of checkpoints */
|
|
306
|
+
getCheckpoints(range) {
|
|
307
|
+
var _a, _b;
|
|
308
|
+
const first = (_a = range === null || range === void 0 ? void 0 : range.first) !== null && _a !== void 0 ? _a : 0;
|
|
309
|
+
const last = (_b = range === null || range === void 0 ? void 0 : range.end) !== null && _b !== void 0 ? _b : this.latestChangesetIndex;
|
|
310
|
+
const checkpoints = [];
|
|
311
|
+
this.db.withSqliteStatement("SELECT csIndex FROM checkpoints WHERE csIndex>=? AND csIndex<=? ORDER BY csIndex", (stmt) => {
|
|
312
|
+
stmt.bindInteger(1, first);
|
|
313
|
+
stmt.bindInteger(2, last);
|
|
314
|
+
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
315
|
+
checkpoints.push(stmt.getValueInteger(0));
|
|
316
|
+
});
|
|
317
|
+
return checkpoints;
|
|
318
|
+
}
|
|
319
|
+
/** Find the checkpoint that is no newer than a changesetIndex */
|
|
320
|
+
queryPreviousCheckpoint(changesetIndex) {
|
|
321
|
+
if (changesetIndex <= 0)
|
|
322
|
+
return 0;
|
|
323
|
+
return this.db.withSqliteStatement("SELECT max(csIndex) FROM checkpoints WHERE csIndex <= ? ", (stmt) => {
|
|
324
|
+
stmt.bindInteger(1, changesetIndex);
|
|
325
|
+
const res = stmt.step();
|
|
326
|
+
if (core_bentley_1.DbResult.BE_SQLITE_ROW !== res)
|
|
327
|
+
throw new core_common_1.IModelError(res, "can't get previous checkpoint");
|
|
328
|
+
return stmt.getValueInteger(0);
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
/** "download" a checkpoint */
|
|
332
|
+
downloadCheckpoint(arg) {
|
|
333
|
+
const index = this.getIndexFromChangeset(arg.changeset);
|
|
334
|
+
const prev = this.queryPreviousCheckpoint(index);
|
|
335
|
+
IModelJsFs_1.IModelJsFs.copySync((0, path_1.join)(this.checkpointDir, this.checkpointNameFromIndex(prev)), arg.targetFile);
|
|
336
|
+
const changeset = this.getChangesetByIndex(index);
|
|
337
|
+
return { index, id: changeset.id };
|
|
338
|
+
}
|
|
339
|
+
copyChangeset(arg) {
|
|
340
|
+
IModelJsFs_1.IModelJsFs.copySync(this.getChangesetFileName(arg.index), arg.pathname);
|
|
341
|
+
return arg;
|
|
342
|
+
}
|
|
343
|
+
/** "download" a changeset */
|
|
344
|
+
downloadChangeset(arg) {
|
|
345
|
+
const cs = this.getChangesetByIndex(arg.index);
|
|
346
|
+
const csProps = { ...cs, pathname: (0, path_1.join)(arg.targetDir, cs.id), index: arg.index };
|
|
347
|
+
return this.copyChangeset(csProps);
|
|
348
|
+
}
|
|
349
|
+
/** "download" all the changesets in a given range */
|
|
350
|
+
downloadChangesets(arg) {
|
|
351
|
+
const cSets = this.queryChangesets(arg.range);
|
|
352
|
+
for (const cs of cSets) {
|
|
353
|
+
cs.pathname = (0, path_1.join)(arg.targetDir, cs.id);
|
|
354
|
+
this.copyChangeset(cs);
|
|
355
|
+
}
|
|
356
|
+
return cSets;
|
|
357
|
+
}
|
|
358
|
+
querySharedLockHolders(elementId) {
|
|
359
|
+
return this.db.withPreparedSqliteStatement("SELECT briefcaseId FROM sharedLocks WHERE lockId=?", (stmt) => {
|
|
360
|
+
stmt.bindId(1, elementId);
|
|
361
|
+
const briefcases = new Set();
|
|
362
|
+
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
363
|
+
briefcases.add(stmt.getValueInteger(0));
|
|
364
|
+
return briefcases;
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
queryAllLocks(briefcaseId) {
|
|
368
|
+
this.getBriefcase(briefcaseId); // throws if briefcaseId invalid.
|
|
369
|
+
const locks = [];
|
|
370
|
+
this.db.withPreparedSqliteStatement("SELECT id FROM locks WHERE briefcaseId=?", (stmt) => {
|
|
371
|
+
stmt.bindInteger(1, briefcaseId);
|
|
372
|
+
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
373
|
+
locks.push({ id: stmt.getValueId(0), state: BackendHubAccess_1.LockState.Exclusive });
|
|
374
|
+
});
|
|
375
|
+
this.db.withPreparedSqliteStatement("SELECT lockId FROM sharedLocks WHERE briefcaseId=?", (stmt) => {
|
|
376
|
+
stmt.bindInteger(1, briefcaseId);
|
|
377
|
+
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
378
|
+
locks.push({ id: stmt.getValueId(0), state: BackendHubAccess_1.LockState.Shared });
|
|
379
|
+
});
|
|
380
|
+
return locks;
|
|
381
|
+
}
|
|
382
|
+
queryLockStatus(elementId) {
|
|
383
|
+
return this.db.withPreparedSqliteStatement("SELECT lastCSetIndex,level,briefcaseId FROM locks WHERE id=?", (stmt) => {
|
|
384
|
+
stmt.bindId(1, elementId);
|
|
385
|
+
const rc = stmt.step();
|
|
386
|
+
if (core_bentley_1.DbResult.BE_SQLITE_ROW !== rc)
|
|
387
|
+
return { state: BackendHubAccess_1.LockState.None };
|
|
388
|
+
const lastCsVal = stmt.getValue(0);
|
|
389
|
+
const lock = {
|
|
390
|
+
lastCsIndex: lastCsVal.isNull ? undefined : lastCsVal.getInteger(),
|
|
391
|
+
state: stmt.getValueInteger(1),
|
|
392
|
+
};
|
|
393
|
+
switch (lock.state) {
|
|
394
|
+
case BackendHubAccess_1.LockState.None:
|
|
395
|
+
return lock;
|
|
396
|
+
case BackendHubAccess_1.LockState.Exclusive:
|
|
397
|
+
return { ...lock, briefcaseId: stmt.getValueInteger(2) };
|
|
398
|
+
case BackendHubAccess_1.LockState.Shared:
|
|
399
|
+
return { ...lock, sharedBy: this.querySharedLockHolders(elementId) };
|
|
400
|
+
default:
|
|
401
|
+
throw new Error("illegal lock state");
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
reserveLock(currStatus, props, briefcase) {
|
|
406
|
+
if (props.state === BackendHubAccess_1.LockState.Exclusive && currStatus.lastCsIndex && (currStatus.lastCsIndex > this.getIndexFromChangeset(briefcase.changeset)))
|
|
407
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelHubStatus.PullIsRequired, "pull is required to obtain lock");
|
|
408
|
+
const wantShared = props.state === BackendHubAccess_1.LockState.Shared;
|
|
409
|
+
if (wantShared && (currStatus.state === BackendHubAccess_1.LockState.Exclusive))
|
|
410
|
+
throw new Error("cannot acquire shared lock because an exclusive lock is already held");
|
|
411
|
+
this.db.withPreparedSqliteStatement("INSERT INTO locks(id,level,briefcaseId) VALUES(?,?,?) ON CONFLICT(id) DO UPDATE SET briefcaseId=excluded.briefcaseId,level=excluded.level", (stmt) => {
|
|
412
|
+
stmt.bindId(1, props.id);
|
|
413
|
+
stmt.bindInteger(2, props.state);
|
|
414
|
+
stmt.bindValue(3, wantShared ? undefined : briefcase.briefcaseId);
|
|
415
|
+
const rc = stmt.step();
|
|
416
|
+
if (rc !== core_bentley_1.DbResult.BE_SQLITE_DONE)
|
|
417
|
+
throw new core_common_1.IModelError(rc, "cannot insert lock");
|
|
418
|
+
});
|
|
419
|
+
if (wantShared) {
|
|
420
|
+
this.db.withPreparedSqliteStatement("INSERT INTO sharedLocks(lockId,briefcaseId) VALUES(?,?)", (stmt) => {
|
|
421
|
+
stmt.bindId(1, props.id);
|
|
422
|
+
stmt.bindInteger(2, briefcase.briefcaseId);
|
|
423
|
+
const rc = stmt.step();
|
|
424
|
+
if (rc !== core_bentley_1.DbResult.BE_SQLITE_DONE)
|
|
425
|
+
throw new core_common_1.IModelError(rc, "cannot insert shared lock");
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
clearLock(id) {
|
|
430
|
+
this.db.withPreparedSqliteStatement("UPDATE locks SET level=0,briefcaseId=NULL WHERE id=?", (stmt) => {
|
|
431
|
+
stmt.bindId(1, id);
|
|
432
|
+
const rc = stmt.step();
|
|
433
|
+
if (rc !== core_bentley_1.DbResult.BE_SQLITE_DONE)
|
|
434
|
+
throw new core_common_1.IModelError(rc, "can't release lock");
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
updateLockChangeset(id, index) {
|
|
438
|
+
if (index <= 0)
|
|
439
|
+
return;
|
|
440
|
+
this.db.withPreparedSqliteStatement("UPDATE locks SET lastCSetIndex=? WHERE id=?", (stmt) => {
|
|
441
|
+
stmt.bindInteger(1, index);
|
|
442
|
+
stmt.bindId(2, id);
|
|
443
|
+
const rc = stmt.step();
|
|
444
|
+
if (rc !== core_bentley_1.DbResult.BE_SQLITE_DONE)
|
|
445
|
+
throw new core_common_1.IModelError(rc, "can't update lock changeSetId");
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
requestLock(props, briefcase) {
|
|
449
|
+
if (props.state === BackendHubAccess_1.LockState.None)
|
|
450
|
+
throw new Error("cannot request lock for LockState.None");
|
|
451
|
+
this.getBriefcase(briefcase.briefcaseId); // throws if briefcaseId invalid.
|
|
452
|
+
const lockStatus = this.queryLockStatus(props.id);
|
|
453
|
+
switch (lockStatus.state) {
|
|
454
|
+
case BackendHubAccess_1.LockState.None:
|
|
455
|
+
return this.reserveLock(lockStatus, props, briefcase);
|
|
456
|
+
case BackendHubAccess_1.LockState.Shared:
|
|
457
|
+
if (props.state === BackendHubAccess_1.LockState.Shared) {
|
|
458
|
+
if (!lockStatus.sharedBy.has(briefcase.briefcaseId))
|
|
459
|
+
this.reserveLock(lockStatus, props, briefcase);
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
// if requester is the only one holding a shared lock, "upgrade" the lock from shared to exclusive
|
|
463
|
+
if (lockStatus.sharedBy.size > 1 || !lockStatus.sharedBy.has(briefcase.briefcaseId)) {
|
|
464
|
+
const id = lockStatus.sharedBy.values().next().value;
|
|
465
|
+
throw new BackendHubAccess_1.LockConflict(id, this.getBriefcase(id).alias, "shared lock is held");
|
|
466
|
+
}
|
|
467
|
+
this.removeSharedLock(props.id, briefcase.briefcaseId);
|
|
468
|
+
this.reserveLock(this.queryLockStatus(props.id), props, briefcase);
|
|
469
|
+
}
|
|
470
|
+
return;
|
|
471
|
+
case BackendHubAccess_1.LockState.Exclusive:
|
|
472
|
+
if (lockStatus.briefcaseId !== briefcase.briefcaseId)
|
|
473
|
+
throw new BackendHubAccess_1.LockConflict(lockStatus.briefcaseId, this.getBriefcase(lockStatus.briefcaseId).alias, "exclusive lock is already held");
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
removeSharedLock(lockId, briefcaseId) {
|
|
477
|
+
this.db.withPreparedSqliteStatement("DELETE FROM sharedLocks WHERE lockId=? AND briefcaseId=?", (stmt) => {
|
|
478
|
+
stmt.bindId(1, lockId);
|
|
479
|
+
stmt.bindInteger(2, briefcaseId);
|
|
480
|
+
const rc = stmt.step();
|
|
481
|
+
if (rc !== core_bentley_1.DbResult.BE_SQLITE_DONE)
|
|
482
|
+
throw new core_common_1.IModelError(rc, "can't remove shared lock");
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
releaseLock(props, arg) {
|
|
486
|
+
const lockId = props.id;
|
|
487
|
+
const lockStatus = this.queryLockStatus(lockId);
|
|
488
|
+
switch (lockStatus.state) {
|
|
489
|
+
case BackendHubAccess_1.LockState.None:
|
|
490
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelHubStatus.LockDoesNotExist, "lock not held");
|
|
491
|
+
case BackendHubAccess_1.LockState.Exclusive:
|
|
492
|
+
if (lockStatus.briefcaseId !== arg.briefcaseId)
|
|
493
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelHubStatus.LockOwnedByAnotherBriefcase, "lock not held by this briefcase");
|
|
494
|
+
this.updateLockChangeset(lockId, arg.changesetIndex);
|
|
495
|
+
this.clearLock(lockId);
|
|
496
|
+
break;
|
|
497
|
+
case BackendHubAccess_1.LockState.Shared:
|
|
498
|
+
if (!lockStatus.sharedBy.has(arg.briefcaseId))
|
|
499
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelHubStatus.LockDoesNotExist, "shared lock not held by this briefcase");
|
|
500
|
+
this.removeSharedLock(lockId, arg.briefcaseId);
|
|
501
|
+
if (lockStatus.sharedBy.size === 1)
|
|
502
|
+
this.clearLock(lockId);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
/** Acquire a set of locks. If any lock cannot be acquired, no locks are acquired */
|
|
506
|
+
acquireLocks(locks, briefcase) {
|
|
507
|
+
try {
|
|
508
|
+
for (const lock of locks)
|
|
509
|
+
this.requestLock({ id: lock[0], state: lock[1] }, briefcase);
|
|
510
|
+
this.db.saveChanges(); // only after all locks have been acquired
|
|
511
|
+
}
|
|
512
|
+
catch (err) {
|
|
513
|
+
this.db.abandonChanges(); // abandon all locks that may have been acquired
|
|
514
|
+
throw err;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
acquireLock(props, briefcase) {
|
|
518
|
+
const locks = new Map();
|
|
519
|
+
locks.set(props.id, props.state);
|
|
520
|
+
this.acquireLocks(locks, briefcase);
|
|
521
|
+
}
|
|
522
|
+
releaseLocks(locks, arg) {
|
|
523
|
+
for (const props of locks)
|
|
524
|
+
this.releaseLock(props, arg);
|
|
525
|
+
this.db.saveChanges();
|
|
526
|
+
}
|
|
527
|
+
releaseAllLocks(arg) {
|
|
528
|
+
const locks = this.queryAllLocks(arg.briefcaseId);
|
|
529
|
+
this.releaseLocks(locks, arg);
|
|
530
|
+
}
|
|
531
|
+
countTable(tableName) {
|
|
532
|
+
return this.db.withSqliteStatement(`SELECT count(*) from ${tableName}`, (stmt) => {
|
|
533
|
+
stmt.step();
|
|
534
|
+
return stmt.getValueInteger(0);
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
// for debugging
|
|
538
|
+
countSharedLocks() { return this.countTable("sharedLocks"); }
|
|
539
|
+
// for debugging
|
|
540
|
+
countLocks() { return this.countTable("locks"); }
|
|
541
|
+
// for debugging
|
|
542
|
+
queryAllSharedLocks() {
|
|
543
|
+
const locks = [];
|
|
544
|
+
this.db.withPreparedSqliteStatement("SELECT lockId,briefcaseId FROM sharedLocks", (stmt) => {
|
|
545
|
+
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
546
|
+
locks.push({ id: stmt.getValueId(0), briefcaseId: stmt.getValueInteger(1) });
|
|
547
|
+
});
|
|
548
|
+
return locks;
|
|
549
|
+
}
|
|
550
|
+
// for debugging
|
|
551
|
+
queryLocks() {
|
|
552
|
+
const locks = [];
|
|
553
|
+
this.db.withPreparedSqliteStatement("SELECT id,level,lastCSetIndex,briefcaseId FROM locks", (stmt) => {
|
|
554
|
+
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step())
|
|
555
|
+
locks.push({
|
|
556
|
+
id: stmt.getValueId(0),
|
|
557
|
+
level: stmt.getValueInteger(1),
|
|
558
|
+
lastCsIndex: stmt.getValue(2).isNull ? undefined : stmt.getValueInteger(2),
|
|
559
|
+
briefcaseId: stmt.getValue(3).isNull ? undefined : stmt.getValueInteger(3),
|
|
560
|
+
});
|
|
561
|
+
});
|
|
562
|
+
return locks;
|
|
563
|
+
}
|
|
564
|
+
removeDir(dirName) {
|
|
565
|
+
if (IModelJsFs_1.IModelJsFs.existsSync(dirName)) {
|
|
566
|
+
IModelJsFs_1.IModelJsFs.purgeDirSync(dirName);
|
|
567
|
+
IModelJsFs_1.IModelJsFs.rmdirSync(dirName);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
cleanup() {
|
|
571
|
+
if (this._hubDb) {
|
|
572
|
+
this._hubDb.closeDb();
|
|
573
|
+
this._hubDb = undefined;
|
|
574
|
+
}
|
|
575
|
+
try {
|
|
576
|
+
this.removeDir(BriefcaseManager_1.BriefcaseManager.getIModelPath(this.iModelId));
|
|
577
|
+
this.removeDir(this.rootDir);
|
|
578
|
+
}
|
|
579
|
+
catch (err) {
|
|
580
|
+
// eslint-disable-next-line no-console
|
|
581
|
+
console.log(`ERROR: test left an iModel open for [${this.iModelName}]. LocalMock cannot clean up - make sure you call imodel.close() in your test`);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
exports.LocalHub = LocalHub;
|
|
586
586
|
//# sourceMappingURL=LocalHub.js.map
|