Пример #1
0
        private void SlowWrite(WriteOp op, AccessCondition accessCondition, List <SessionState> sessions = null, ServerMonitor monitor = null)
        {
            // A reconfiguration is in progress, but may not have happened yet.
            // We could try to complete this write before the reconfiguration, but that would require locking
            // to prevent the configuration service from changing the configuration during this write.
            // Instead, we take the simple approach of waiting for the reconfiguration to complete.

            bool isDone = false;

            do  // while unable to lease the configuration
            {
                if (configuration.IsInFastMode(renew: true))
                {
                    if (configuration.PrimaryServers.Count == 1)
                    {
                        FastWrite(op, sessions, monitor);
                    }
                    else
                    {
                        MultiWrite(op, accessCondition, sessions, monitor);
                    }
                    isDone = true;
                }
                else
                {
                    Thread.Sleep(ConstPool.CONFIGURATION_ACTION_DURATION);
                }
            }while (!isDone);
        }
Пример #2
0
        private void FastWrite(WriteOp op, List <SessionState> sessions = null, ServerMonitor monitor = null)
        {
            // there should only be one primary server since we are in fast mode
            string     server = configuration.PrimaryServers.First();
            ICloudBlob blob   = ClientRegistry.GetCloudBlob(server, configuration.Name, blobName, false);

            watch.Start();
            op(blob);
            watch.Stop();

            // update server and session state
            ServerState ss = (monitor == null) ? slaEngine.Monitor.GetServerState(server) : monitor.GetServerState(server);

            ss.AddRtt(watch.ElapsedMilliseconds);
            if (sessions == null)
            {
                slaEngine.Session.RecordObjectWritten(blobName, Timestamp(blob), ss);
            }
            else
            {
                foreach (SessionState session in sessions)
                {
                    session.RecordObjectWritten(blobName, Timestamp(blob), ss);
                }
            }
        }
Пример #3
0
        public void SetupOperations(Boolean monitorOps)
        {
            if (monitorOps)
            {
                ReadOperationHandler = (b, o, c) =>
                {
                    if (m_Core.State.PC != Position && m_Core.State.BranchPC != Position)
                    {
                        Machine.Current.DeviceCPU.ResourceMonitor.CPUMemRead(Position);
                    }
                    return(base.Read(b, o, c));
                };

                WriteOperationHandler = (b, o, c) =>
                {
                    Machine.Current.DeviceCPU.ResourceMonitor.CPUMemWrite(Position);
                    base.Write(b, o, c);
                };
            }
            else
            {
                ReadOperationHandler = (b, o, c) =>
                {
                    return(base.Read(b, o, c));
                };

                WriteOperationHandler = (b, o, c) =>
                {
                    base.Write(b, o, c);
                };
            }
        }
Пример #4
0
 private void WriteLoop <TValue>(byte register, TValue value, WriteOp <TValue> op)
 {
     for (int i = 0; i < MaxRetries; i++)
     {
         if (op(register, value))
         {
             return;
         }
     }
 }
Пример #5
0
 /// <summary>
 /// Perform a local write operation, e.g. set a property, on all blobs holding a replica.
 /// This does not bother to check the lease on the configuration.
 /// It should not be used for arbitrary writes that need to be performed atomically.
 /// </summary>
 /// <param name="op">the write operation being done</param>
 public void SetProperty(WriteOp op)
 {
     foreach (string server in configuration.PrimaryServers)
     {
         ICloudBlob blob = ClientRegistry.GetCloudBlob(server, configuration.Name, blobName);
         op(blob);
     }
     foreach (string server in configuration.SecondaryServers)
     {
         ICloudBlob blob = ClientRegistry.GetCloudBlob(server, configuration.Name, blobName);
         op(blob);
     }
 }
Пример #6
0
 public void Write(WriteOp op, AccessCondition accessCondition, List <SessionState> sessions = null, ServerMonitor monitor = null)
 {
     // TODO: ensure that there is enough time left on the lease to complete the write
     // Can set a timeout using BlobRequestOptions and/or renew a least that is about to expire
     if (configuration.IsInFastMode())
     {
         if (configuration.PrimaryServers.Count == 1)
         {
             FastWrite(op, sessions, monitor);
         }
         else
         {
             MultiWrite(op, accessCondition, sessions, monitor);
         }
     }
     else
     {
         SlowWrite(op, accessCondition, sessions, monitor);
     }
 }
Пример #7
0
        private void MultiWriteUsingBlobLease(WriteOp op)
        {
            // TODO: recover from failed clients that may leave a write partially completed
            // TODO: remove use of leases and replace with ETags
            // throw new Exception("Write to multiple primaries not yet implemented.");
            try
            {
                bool done = false;
                while (!done)
                {
                    // grab lease on blob to guard against concurrent writers
                    using (PrimaryCloudBlobLease lease = new PrimaryCloudBlobLease(blobName, configuration, true))
                    {
                        if (lease.HasLease)
                        {
                            // TODO: fix code for writing to multiple primaries (and remove it from here)
                            foreach (string server in configuration.PrimaryServers)
                            {
                                watch.Start();
                                ICloudBlob blob = ClientRegistry.GetCloudBlob(server, configuration.Name, blobName, false);
                                op(blob);
                                watch.Stop();

                                ServerState ss = slaEngine.Monitor.GetServerState(server);
                                ss.AddRtt(watch.ElapsedMilliseconds);
                                slaEngine.Session.RecordObjectWritten(blobName, Timestamp(blob), ss);
                            }
                            done = true;
                        }
                    }
                }
            }
            catch (StorageException se)
            {
                throw se;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
Пример #8
0
        public void SetupOperations(Boolean monitorOps)
        {
            if (monitorOps)
            {
                ReadOperationHandler = (b, o, c) =>
                    {
                        if (m_Core.State.PC != Position && m_Core.State.BranchPC != Position)
                            Machine.Current.DeviceCPU.ResourceMonitor.CPUMemRead(Position);
                        return base.Read(b, o, c);
                    };

                WriteOperationHandler = (b, o, c) =>
                {
                    Machine.Current.DeviceCPU.ResourceMonitor.CPUMemWrite(Position);
                    base.Write(b, o, c);
                };
            }
            else
            {
                ReadOperationHandler = (b, o, c) =>
                {
                    return base.Read(b, o, c);
                };

                WriteOperationHandler = (b, o, c) =>
                {
                    base.Write(b, o, c);
                };
            }
        }
Пример #9
0
        /// <summary>
        /// Optimization #6:
        /// Constant substitution
        ///
        /// TODO: This method has some inconsistencies when setting the offset with the new memory operations.
        ///       For some memory operations, I'm using "new {Op}(ptr + {op}.Offset)"
        ///       and for others I'm just using "new {Op}({op}.Offset)".
        ///       I'm pretty sure this inconsistency is causing some problems.
        /// </summary>
        /// <param name="operations"></param>
        private bool SubstituteConstants(ref DILOperationSet operations)
        {
            if (WereConstantsSubstituted)
            {
                return(false);
            }

            var ptr = 0;
            var arr = operations.ToArray();
            var didAnysubstitutions = false;

            for (int i = 0; i < arr.Length; i++)
            {
                var operation = arr[i];
                if (operation is AdditionMemoryOp)
                {
                    var add = (AdditionMemoryOp)operation;
                    if (add.Constant == null)
                    {
                        arr[i] = new AdditionMemoryOp(ptr + add.Offset, add.Scalar, new ConstantValue(ptr + add.Offset));
                        didAnysubstitutions = true;
                    }
                }
                else if (operation is MultiplicationMemoryOp)
                {
                    var mul = (MultiplicationMemoryOp)operation;
                    if (mul.Constant == null)
                    {
                        arr[i] = new MultiplicationMemoryOp(ptr + mul.Offset, mul.Scalar, new ConstantValue(ptr + mul.Offset), new ConstantValue(ptr));
                    }
                }
                else if (operation is AssignOp)
                {
                    var ass = arr[i] as AssignOp;
                    if (ass.Constant == null)
                    {
                        arr[i] = new AssignOp(ptr + ass.Offset, ass.Value, new ConstantValue(ptr + ass.Offset));
                        didAnysubstitutions = true;
                    }
                }
                else if (operation is PtrOp)
                {
                    arr[i] = null; // if we're using constants, then we don't need pointer movements
                    var ptrOp = (PtrOp)operation;
                    ptr += ptrOp.Delta;
                    //didAnysubstitutions = true;
                }
                else if (operation is WriteOp)
                {
                    var write = ((WriteOp)arr[i]);
                    if (write.Constant == null)
                    {
                        arr[i] = new WriteOp(write.Offset, write.Repeated, new ConstantValue(ptr));
                        didAnysubstitutions = true;
                    }
                }
                else if (operation is ReadOp)
                {
                    var read = ((ReadOp)arr[i]);
                    if (read.Constant == null)
                    {
                        arr[i] = new ReadOp(read.Offset, read.Repeated, new ConstantValue(ptr));
                        didAnysubstitutions = true;
                    }
                }
            }

            var list = arr.ToList();

            list.RemoveAll(l => l == null);

            operations = new DILOperationSet(list);

            operations.WereConstantsSubstituted = true;

            return(didAnysubstitutions);
        }
Пример #10
0
        private void DoFlush(IoSession session, WriteOp op)
        {
            if (op != null && !op.IsExpired)
            {
                try
                {
                    long cnt = flushCounter.AtomicIncrementAndGet();
                    long now = new DateTime().CurrentTimeMillis();
                    if (now - lastLogTime.ReadFullFence() > 60000)
                    {
                        lastLogTime.WriteFullFence(now);
                        string log = String.Format("opQueueSize: {0}, session: {1}, couner: {2}", opQueue.Count, session.RemoteEndPoint.ToString(), cnt);
                        client.Log.Info(log);
                    }

                    var writeFuture = session.Write(op.Command);
                    writeFuture.Complete += (s, e) =>
                    {
                        if (e.Future.Done)
                        {
                            flushing.AtomicExchange(false);
                            flushingOp.AtomicExchange(null);
                        }
                        else
                        {
                            if (!IsClosed)
                            {
                                Thread.Sleep(client.Config.EndpointSessionWriteRetryDealyInMills);
                                DoFlush(e.Future.Session, op);
                            }
                        }
                    };
                }
                catch (Exception ex)
                {
                    client.Log.Error(ex);
                    flushing.AtomicExchange(false);
                    flushingOp.AtomicExchange(null);
                }
            }
            else
            {
                flushing.AtomicExchange(false);
                flushingOp.AtomicExchange(null);
            }
        }
Пример #11
0
        private void MultiWrite(WriteOp op, AccessCondition access, List <SessionState> sessions = null, ServerMonitor monitor = null)
        {
            // This protocol uses three phases and ETags
            // It assumes that the client is in fast mode and remains so throughout the protocol
            // i.e. it assumes that the set of primaries does not change.
            // TODO: recover from failed clients that may leave a write partially completed

            ICloudBlob blob;
            Dictionary <string, string> eTags;

            // Phase 1.  Mark intention to write with write-in-progress flags
            eTags = SetWiPFlags();
            if (eTags == null)
            {
                // flags were not successfully set, so abort the protocol
                return;
            }

            // Phase 2.  Perform write at all primaries
            bool didAtLeastOne = false;

            foreach (string server in configuration.PrimaryServers)
            {
                blob = ClientRegistry.GetCloudBlob(server, configuration.Name, blobName, false);
                access.IfMatchETag = eTags[server];
                watch.Start();
                try
                {
                    op(blob);
                }
                catch (StorageException)
                {
                    // If writing fails at some primary, then abort the protocol
                    // It could be that a concurrent writer is in progress
                    // Note that some writes may have already been performed
                    // If so, then we leave the WiP flags set so the recovery process will kick in
                    // or so a concurrent writer can complete its protocol and overwrite our writes
                    // If not, then we can clear the WiP flags
                    if (!didAtLeastOne)
                    {
                        ClearWiPFlags(eTags);
                    }
                    return;
                }
                watch.Stop();
                eTags[server] = blob.Properties.ETag;
                didAtLeastOne = true;

                // update session and server state
                ServerState ss = (monitor == null) ? slaEngine.Monitor.GetServerState(server) : monitor.GetServerState(server);
                ss.AddRtt(watch.ElapsedMilliseconds);
                if (sessions == null)
                {
                    slaEngine.Session.RecordObjectWritten(blobName, Timestamp(blob), ss);
                }
                else
                {
                    foreach (SessionState session in sessions)
                    {
                        session.RecordObjectWritten(blobName, Timestamp(blob), ss);
                    }
                }
            }

            // Phase 3.  Clear write-in-progress flags to indicate that write has completed
            ClearWiPFlags(eTags);
        }