Example #1
0
        /// <summary>
        /// disconnect removes a connection to the database, a connection
        /// which was previously established via Raft consensus.
        /// </summary>
        /// <param name="c"></param>
        internal async Task disconnect(StoreConnection c)
        {
            var cmd = new Command {
                Typ = CommandType.disconnect, Sub = new connectionSub {
                    ConnID = c.ID
                }
            };
            await raft.Accept(cmd).ThrowOnError();

            stats.NumDisconnects.WriteMetric(1);
        }
Example #2
0
 /// <summary>
 /// Connection returns the connection for the given ID.
 /// </summary>
 /// <param name="id"></param>
 /// <param name="conn"></param>
 /// <returns></returns>
 public bool Connection(ulong id, out StoreConnection conn)
 {
     connsMu.EnterReadLock();
     try
     {
         return(conns.TryGetValue(id, out conn));
     }
     finally
     {
         connsMu.ExitReadLock();
     }
 }
Example #3
0
        /// <summary>
        /// Execute executes queries that return no rows, but do modify the database. If connection
        /// is nil then the utility connection is used.
        /// </summary>
        /// <param name="c"></param>
        /// <param name="ex"></param>
        /// <returns></returns>
        internal async Task <ExecuteResponse> execute(StoreConnection c, ExecuteRequest ex)
        {
            if (c == null)
            {
                connsMu.EnterReadLock();
                try
                {
                    c = conns[defaultConnID];
                }
                finally
                {
                    connsMu.ExitReadLock();
                }
            }
            c.SetLastUsedNow();
            var start = DateTime.Now;
            var cmd   = new Command
            {
                Typ = CommandType.execute,
                Sub = new databaseSub
                {
                    ConnID  = c.ID,
                    Atomic  = ex.Atomic,
                    Queries = ex.Queries,
                    Timings = ex.Timings
                }
            };

            var f = await raft.Accept(cmd).ThrowOnError();

            if (f is FsmExecuteResponse <Command> )
            {
                return(new ExecuteResponse
                {
                    Results = (f as FsmExecuteResponse <Command>).Results,
                    Time = (DateTime.Now - start).TotalSeconds,
                    Raft = new RaftResponse {
                        NodeID = ID
                    }
                });
            }
            else if (f is ErrorResponse <Command> )
            {
                throw new Exception((f as ErrorResponse <Command>).Error);
            }
            else
            {
                throw new Exception("unsupported type");
            }
        }
Example #4
0
        internal async Task <ExecuteResponse> executeOrAbort(StoreConnection c, ExecuteRequest ex)
        {
            if (c == null)
            {
                connsMu.EnterReadLock();
                try
                {
                    c = conns[defaultConnID];
                }
                finally
                {
                    connsMu.ExitReadLock();
                }
            }
            bool errored = false;

            try
            {
                var f = await c.Store.execute(c, ex);

                errored = f.Results.Any(r => !string.IsNullOrEmpty(r.Error));
                return(f);
            }
            catch (Exception e)
            {
                errored = true;
                c.Logger.LogError(e.ToString());
                throw;
            }
            finally
            {
                if (errored)
                {
                    try
                    {
                        await c.AbortTransaction();
                    }
                    catch (Exception e)
                    {
                        c.Logger.LogWarning($"WARNING: failed to abort transaction on {c}: {e.Message}");
                    }
                }
            }
        }
Example #5
0
        /// <summary>
        /// Query executes queries that return rows, and do not modify the database. If
        /// connection is nil, then the utility connection is used.
        /// </summary>
        /// <param name="c"></param>
        /// <param name="qr"></param>
        /// <returns></returns>
        internal async Task <QueryResponse> query(StoreConnection c, QueryRequest qr)
        {
            if (c == null)
            {
                connsMu.EnterReadLock();
                try
                {
                    c = conns[defaultConnID];
                }
                finally
                {
                    connsMu.ExitReadLock();
                }
            }
            c.SetLastUsedNow();
            restoreMu.EnterReadLock();
            try
            {
                var start = DateTime.Now;
                if (qr.Lvl == ConsistencyLevel.Strong)
                {
                    var d = new databaseSub
                    {
                        ConnID  = c.ID,
                        Atomic  = qr.Atomic,
                        Queries = qr.Queries,
                        Timings = qr.Timings
                    };
                    var cmd = new Command {
                        Typ = CommandType.query, Sub = d
                    };
                    var f = await raft.Accept(cmd).ThrowOnError();

                    if (f is FsmQueryResponse <Command> )
                    {
                        return(new QueryResponse
                        {
                            Rows = (f as FsmQueryResponse <Command>).Rows,
                            Time = (DateTime.Now - start).TotalSeconds,
                            Raft = new RaftResponse {
                                NodeID = ID
                            }
                        });
                    }
                    else if (f is ErrorResponse <Command> )
                    {
                        throw new Exception((f as ErrorResponse <Command>).Error);
                    }
                    else
                    {
                        throw new Exception("unsupported type");
                    }
                }

                if (qr.Lvl == ConsistencyLevel.Weak && !(raft.State is Leader))
                {
                    throw new NotLeaderException();
                }

                var r = c.db.Query(qr.Queries.ToArray(), qr.Atomic, qr.Timings);
                return(new QueryResponse
                {
                    Rows = r,
                    Time = (DateTime.Now - start).TotalSeconds
                });
            }
            finally
            {
                restoreMu.ExitReadLock();
            }
        }