// PercentageStat is a basic stat plus percent calc public override OSDMap ToOSDMap() { // Get the foundational instance OSDMap map = base.ToOSDMap(); map["StatType"] = "PercentageStat"; map.Add("Antecedent", OSD.FromLong(Antecedent)); map.Add("Consequent", OSD.FromLong(Consequent)); return(map); }
// Get a copy of the current histogram public OSDArray GetHistogramAsOSDArray() { OSDArray ret = new OSDArray(m_numBuckets); lock (histoLock) { int indx = m_lastBucket + 1; for (int ii = 0; ii < m_numBuckets; ii++, indx++) { if (indx >= m_numBuckets) indx = 0; ret[ii] = OSD.FromLong(m_histogram[indx]); } } return ret; }
public override OSDMap OReport(string uptime, string version) { double elapsedHours = (DateTime.Now - startTime).TotalHours; if (elapsedHours <= 0) { elapsedHours = 1; } // prevent divide by zero long assetRequestsTodayPerHour = (long)Math.Round(AssetRequestsToday / elapsedHours); long assetRequestsYesterdayPerHour = (long)Math.Round(AssetRequestsYesterday / 24.0); OSDMap ret = new OSDMap(); ret.Add("AssetRequestsToday", OSD.FromLong(AssetRequestsToday)); ret.Add("AssetRequestsTodayPerHour", OSD.FromLong(assetRequestsTodayPerHour)); ret.Add("AssetRequestsNotFoundToday", OSD.FromLong(AssetRequestsNotFoundToday)); ret.Add("AssetRequestsYesterday", OSD.FromLong(AssetRequestsYesterday)); ret.Add("AssetRequestsYesterdayPerHour", OSD.FromLong(assetRequestsYesterdayPerHour)); ret.Add("AssetRequestsNotFoundYesterday", OSD.FromLong(assetRequestsNotFoundYesterday)); return(ret); }
/// <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); } }
/// <summary> /// Convert the value of the given property to OSD type. /// </summary> /// <param name="property"></param> /// <returns></returns> public OSDArray ToOSDArray() { //DebugLog.WarnFormat("[SYNCED PROPERTY] ToOSDArray called for property {0}", Property.ToString()); lock (m_lock) { OSDArray propertyData = new OSDArray(); propertyData.Add(OSD.FromInteger((uint)Property)); propertyData.Add(OSD.FromLong(LastUpdateTimeStamp)); propertyData.Add(OSD.FromString(LastUpdateSyncID)); OSD value = null; switch (Property) { /////////////////////////////////////// //SOP properties with complex structure /////////////////////////////////////// case SyncableProperties.Type.AgentCircuitData: case SyncableProperties.Type.AvatarAppearance: value = (OSDMap)LastUpdateValue; break; case SyncableProperties.Type.Animations: value = (OSDArray)LastUpdateValue; break; //////////////////////////// // Integer/enum type properties //////////////////////////// case SyncableProperties.Type.CreationDate: // int case SyncableProperties.Type.LinkNum: // int case SyncableProperties.Type.OwnershipCost: // int case SyncableProperties.Type.SalePrice: // int case SyncableProperties.Type.ScriptAccessPin: // int case SyncableProperties.Type.AggregateScriptEvents: // enum case SyncableProperties.Type.Flags: // enum case SyncableProperties.Type.LocalFlags: // enum case SyncableProperties.Type.PresenceType: // enum value = OSD.FromInteger((int)LastUpdateValue); break; //////////////////////////// // Byte type properties //////////////////////////// case SyncableProperties.Type.ClickAction: case SyncableProperties.Type.Material: case SyncableProperties.Type.ObjectSaleType: value = OSD.FromInteger((byte)LastUpdateValue); break; //////////////////////////// // Boolean type properties //////////////////////////// case SyncableProperties.Type.AllowedDrop: case SyncableProperties.Type.IsAttachment: case SyncableProperties.Type.PassTouches: case SyncableProperties.Type.VolumeDetectActive: case SyncableProperties.Type.Flying: case SyncableProperties.Type.IsColliding: case SyncableProperties.Type.CollidingGround: case SyncableProperties.Type.Kinematic: case SyncableProperties.Type.IsSelected: case SyncableProperties.Type.AllowMovement: value = OSD.FromBoolean((bool)LastUpdateValue); break; //////////////////////////// // Vector3 type properties //////////////////////////// case SyncableProperties.Type.AngularVelocity: case SyncableProperties.Type.AttachedPos: case SyncableProperties.Type.GroupPosition: case SyncableProperties.Type.OffsetPosition: case SyncableProperties.Type.Scale: case SyncableProperties.Type.SitTargetPosition: case SyncableProperties.Type.SitTargetPositionLL: case SyncableProperties.Type.SOP_Acceleration: case SyncableProperties.Type.Velocity: case SyncableProperties.Type.Force: case SyncableProperties.Type.PA_Acceleration: case SyncableProperties.Type.PA_Velocity: case SyncableProperties.Type.PA_TargetVelocity: case SyncableProperties.Type.Position: case SyncableProperties.Type.RotationalVelocity: case SyncableProperties.Type.Size: case SyncableProperties.Type.Torque: case SyncableProperties.Type.AbsolutePosition: value = OSD.FromVector3((Vector3)LastUpdateValue); break; //////////////////////////// // UUID type properties //////////////////////////// case SyncableProperties.Type.AttachedAvatar: case SyncableProperties.Type.CollisionSound: case SyncableProperties.Type.CreatorID: case SyncableProperties.Type.FolderID: case SyncableProperties.Type.GroupID: case SyncableProperties.Type.LastOwnerID: case SyncableProperties.Type.OwnerID: case SyncableProperties.Type.Sound: value = OSD.FromUUID((UUID)LastUpdateValue); break; //////////////////////////// // UInt type properties //////////////////////////// case SyncableProperties.Type.LocalId: case SyncableProperties.Type.AttachmentPoint: case SyncableProperties.Type.BaseMask: case SyncableProperties.Type.Category: case SyncableProperties.Type.EveryoneMask: case SyncableProperties.Type.GroupMask: case SyncableProperties.Type.InventorySerial: case SyncableProperties.Type.NextOwnerMask: case SyncableProperties.Type.OwnerMask: case SyncableProperties.Type.AgentControlFlags: case SyncableProperties.Type.ParentId: value = OSD.FromUInteger((uint)LastUpdateValue); break; //////////////////////////// // Float type properties //////////////////////////// case SyncableProperties.Type.CollisionSoundVolume: case SyncableProperties.Type.Buoyancy: value = OSD.FromReal((float)LastUpdateValue); break; //////////////////////////// // String type properties //////////////////////////// case SyncableProperties.Type.Color: case SyncableProperties.Type.CreatorData: case SyncableProperties.Type.Description: case SyncableProperties.Type.MediaUrl: case SyncableProperties.Type.Name: case SyncableProperties.Type.RealRegion: case SyncableProperties.Type.Shape: case SyncableProperties.Type.SitName: case SyncableProperties.Type.TaskInventory: case SyncableProperties.Type.Text: case SyncableProperties.Type.TouchName: value = OSD.FromString((string)LastUpdateValue); break; //////////////////////////// // byte[] (binary data) type properties //////////////////////////// case SyncableProperties.Type.ParticleSystem: case SyncableProperties.Type.TextureAnimation: value = OSD.FromBinary((byte[])LastUpdateValue); break; //////////////////////////// // Quaternion type properties //////////////////////////// case SyncableProperties.Type.RotationOffset: case SyncableProperties.Type.SitTargetOrientation: case SyncableProperties.Type.SitTargetOrientationLL: case SyncableProperties.Type.Orientation: case SyncableProperties.Type.Rotation: value = OSD.FromQuaternion((Quaternion)LastUpdateValue); break; default: DebugLog.WarnFormat("[SYNCED PROPERTY] ToOSDArray: No handler for property {0} ", Property); break; } propertyData.Add(value); return(propertyData); } }