private HttpStatusCode CancelCrossing(CrossingRequest cross)
 {
     m_crossLock.EnterUpgradeableReadLock();
     try
     {
         if (m_crossings.ContainsKey(cross.uuid))
         {
             m_crossLock.EnterWriteLock();
             try
             {
                 m_crossings.Remove(cross.uuid);
                 return(HttpStatusCode.OK);
             }
             finally
             {
                 m_crossLock.ExitWriteLock();
             }
         }
         else
         {
             return(HttpStatusCode.NotFound);
         }
     }
     finally
     {
         m_crossLock.ExitUpgradeableReadLock();
     }
 }
        /// <summary>
        /// Used for cancelling a crossing underway. Should be used before the crossing message starts propagating.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="actorRequest"></param>
        private void HandleCancelCrossing(HttpListenerContext context, HttpListenerRequest actorRequest)
        {
            StreamReader    actorReader  = new StreamReader(actorRequest.InputStream);
            XmlSerializer   deserializer = new XmlSerializer(typeof(CrossingRequest));
            CrossingRequest cross        = (CrossingRequest)deserializer.Deserialize(actorReader);
            HttpStatusCode  status       = CancelCrossing(cross);

            HttpListenerResponse actorResponse = context.Response;

            actorResponse.StatusCode = (int)status;
            actorResponse.Close();
        }
        /// <summary>
        /// Check if the requested crossing moves the object out of an active quark to non-active quark.
        /// If not, a simple udpdate property could be used instead, with the added curquark and prevquark info.
        /// </summary>
        /// <param name="cross"></param>
        /// <returns></returns>
        private HttpStatusCode ValidateCrossing(CrossingRequest cross)
        {
            bool             crossing         = false;
            HashSet <string> subscribedActors = new HashSet <string>();

            subscribedActors.UnionWith(m_quarkSubscriptions[cross.prevQuark].ActiveSubscribers);
            subscribedActors.UnionWith(m_quarkSubscriptions[cross.curQuark].ActiveSubscribers);

            foreach (string strActor in subscribedActors)
            {
                if (!(m_actor[strActor].ActiveQuarks.Contains(cross.prevQuark) && m_actor[strActor].ActiveQuarks.Contains(cross.curQuark)))
                {
                    crossing = true;
                    break;
                }
            }
            if (crossing == false)
            {
                return(HttpStatusCode.OK);
            }

            // Crossing is already underway for this object
            if (m_crossings.ContainsKey(cross.uuid))
            {
                // If incoming crossing is older than current, discard, return forbidden.
                // This could happen if two crossings were generated while one is in progress. The crossing with timestamp
                // in between will simply be overwritten
                if (cross.timestamp < m_crossings[cross.uuid].cross.timestamp)
                {
                    return(HttpStatusCode.Forbidden);
                }
                else if (cross.timestamp == m_crossings[cross.uuid].cross.timestamp)
                {
                    return(HttpStatusCode.Forbidden);
                }
                else
                {
                    // Tell actor there was a conflict. Actor will wait until it receives the first crossing message before trying again.
                    // Note: This could be made more efficient if it's possible to remember the cross requests and only accept the next earliest crossing.
                    return(HttpStatusCode.Conflict);
                }
            }
            else
            {
                return(HttpStatusCode.Created);
            }
        }
        /// <summary>
        /// Handles a quark crossing request. Checks to see if the request is possible, and returns true or false based on
        /// the validity of the crossing to the actor who requested. This is performed in 3 steps:
        /// Step 1: Tell root to be ready to receive crossing requests for the object
        /// Root will also do sanity checks (e.g. object was deleted before crossing), so checking actorStatus code
        /// is important.
        /// Step 2: Root provides URL for uploading updated properties and for downloading said object.
        /// Step 3: Tell actor about the URL where it may contact the root directly.
        /// TODO: This can be optimized if we are allowed to remember or calculate the URL. We could respond immediately with the URL
        /// and the actor would keep trying it until root accepts it. For now, we avoid concurrency.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="actorRequest"></param>
        private void HandleCrossing(HttpListenerContext context, HttpListenerRequest actorRequest)
        {
            StreamReader    actorReader = new StreamReader(actorRequest.InputStream);
            XmlSerializer   deserializer = new XmlSerializer(typeof(CrossingRequest));
            CrossingRequest cross = (CrossingRequest)deserializer.Deserialize(actorReader);
            QuarkPublisher  curQp = null, prevQp = null;
            string          url = "";
            HttpStatusCode  status;

            m_crossLock.EnterReadLock();
            try
            {
                m_log.InfoFormat("{0}: Handling Crossing. Time: {1}", LogHeader, DateTime.Now.Ticks);
                if (m_quarkSubscriptions.TryGetValue(cross.curQuark, out curQp) && m_quarkSubscriptions.TryGetValue(cross.prevQuark, out prevQp))
                {
                    if (curQp.RootActorID != prevQp.RootActorID)
                    {
                        // TODO: Inter-root communication
                    }
                    else
                    {
                        // Actor's response variables
                        HttpListenerResponse actorResponse = context.Response;
                        Stream actorOutput = actorResponse.OutputStream;

                        // Root's request variables
                        RootInfo       root        = (RootInfo)m_actor[curQp.RootActorID];
                        HttpWebRequest rootRequest = (HttpWebRequest)WebRequest.Create("http://" + root.quarkAddress + "/cross/");
                        rootRequest.Credentials = CredentialCache.DefaultCredentials;
                        rootRequest.Method      = "POST";
                        rootRequest.ContentType = "text/json";
                        Stream rootOutput = rootRequest.GetRequestStream();

                        status = ValidateCrossing(cross);
                        if (status != HttpStatusCode.Created)
                        {
                            actorResponse.StatusCode = (int)status;
                            actorOutput.Close();
                            actorResponse.Close();
                            return;
                        }
                        // From here on, I might have to write, make sure we only do one of these at a time.
                        // Can't go in UpgradeableLock with a ReadLock, so let go first.
                        m_crossLock.ExitReadLock();
                        m_crossLock.EnterUpgradeableReadLock();
                        try
                        {
                            // First we double check nothing changed while we were waiting for the lock, and we are still valid to cross.
                            status = ValidateCrossing(cross);
                            if (status != HttpStatusCode.Created)
                            {
                                actorResponse.StatusCode = (int)status;
                                actorOutput.Close();
                                actorResponse.Close();
                                return;
                            }

                            // Step 1: Tell root to be ready to receive crossing requests for the object
                            // Root will also do sanity checks (e.g. object was deleted before crossing), so checking actorStatus code
                            // is important.
                            OSDMap DataMap = new OSDMap();
                            DataMap["uuid"] = OSD.FromUUID(cross.uuid);
                            DataMap["pq"]   = OSD.FromString(cross.prevQuark);
                            DataMap["cq"]   = OSD.FromString(cross.curQuark);
                            DataMap["ts"]   = OSD.FromLong(cross.timestamp);

                            string encodedMap     = OSDParser.SerializeJsonString(DataMap, true);
                            byte[] rootData       = System.Text.Encoding.ASCII.GetBytes(encodedMap);
                            int    rootDataLength = rootData.Length;
                            rootOutput.Write(rootData, 0, rootDataLength);
                            rootOutput.Close();

                            // Step 2: Root provides URL for uploading updated properties and for downloading said object.
                            HttpWebResponse response = (HttpWebResponse)rootRequest.GetResponse();
                            if (HttpStatusCode.OK == response.StatusCode)
                            {
                                m_crossLock.EnterWriteLock();
                                try
                                {
                                    m_crossings[cross.uuid]       = new CurrentCrossings();
                                    m_crossings[cross.uuid].cross = cross;
                                    m_crossings[cross.uuid].actors.UnionWith(m_quarkSubscriptions[cross.prevQuark].GetAllQuarkSubscribers());
                                    m_crossings[cross.uuid].actors.UnionWith(m_quarkSubscriptions[cross.curQuark].GetAllQuarkSubscribers());
                                    // Remove the starting actor from the list of actors to ACK.
                                    m_crossings[cross.uuid].actors.Remove(cross.actorID);
                                    m_crossings[cross.uuid].rootHandler = root;
                                }
                                finally
                                {
                                    m_crossLock.ExitWriteLock();
                                }
                                Stream       respData   = response.GetResponseStream();
                                StreamReader rootReader = new StreamReader(respData);
                                url = rootReader.ReadToEnd();
                                m_log.WarnFormat("{0}: Got URL for object request from server: {1}", LogHeader, url);
                                if (url.Length > 0)
                                {
                                    // Step 3: Tell actor about the URL where it may contact the root directly.
                                    // TODO: This can be optimized if we are allowed to remember or calculate the URL. We could respond immediately with the URL
                                    // and the actor would keep trying it until root accepts it. For now, we avoid concurrency.
                                    actorResponse.StatusCode = (int)HttpStatusCode.Created;
                                    byte[] actorUrlData       = System.Text.Encoding.ASCII.GetBytes(url);
                                    int    actorUrlDataLength = actorUrlData.Length;
                                    actorOutput.Write(actorUrlData, 0, actorUrlDataLength);
                                    actorOutput.Close();
                                    actorResponse.Close();
                                }
                                else
                                {
                                    m_log.ErrorFormat("{0}: Received empty URL from Root", LogHeader);
                                }
                            }
                            else
                            {
                                m_log.ErrorFormat("{0}: Failed to request crossing from root. Error Code: {1}", LogHeader, response.StatusCode);
                            }
                        }
                        finally
                        {
                            m_crossLock.ExitUpgradeableReadLock();
                        }
                    }
                }
            }
            catch (Exception e)
            {
                m_log.ErrorFormat("{0}: Failed to request crossing from root and forward to actor. Exception: {1}\n{2}", LogHeader, e, e.StackTrace);
            }
            finally
            {
                if (m_crossLock.IsReadLockHeld)
                {
                    m_crossLock.ExitReadLock();
                }
            }
        }
        /// <summary>
        /// Used for actors ACKing received crossed messages. Once all expected actors have ACKEd the crossing message,
        /// the Sync Service informs the root actor to push a crossing finished.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="request"></param>
        private void HandleAckCrossing(HttpListenerContext context, HttpListenerRequest request)
        {
            m_log.InfoFormat("{0}: HandleAckCrossing", LogHeader);
            StreamReader     actorReader  = new StreamReader(request.InputStream);
            XmlSerializer    deserializer = new XmlSerializer(typeof(CrossingFinished));
            CrossingFinished cf           = (CrossingFinished)deserializer.Deserialize(actorReader);
            string           ackActorID   = cf.ackActorID;
            CrossingRequest  cross        = cf.cross;
            RootInfo         root         = null;

            bool allAcksReceived = false;

            try
            {
                HttpStatusCode actorStatus;
                m_crossings[cross.uuid].actors.Remove(ackActorID);
                m_log.InfoFormat("{0}: Ack received from {1}, {2} acks remaining.", LogHeader, ackActorID, m_crossings[cross.uuid].actors.Count);
                if (m_crossings[cross.uuid].actors.Count == 0)
                {
                    root            = m_crossings[cross.uuid].rootHandler;
                    actorStatus     = CancelCrossing(cross);
                    allAcksReceived = true;
                }
                else
                {
                    actorStatus = HttpStatusCode.OK;
                }

                HttpListenerResponse actorResponse = context.Response;
                actorResponse.StatusCode = (int)actorStatus;
                actorResponse.Close();

                if (allAcksReceived)
                {
                    if (actorStatus == HttpStatusCode.OK)
                    {
                        m_log.InfoFormat("{0}: Informing root that crossing is finished", LogHeader);
                        // Now tell root to tell every actor that the crossing is finnished!
                        // Root's request variables
                        HttpWebRequest rootRequest = (HttpWebRequest)WebRequest.Create("http://" + root.quarkAddress + "/finished/");
                        rootRequest.Credentials = CredentialCache.DefaultCredentials;
                        rootRequest.Method      = "POST";
                        rootRequest.ContentType = "text/json";
                        Stream rootOutput = rootRequest.GetRequestStream();

                        OSDMap DataMap = new OSDMap();
                        DataMap["uuid"] = OSD.FromUUID(cross.uuid);
                        DataMap["ts"]   = OSD.FromLong(cross.timestamp);

                        string encodedMap     = OSDParser.SerializeJsonString(DataMap, true);
                        byte[] rootData       = System.Text.Encoding.ASCII.GetBytes(encodedMap);
                        int    rootDataLength = rootData.Length;
                        rootOutput.Write(rootData, 0, rootDataLength);
                        rootOutput.Close();

                        // Check if everything went OK
                        try
                        {
                            HttpWebResponse response = (HttpWebResponse)rootRequest.GetResponse();
                            if (response.StatusCode == HttpStatusCode.OK)
                            {
                                m_log.InfoFormat("{0}: Successfully finished crossing.", LogHeader);
                                return;
                            }
                        }
                        catch (WebException we)
                        {
                            var resp = we.Response as HttpWebResponse;
                            m_log.ErrorFormat("{0}: Sync Crossing finished fail with actorStatus code: {1}", LogHeader, resp.StatusCode);
                        }
                    }
                    else
                    {
                        throw new Exception("Could not find the object in the crossing dictionary");
                    }
                }
            }
            catch (Exception e)
            {
                m_log.ErrorFormat("{0}: Unkown exception while handling ACK from actor. Exception {1}", LogHeader, e);
            }
        }