public MetadataRecord GetExactMetadata(string repoPath) { try { GetExactMetadataQuery.Bind((binder, repo) => { var zData = StringToHGlobalUTF8(repo, out var len); if (binder.BindText(1, zData, len) != 0) { ThrowHelper.FailFast("Cannot bind repoPath"); } }, repoPath); return(GetExactMetadataQuery.Step((hasRow, reader, _) => { if (hasRow) { return MapMetadataTableRow(reader); } return default; }, (object)null)); } finally { GetExactMetadataQuery.ClearAndReset(); } }
// TODO this should return IEnumerable of all new rows that should map to repo creation event // For external repos server must send the entire path with ids. // This is called inside a txn. A use case is recursive path creation that calls the query multiple times. // Parent must exist exactly in this call. public bool InsertMetadataRow(MetadataRecord record) { try { InsertMetadataRowQuery.Bind((binder, r) => { int rc; var zData = StringToHGlobalUTF8(r.PK, out var len); if ((rc = binder.BindText(1, zData, len)) != 0) { ThrowHelper.FailFast("Cannot bind PK: " + rc); } if ((rc = binder.BindInt64(2, r.RepoId)) != 0) { ThrowHelper.FailFast("Cannot bind RepoId: " + rc); } if ((rc = binder.BindInt64(3, r.ContainerId)) != 0) { ThrowHelper.FailFast("Cannot bind ContainerId: " + rc); } if ((rc = binder.BindInt64(4, r.ParentId)) != 0) { ThrowHelper.FailFast("Cannot bind ParentId: " + rc); } if ((rc = binder.BindInt64(5, r.Counter)) != 0) { ThrowHelper.FailFast("Cannot bind Counter: " + rc); } if ((rc = binder.BindInt64(6, r.Version)) != 0) { ThrowHelper.FailFast("Cannot bind Version: " + rc); } if ((rc = binder.BindInt64(7, r.RemoteId)) != 0) { ThrowHelper.FailFast("Cannot bind RemoteId: " + rc); } if ((rc = binder.BindInt64(8, r.Permissions)) != 0) { ThrowHelper.FailFast("Cannot bind Permissions: " + rc); } if ((rc = binder.BindInt64(9, r.SchemaType)) != 0) { ThrowHelper.FailFast("Cannot bind SchemaType: " + rc); } if (r.Schema != null) { zData = StringToHGlobalUTF8(JsonSerializer.ToJsonString(r.Schema, ExcludeNullStandardResolver.Instance), out len); if ((rc = binder.BindText(10, zData, len)) != 0) { ThrowHelper.FailFast("Cannot bind Schema: " + rc); } } if (r.Metadata != null) { zData = StringToHGlobalUTF8(JsonSerializer.ToJsonString(r.Metadata, ExcludeNullStandardResolver.Instance), out len); if ((rc = binder.BindText(11, zData, len)) != 0) { ThrowHelper.FailFast("Cannot bind Metadata: " + rc); } } }, record); try { return(InsertMetadataRowQuery.Step((hasRow, reader, state) => { if (hasRow) { ThrowHelper.FailFast("InsertChunk should not return rows"); } return reader.Changes() == 1; }, (object)null)); } catch { return(false); } } catch (Exception ex) { ThrowHelper.FailFast("Cannot insert chunk: " + ex); return(false); } finally { InsertMetadataRowQuery.ClearAndReset(); } }
public int IncrementCounter(string repoPath) { // TODO exception handling (e.g. SQLite busy) // BeginConcurrentQuery.RawStep((hasRow, reader, st) => true, (object)null, out _); try { IncrementCounterQuery.Bind((binder, repo) => { var zData = StringToHGlobalUTF8(repo, out var len); if (binder.BindText(1, zData, len) != 0) { ThrowHelper.FailFast("Cannot bind repoPath"); } }, repoPath); GetExactMetadataQuery.Bind((binder, repo) => { var zData = StringToHGlobalUTF8(repo, out var len); if (binder.BindText(1, zData, len) != 0) { ThrowHelper.FailFast("Cannot bind repoPath"); } }, repoPath); if (IncrementCounterQuery.Step((hasRow, reader, _) => { if (hasRow) { ThrowHelper.FailFast("InsertChunk should not return rows."); } return(reader.Changes() == 1); }, (object)null)) { return(GetExactMetadataQuery.Step((hasRow, reader, _) => { if (hasRow) { return MapMetadataTableRow(reader).Counter; } return -1; }, (object)null)); //// TODO separate query //var md = GetExactMetadata(repoPath, false); //return md.Counter; } else { return(-1); } } finally { // CommitQuery.RawStep((hasRow, reader, st) => true, (object)null, out _); IncrementCounterQuery.ClearAndReset(); GetExactMetadataQuery.ClearAndReset(); //BeginConcurrentQuery.Reset(); //CommitQuery.Reset(); } }
public unsafe (bool, long) InsertTest(long a, long b, RetainedMemory <byte> rawData) { const int aColumn = 1; const int bColumn = 2; const int dataColumn = 3; try { var sw = new SpinWait(); // TODO serialize before bind because we need to release temp buffer InsertTestQuery.Bind((binder, tuple) => { var blobSize = tuple.rawData.Length; var ptr = (IntPtr)tuple.rawData.Pointer; Debug.Assert(blobSize > 0); int rc; if ((rc = binder.BindInt64(aColumn, tuple.a)) != 0) { ThrowHelper.FailFast("Cannot bind chunk.StreamId: " + rc); } if ((rc = binder.BindInt64(bColumn, tuple.b)) != 0) { ThrowHelper.FailFast("Cannot bind chunk.FirstVersion: " + rc); } if ((rc = binder.BindBlob(dataColumn, ptr, blobSize)) != 0) { ThrowHelper.FailFast("Cannot bind chunk blob: " + rc); } }, (a, b, rawData)); RETRY: // var rcBegin = BeginConcurrentQuery.RawStep((hasRow, reader, st) => true, (object)null, out _); // Console.WriteLine("rcBegin: " + rcBegin); RETRY_TEST: var rcTest = InsertTestQuery.RawStep((hasRow, reader, state) => { if (hasRow) { ThrowHelper.FailFast("InsertChunk should not return rows"); } return(reader.Changes() == 1, reader.LastRowId()); }, (object)null, out var result); //if (rcTest != Spreads.SQLite.Interop.Constants.SQLITE_DONE) //{ // Console.WriteLine("rcTest: " + rcTest); //} RETRY_COMMIT: // var rcCommit = CommitQuery.RawStep((hasRow, reader, st) => true, (object)null, out _); if (rcTest != Spreads.SQLite.Interop.Constants.SQLITE_DONE) { // Console.WriteLine(rcCommit); sw.SpinOnce(); goto RETRY_TEST; ////// Console.WriteLine(rcTest); //if (rcCommit == Spreads.SQLite.Interop.Constants.SQLITE_BUSY_SNAPSHOT) //{ // // Console.WriteLine("SQLITE_BUSY_SNAPSHOT"); //} //else //{ // //Console.WriteLine("RETRY"); // sw.SpinOnce(); // // Console.WriteLine(rcCommit); // goto RETRY_COMMIT; //} //////// Console.WriteLine("NOT DONE: " + rcTest); //Rollback(); //BeginConcurrentQuery.Reset(); //TestQuery.Reset(); //CommitQuery.Reset(); //sw.SpinOnce(); //goto RETRY; } return(result); } catch (Exception ex) { ThrowHelper.FailFast("Cannot insert chunk: " + ex); return(false, 0); } finally { InsertTestQuery.ClearAndReset(); //BeginConcurrentQuery.Reset(); //CommitQuery.Reset(); } }