internal void WriteMessage(ref int db, RedisMessage next, IList <QueuedMessage> queued) { if (next.Db >= 0) { if (db != next.Db) { db = next.Db; RedisMessage changeDb = RedisMessage.Create(db, RedisLiteral.SELECT, db).ExpectOk().Critical(); if (queued != null) { queued.Add((QueuedMessage)(changeDb = new QueuedMessage(changeDb))); } RecordSent(changeDb); changeDb.Write(outBuffer); Interlocked.Increment(ref messagesSent); } LogUsage(db); } if (next.Command == RedisLiteral.SELECT) { // dealt with above; no need to send SELECT, SELECT } else { var mm = next as IMultiMessage; RedisMessage tmp = next; if (queued != null) { if (mm != null) { throw new InvalidOperationException( "Cannot perform composite operations (such as transactions) inside transactions"); } queued.Add((QueuedMessage)(tmp = new QueuedMessage(tmp))); } if (mm == null) { RecordSent(tmp); tmp.Write(outBuffer); Interlocked.Increment(ref messagesSent); switch (tmp.Command) { // scripts can change database case RedisLiteral.EVAL: case RedisLiteral.EVALSHA: // transactions can be aborted without running the inner commands (SELECT) that have been written case RedisLiteral.DISCARD: case RedisLiteral.EXEC: // we can't trust the current database; whack it db = -1; break; } } else { mm.Execute(this, ref db); } } }