예제 #1
0
 // Enqueue an update
 // Note that only one update for each id is queued so it is possible that this particular
 //      update will not get queued if there is already one queued for that id.
 // Returns 'true' if the object was actually enqueued.
 public bool Enqueue(UUID id, SyncMsg update)
 {
     bool ret = false;
     lock(m_syncRoot)
     {
         if (!m_updates.ContainsKey(id))
         {
             m_queue.Enqueue(id);
             m_updates[id] = update;
             ret = true;
         }
         else
         {
             OverWrittenUpdates++;
             // If this is an update, we merge our update flags
             SyncMsgUpdatedProperties updatedPropMsg = update as SyncMsgUpdatedProperties;
             SyncMsgUpdatedProperties existingUpdatedPropMsg = m_updates[id] as SyncMsgUpdatedProperties;
             if (updatedPropMsg != null && existingUpdatedPropMsg != null)
             {
                 existingUpdatedPropMsg.AddUpdates(updatedPropMsg.SyncableProperties);
             }
             else
             {
                 // It is very odd that it is not one of ours. Don't know how another type got into the list.
             }
         }
         Monitor.Pulse(m_syncRoot);
     }
     return ret;
 }
예제 #2
0
 // Add a message to the first of the queue.
 public void QueueMessageFirst(SyncMsg update)
 {
     lock (m_syncRoot)
     {
         m_firstQueue.Enqueue(update);
         Monitor.Pulse(m_syncRoot);
     }
 }
예제 #3
0
        //Send out a messge directly. This should only by called for short messages that are not sent frequently.
        //Don't call this function for sending out updates. Call EnqueueOutgoingUpdate instead
        private void Send(SyncMsg msg)
        {
            // m_log.DebugFormat("{0} Send msg: {1}: {2}", LogHeader, this.Description, msg.ToString());
            if (m_tcpConnection.Connected)
            {
                try
                {
                    byte[] data = msg.GetWireBytes();
                    CollectSendStat(msg.MType.ToString(), msg.DataLength);
                    // Rather than async write, use the TCP flow control to stop this thread if the
                    //    receiver cannot consume the data quick enough.
                    m_tcpConnection.GetStream().Write(data, 0, data.Length);

                    m_lastSendTime = DateTime.Now;

                    /*
                    m_tcpConnection.GetStream().BeginWrite(data, 0, data.Length, ar =>
                    {
                        if (m_tcpConnection.Connected)
                        {
                            try
                            {
                                m_tcpConnection.GetStream().EndWrite(ar);
                            }
                            catch (Exception)
                            { }
                        }
                    }, null);
                     */
                }
                catch (Exception e)
                {
                    m_log.ErrorFormat("{0}:Error in Send() {1}/{2} has disconnected: connector={3}, msgType={4}. e={5}",
                                LogHeader, otherSideActorID, otherSideRegionName, m_connectorNum, msg.MType.ToString(), e);
                    Shutdown();
                }
            }
        }
예제 #4
0
        private void HandleMessage(SyncMsg msg)
        {
            // m_log.DebugFormat("{0} Recv msg: {1}: {2}", LogHeader, this.Description, msg.ToString());
            CollectReceiveStat(msg.MType.ToString(), msg.DataLength);

            // TODO: Consider doing the data unpacking on a different thread than the input reader thread
            try
            {
                msg.ConvertIn(m_regionSyncModule);
            }
            catch (Exception e)
            {
                if (msg == null)
                {
                    m_log.ErrorFormat("{0} Exception converting msg: NULL MESSAGE: {1}", LogHeader, e);
                }
                else
                {
                    m_log.ErrorFormat("{0} Exception converting msg: type={1},len={2}: {3}", LogHeader, msg.MType, msg.DataLength, e);
                }
            }

            // TODO: Consider doing the message processing on a different thread than the input reader thread
            try
            {
                msg.HandleIn(m_regionSyncModule);
            }
            catch (Exception e)
            {
                if (msg == null)
                {
                    m_log.ErrorFormat("{0} Exception handling msg: NULL MESSAGE: {1}", LogHeader, e);
                }
                else
                {
                    m_log.ErrorFormat("{0} Exception handling msg: type={1},len={2}: {3}", LogHeader, msg.MType, msg.DataLength, e);
                }
            }

            // If this is an initialization message, print out info and start stats gathering if initialized enough
            if (msg.MType == SyncMsg.MsgType.RegionName || msg.MType == SyncMsg.MsgType.ActorID)
            {
                switch (msg.MType)
                {
                    case SyncMsg.MsgType.RegionName:
                        m_log.DebugFormat("Syncing to region \"{0}\"", otherSideRegionName);
                        break;
                    case SyncMsg.MsgType.ActorID:
                        m_log.DebugFormat("Syncing to actor \"{0}\"", otherSideActorID);
                        break;
                }
                if (otherSideRegionName != null && otherSideActorID != null)
                    StartCollectingStats();
            }
        }
예제 #5
0
 public bool KeepAlive(SyncMsg msg)
 {
     TimeSpan timePassed = DateTime.Now - m_lastSendTime;
     if (timePassed.TotalMilliseconds > KeepAliveMaxInterval)
     {
         ImmediateOutgoingMsg(msg);
         return true;
     }
     else
         return false;
 }
예제 #6
0
        // Queue the outgoing message so it it sent "now" and before update messages.
        public void ImmediateOutgoingMsg(SyncMsg msg)
        {
            msg.LogTransmission(this);

            // The new way is to add a first queue and to place this message at the front.
            m_outQ.QueueMessageFirst(msg);

            if (m_collectingStats)
                currentQueue.Event(1);
        }
예제 #7
0
 /// <summary>
 /// Enqueue update of an object/avatar into the outgoing queue, and return right away
 /// </summary>
 /// <param name="id">UUID of the object/avatar</param>
 /// <param name="update">the update infomation in byte format</param>
 public void EnqueueOutgoingUpdate(UUID id, SyncMsg update)
 {
     // m_log.DebugFormat("{0} Enqueue msg {1}", LogHeader, update.ToString());
     update.LogTransmission(this);
     // Enqueue is thread safe
     bool actuallyQueued = m_outQ.Enqueue(id, update);
     /* BEGIN DEBUG
     if (!actuallyQueued)
     {
         SyncMsgUpdatedProperties upd = update as SyncMsgUpdatedProperties;
         m_log.DebugFormat("{0} EnqueueOutgoingUpdate. Multiple update. UUID={1}, prop={2}",
                             LogHeader, upd.Uuid, upd.PropsAsString());
     }
      END DEBUG */
     if (actuallyQueued && m_collectingStats)
         currentQueue.Event(1);
 }