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();
                }
            }
Exemplo n.º 4
0
            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();
                }
            }