private void VerifyTimeout(int writeTimeout)
        {
            using (var com1 = new SerialPort(TCSupport.LocalMachineSerialInfo.FirstAvailablePortName))
                using (var com2 = new SerialPort(TCSupport.LocalMachineSerialInfo.SecondAvailablePortName))
                {
                    var asyncRead           = new AsyncWrite(com1);
                    var asyncEndWrite       = new Task(asyncRead.EndWrite);
                    var asyncCallbackCalled = false;

                    com1.Open();
                    com2.Open();
                    com1.Handshake    = Handshake.RequestToSend;
                    com1.WriteTimeout = writeTimeout;

                    IAsyncResult writeAsyncResult = com1.BaseStream.BeginWrite(new byte[8], 0, 8, ar => asyncCallbackCalled = true, null);
                    asyncRead.WriteAsyncResult = writeAsyncResult;

                    Thread.Sleep(100 > com1.WriteTimeout ? 2 * com1.WriteTimeout : 200);
                    // Sleep for 200ms or 2 times the WriteTimeout

                    if (writeAsyncResult.IsCompleted)
                    {
                        // Verify the IAsyncResult has not completed
                        Fail("Err_565088aueiud!!!: Expected read to not have completed");
                    }

                    asyncEndWrite.Start();
                    TCSupport.WaitForTaskToStart(asyncEndWrite);
                    Thread.Sleep(100 < com1.WriteTimeout ? 2 * com1.WriteTimeout : 200);
                    // Sleep for 200ms or 2 times the WriteTimeout

                    if (asyncEndWrite.IsCompleted)
                    {
                        // Verify EndRead is blocking and is still alive
                        Fail("Err_4085858aiehe!!!: Expected read to not have completed");
                    }

                    if (asyncCallbackCalled)
                    {
                        Fail("Err_750551aiuehd!!!: Expected AsyncCallback not to be called");
                    }

                    com2.RtsEnable = true;

                    TCSupport.WaitForTaskCompletion(asyncEndWrite);
                    var waitTime = 0;
                    while (!asyncCallbackCalled && waitTime < 5000)
                    {
                        Thread.Sleep(50);
                        waitTime += 50;
                    }

                    if (!asyncCallbackCalled)
                    {
                        Fail(
                            "Err_21208aheide!!!: Expected AsyncCallback to be called after some data was written to the port");
                    }
                }
        }
 public AsyncWrite(AsyncWrite other)
     : base(other)
 {
     this.writePolicy = other.writePolicy;
     this.listener    = other.listener;
     this.key         = other.key;
     this.bins        = other.bins;
     this.operation   = other.operation;
 }
        /// <summary>
        /// May return either a physical file name or a MemoryStream with the data.
        /// Faster than GetCachedFile, as writes are (usually) asynchronous. If the write queue is full, the write is forced to be synchronous again.
        /// Identical to GetCachedFile() when asynchronous=false
        /// </summary>
        /// <param name="keyBasis"></param>
        /// <param name="extension"></param>
        /// <param name="writeCallback"></param>
        /// <param name="timeoutMs"></param>
        /// <returns></returns>
        public CacheResult GetCachedFile(string keyBasis, string extension, ResizeImageDelegate writeCallback, int timeoutMs, bool asynchronous)
        {
            Stopwatch sw = null;

            if (lp.Logger != null)
            {
                sw = new Stopwatch(); sw.Start();
            }

            // Path to the file in the blob container
            string      path   = new UrlHasher().Hash(keyBasis) + '.' + extension;
            CacheResult result = new CacheResult(CacheQueryResult.Hit, path);

            bool asyncFailed = false;

            //2013-apr-25: What happens if the file is still being written to blob storage - it's present but not complete? To handle that, we use mayBeLocked.
            bool mayBeLocked = Locks.MayBeLocked(path.ToUpperInvariant());

            // On the first check, verify the file exists by connecting to the blob directly
            if (!asynchronous)
            {
                //May throw an IOException if the file cannot be opened, and is locked by an external processes for longer than timeoutMs.
                //This method may take longer than timeoutMs under absolute worst conditions.
                if (!TryWriteFile(result, path, writeCallback, timeoutMs, !mayBeLocked))
                {
                    //On failure
                    result.Result = CacheQueryResult.Failed;
                }
            }
            else if (!Index.PathExistInIndex(path) || mayBeLocked)
            {
                //Looks like a miss. Let's enter a lock for the creation of the file. This is a different locking system than for writing to the file - far less contention, as it doesn't include the
                //This prevents two identical requests from duplicating efforts. Different requests don't lock.

                //Lock execution using relativePath as the sync basis. Ignore casing differences. This prevents duplicate entries in the write queue and wasted CPU/RAM usage.
                if (!QueueLocks.TryExecute(path.ToUpperInvariant(), timeoutMs,
                                           delegate() {
                    //Now, if the item we seek is in the queue, we have a memcached hit. If not, we should check the index. It's possible the item has been written to disk already.
                    //If both are a miss, we should see if there is enough room in the write queue. If not, switch to in-thread writing.

                    AsyncWrite t = CurrentWrites.Get(path);

                    if (t != null)
                    {
                        result.Data = t.GetReadonlyStream();
                    }

                    //On the second check, use cached data for speed. The cached data should be updated if another thread updated a file (but not if another process did).
                    //When t == null, and we're inside QueueLocks, all work on the file must be finished, so we have no need to consult mayBeLocked.
                    if (t == null && !Index.PathExistInIndex(path))
                    {
                        result.Result = CacheQueryResult.Miss;
                        //Still a miss, we even rechecked the filesystem. Write to memory.
                        MemoryStream ms = new MemoryStream(4096);      //4K initial capacity is minimal, but this array will get copied around alot, better to underestimate.
                        //Read, resize, process, and encode the image. Lots of exceptions thrown here.
                        writeCallback(ms);
                        ms.Position = 0;

                        AsyncWrite w = new AsyncWrite(CurrentWrites, ms, path);
                        if (CurrentWrites.Queue(w, delegate(AsyncWrite job) {
                            try
                            {
                                Stopwatch swio = new Stopwatch();

                                swio.Start();
                                //TODO: perhaps a different timeout?
                                if (!TryWriteFile(null, job.Path, delegate(Stream s) { ((MemoryStream)job.GetReadonlyStream()).WriteTo(s); }, timeoutMs, true))
                                {
                                    swio.Stop();
                                    //We failed to lock the file.
                                    if (lp.Logger != null)
                                    {
                                        lp.Logger.Warn("Failed to flush async write, timeout exceeded after {1}ms - {0}", result.Path, swio.ElapsedMilliseconds);
                                    }
                                }
                                else
                                {
                                    swio.Stop();
                                    if (lp.Logger != null)
                                    {
                                        lp.Logger.Trace("{0}ms: Async write started {1}ms after enqueue for {2}", swio.ElapsedMilliseconds.ToString().PadLeft(4), DateTime.UtcNow.Subtract(w.JobCreatedAt).Subtract(swio.Elapsed).TotalMilliseconds, result.Path);
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                if (lp.Logger != null)
                                {
                                    lp.Logger.Error("Failed to flush async write, {0} {1}\n{2}", ex.ToString(), result.Path, ex.StackTrace);
                                }
                            }
                            finally
                            {
                                CurrentWrites.Remove(job);     //Remove from the queue, it's done or failed.
                            }
                        }))
                        {
                            //We queued it! Send back a read-only memory stream
                            result.Data = w.GetReadonlyStream();
                        }
                        else
                        {
                            asyncFailed = false;
                            //We failed to queue it - either the ThreadPool was exhausted or we exceeded the MB limit for the write queue.
                            //Write the MemoryStream to disk using the normal method.
                            //This is nested inside a queuelock because if we failed here, the next one will also. Better to force it to wait until the file is written to blob storage.
                            if (!TryWriteFile(result, path, delegate(Stream s) { ms.WriteTo(s); }, timeoutMs, false))
                            {
                                if (lp.Logger != null)
                                {
                                    lp.Logger.Warn("Failed to queue async write, also failed to lock for sync writing: {0}", result.Path);
                                }
                            }
                        }
                    }
                }))
                {
                    //On failure
                    result.Result = CacheQueryResult.Failed;
                }
            }
            if (lp.Logger != null)
            {
                sw.Stop();
                lp.Logger.Trace("{0}ms: {3}{1} for {2}, Key: {4}", sw.ElapsedMilliseconds.ToString(NumberFormatInfo.InvariantInfo).PadLeft(4), result.Result.ToString(), result.Path, asynchronous ? (asyncFailed ? "Fallback to sync  " : "Async ") : "", keyBasis);
            }

            //Fire event
            if (CacheResultReturned != null)
            {
                CacheResultReturned(this, result);
            }
            return(result);
        }
Beispiel #4
0
 /*
  * @ 以异步方式启动写入日志
  * */
 private void WriteLocal(string text, LogType type, Exception ex)
 {
     AsyncWrite   asyncWrite = new AsyncWrite(Write);
     IAsyncResult result     = asyncWrite.BeginInvoke(text, type, ex, logRecordType, null, null);
 }
Beispiel #5
0
    private bool VerifyTimeout(int writeTimeout)
    {
        SerialPort com1     = new SerialPort(TCSupport.LocalMachineSerialInfo.FirstAvailablePortName);
        SerialPort com2     = new SerialPort(TCSupport.LocalMachineSerialInfo.SecondAvailablePortName);
        bool       retValue = true;

        System.IAsyncResult writeAsyncResult;

        AsyncWrite asyncRead = new AsyncWrite(com1);

        System.Threading.Thread asyncEndWrite = new System.Threading.Thread(new System.Threading.ThreadStart(asyncRead.EndWrite));
        int  waitTime;
        bool asyncCallbackCalled = false;

        com1.Open();
        com2.Open();
        com1.Handshake    = Handshake.RequestToSend;
        com1.WriteTimeout = writeTimeout;

        writeAsyncResult           = com1.BaseStream.BeginWrite(new byte[8], 0, 8, delegate(IAsyncResult ar) { asyncCallbackCalled = true; }, null);
        asyncRead.WriteAsyncResult = writeAsyncResult;

        System.Threading.Thread.Sleep(100 > com1.WriteTimeout ? 2 * com1.WriteTimeout : 200); //Sleep for 200ms or 2 times the WriteTimeout

        if (writeAsyncResult.IsCompleted)
        {//Verify the IAsyncResult has not completed
            Console.WriteLine("Err_565088aueiud!!!: Expected read to not have completed");
            retValue = false;
        }

        asyncEndWrite.Start();

        waitTime = 0;
        while (asyncEndWrite.ThreadState == System.Threading.ThreadState.Unstarted && waitTime < MAX_WAIT_THREAD)
        {//Wait for the thread to start
            System.Threading.Thread.Sleep(50);
            waitTime += 50;
        }

        if (MAX_WAIT_THREAD <= waitTime)
        {
            Console.WriteLine("Err_018158ajied!!!: Expected EndRead to have returned");
            retValue = false;
        }

        System.Threading.Thread.Sleep(100 < com1.WriteTimeout ? 2 * com1.WriteTimeout : 200); //Sleep for 200ms or 2 times the WriteTimeout

        if (!asyncEndWrite.IsAlive)
        {//Verify EndRead is blocking and is still alive
            Console.WriteLine("Err_4085858aiehe!!!: Expected read to not have completed");
            retValue = false;
        }

        if (asyncCallbackCalled)
        {
            Console.WriteLine("Err_750551aiuehd!!!: Expected AsyncCallback not to be called");
            retValue = false;
        }

        com2.RtsEnable = true;

        waitTime = 0;
        while (asyncEndWrite.IsAlive && waitTime < MAX_WAIT_THREAD)
        {
            System.Threading.Thread.Sleep(50);
            waitTime += 50;
        }

        if (MAX_WAIT_THREAD <= waitTime)
        {
            Console.WriteLine("Err_018158ajied!!!: Expected EndRead to have returned");
            retValue = false;
        }

        waitTime = 0;
        while (!asyncCallbackCalled && waitTime < 5000)
        {
            System.Threading.Thread.Sleep(50);
            waitTime += 50;
        }

        if (!asyncCallbackCalled)
        {
            Console.WriteLine("Err_21208aheide!!!: Expected AsyncCallback to be called after some data was written to the port");
            retValue = false;
        }


        if (com1.IsOpen)
        {
            com1.Close();
        }

        if (com2.IsOpen)
        {
            com2.Close();
        }

        return(retValue);
    }