<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.secondlife.com/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Poppy+Linden</id>
	<title>Second Life Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.secondlife.com/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Poppy+Linden"/>
	<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/wiki/Special:Contributions/Poppy_Linden"/>
	<updated>2026-06-28T09:28:08Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.1</generator>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Asset_Wrapper&amp;diff=929852</id>
		<title>Asset Wrapper</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Asset_Wrapper&amp;diff=929852"/>
		<updated>2010-05-27T00:48:04Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Reference !! extension !! id !! mime type !! LSL&lt;br /&gt;
|-&lt;br /&gt;
{{Asset Type&lt;br /&gt;
|wiki_page=Asset Wrapper&lt;br /&gt;
|extension=asset&lt;br /&gt;
|id=unassigned&lt;br /&gt;
|mime_type=application/vnd.ll.asset&lt;br /&gt;
}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Requirements =&lt;br /&gt;
A simple container format has been invented to wrap assets in a somewhat flexible and concise manner. Specifically we needed a format which:&lt;br /&gt;
&lt;br /&gt;
* provides features for attribution.&lt;br /&gt;
* the meta-data needs to be in the first network packet. (specifically a requirement of texture attribution)&lt;br /&gt;
* supports arbitrary meta-data.&lt;br /&gt;
* introduces minimal byte overhead and does not require increased payload size.&lt;br /&gt;
&lt;br /&gt;
Other container formats were considered but rejected for one of:&lt;br /&gt;
&lt;br /&gt;
* too much overhead&lt;br /&gt;
* poor cross-language and cross-platform support&lt;br /&gt;
* geared for streaming content rather than fixed assets.&lt;br /&gt;
&lt;br /&gt;
= Specification =&lt;br /&gt;
The asset type is an [[LLSD]] array of arrays. Each sub-array will contain a [[LLSD]] map of meta-data followed by the data segment. Asset files are serialized in binary [[LLSD]] unless a header in asset file indicates otherwise. &lt;br /&gt;
&lt;br /&gt;
The asset file:&lt;br /&gt;
* &#039;&#039;&#039;must&#039;&#039;&#039; be an array of arrays.&lt;br /&gt;
* &#039;&#039;&#039;should&#039;&#039;&#039; be binary&lt;br /&gt;
* &#039;&#039;&#039;may not&#039;&#039;&#039; have a header to indicate binary serialization&lt;br /&gt;
* &#039;&#039;&#039;must&#039;&#039;&#039; indicate if they are not serialized in the binary format in the first line of the file.&lt;br /&gt;
* &#039;&#039;&#039;should not&#039;&#039;&#039; contain more than one segment of a particular content-type.&lt;br /&gt;
&lt;br /&gt;
The meta-data segment:&lt;br /&gt;
* &#039;&#039;&#039;must&#039;&#039;&#039; contain the &#039;content-type&#039; of the data.&lt;br /&gt;
* &#039;&#039;&#039;should&#039;&#039;&#039; contain a &#039;creation-date&#039; of the data. &lt;br /&gt;
* &#039;&#039;&#039;should not&#039;&#039;&#039; contain a &#039;content-length&#039;.&lt;br /&gt;
&lt;br /&gt;
= examples =&lt;br /&gt;
This is a [[LLSD#Notation_Serialization|notation based]] mock-up of what an asset will actually look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[[{&#039;content-type&#039;:&#039;image/x-j2c&#039;, &lt;br /&gt;
   &#039;creation-date&#039;:&#039;2007-01-01T00:01:00Z&#039;, &lt;br /&gt;
   &#039;creator-id&#039;:u3c115e51-04f4-523c-9fa6-98aff1034730}, &lt;br /&gt;
 &amp;lt;BINARY IMAGE DATA&amp;gt;]] &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example shows two different wrapped assets. Note that the first binary blob is serialized as raw data and the curly braces are inside the 160 bytes of content. The vnd.ll.lslbyte presented here is a (somewhat truncated) base64 encoding of the byte code generated by compiling the related vnd.ll.lsltext.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
  [&lt;br /&gt;
    {&lt;br /&gt;
      &#039;content-type&#039;:&#039;application/vnd.ll.lsltext&#039;, &lt;br /&gt;
      &#039;creation-date&#039;:&#039;2007-03-15T18:30:00Z&#039;, &lt;br /&gt;
      &#039;creator-id&#039;:u3c115e51-04f4-523c-9fa6-98aff1034730&lt;br /&gt;
    },&lt;br /&gt;
    b(160)&amp;quot;default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSay(0, &amp;quot;Hello, Avatar!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    touch_start(integer total_number)&lt;br /&gt;
    {&lt;br /&gt;
        llSay(0, &amp;quot;Touched.&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  [&lt;br /&gt;
    {&lt;br /&gt;
      &#039;content-type&#039;:&#039;application/vnd.ll.lslbyte&#039;, &lt;br /&gt;
      &#039;creation-date&#039;:&#039;2007-03-15T18:30:18Z&#039;, &lt;br /&gt;
      &#039;creator-id&#039;:u3c115e51-04f4-523c-9fa6-98aff1034730&lt;br /&gt;
    },&lt;br /&gt;
    b64&amp;quot;AABAAAAAAAAAAAIAAAA//wAAP/8AAADgAAAA5wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&lt;br /&gt;
AABkAAAAZAAAAAAAAAAAAAAAZAAAAAAAAAABAAAAAAAAAAAAAAAAAAAABQAAAAEAAAAQAAAAAAAA&lt;br /&gt;
AAUAAAAFAAAAABAAAAAAAAAAPgAAAAQAAAAFAGNbXgAAAABgSGVsbG8sIEF2YXRhciEAZgAAAABc&lt;br /&gt;
XgAAAAhwEQjRABeVAAAABQBjW14AAAAAYFRvdWNoZWQuAGYAAAAAXF4AAAAIcBEI0QAXAZUAAEAA&lt;br /&gt;
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;quot; &lt;br /&gt;
  ]&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Gestures&amp;diff=929842</id>
		<title>Gestures</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Gestures&amp;diff=929842"/>
		<updated>2010-05-27T00:47:47Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{KBmaster}}&lt;br /&gt;
{{Navbox/Controls}}&lt;br /&gt;
&lt;br /&gt;
== What are gestures? ==&lt;br /&gt;
&lt;br /&gt;
Gestures are an inventory item type (shown as [[Image:Inv_item_gesture.png]]) that allow you to &#039;&#039;&#039;create a [http://en.wikipedia.org/wiki/Macro_%28computer_science%29 series of steps] which trigger your avatar to animate, play sounds, and emit text chat&#039;&#039;&#039;. These can be used for practical purposes or to amuse friends. For example, a cartoon &amp;quot;Squish!&amp;quot; noise accompanied by your avatar falling down. In Second Life [[culture]], many gestures are openly circulated like [http://knowyourmeme.com/ memes], as they add a lot of spark to social situations.&lt;br /&gt;
&lt;br /&gt;
Gestures can be triggered with:&lt;br /&gt;
&lt;br /&gt;
* Keyboard shortcuts&lt;br /&gt;
* Text chat words/phrases&lt;br /&gt;
* Voice volume.&lt;br /&gt;
&lt;br /&gt;
== Where do I get gestures? ==&lt;br /&gt;
&lt;br /&gt;
There are a variety of sample gestures in your inventory&#039;s Library folder. Search your inventory for &amp;quot;&amp;lt;code&amp;gt;gesture&amp;lt;/code&amp;gt;&amp;quot; and scroll down.&lt;br /&gt;
&lt;br /&gt;
You can also [https://www.xstreetsl.com/modules.php?name=Marketplace&amp;amp;CategoryID=233 purchase many readymade gestures at Xstreet]. [[:Category:Xstreet|Learn more about Xstreet.]]&lt;br /&gt;
&lt;br /&gt;
== How do I make a gesture? ==&lt;br /&gt;
&lt;br /&gt;
Many variations exist, but here&#039;s a simple exercise to get you started.&lt;br /&gt;
&lt;br /&gt;
# Click the &#039;&#039;&#039;Inventory&#039;&#039;&#039; button in the bottom right of the Viewer window to open the Inventory window.&lt;br /&gt;
# Right-click the &#039;&#039;&#039;Gestures&#039;&#039;&#039; folder (if you don&#039;t see it, open the &#039;&#039;&#039;My Inventory&#039;&#039;&#039; folder) and select &#039;&#039;&#039;New Gesture&#039;&#039;&#039; from the context menu.&lt;br /&gt;
# Type in a unique name for the gesture. You can always change this later. The Gesture editor window appears:&lt;br /&gt;
#: [[File:Gesture_editor_window.png|640px]]&lt;br /&gt;
# In the Gesture window, under &#039;&#039;&#039;Steps&#039;&#039;&#039;, there are example steps. Click &#039;&#039;&#039;Preview&#039;&#039;&#039; button to see and hear what the gesture does as a whole. For example:&lt;br /&gt;
## Click the first step, &#039;&#039;&#039;Start Animation: Wave&#039;&#039;&#039;.&lt;br /&gt;
## Click the dropdown below and select a different animation, like &#039;&#039;&#039;Afraid&#039;&#039;&#039;. The steps update to show this.&lt;br /&gt;
## Click &#039;&#039;&#039;Preview&#039;&#039;&#039; again.&lt;br /&gt;
# Add and remove steps using the &#039;&#039;&#039;Add &amp;gt;&amp;gt;&#039;&#039;&#039; and &#039;&#039;&#039;Remove&#039;&#039;&#039; buttons.&lt;br /&gt;
# Change the order of the steps by selecting a step, then clicking &#039;&#039;&#039;Move Up&#039;&#039;&#039; and &#039;&#039;&#039;Move Down&#039;&#039;&#039;.&lt;br /&gt;
# As-desired, enter a &#039;&#039;&#039;Trigger&#039;&#039;&#039; and/or &#039;&#039;&#039;Shortcut Key&#039;&#039;&#039;. Changing the &#039;&#039;&#039;Description&#039;&#039;&#039; is optional, but you should at least have one way to easily trigger the gesture.&lt;br /&gt;
# Make sure &#039;&#039;&#039;Active&#039;&#039;&#039; is checked. Gestures must be active to be triggered.&lt;br /&gt;
# When you&#039;re done, click &#039;&#039;&#039;Save&#039;&#039;&#039; button and close the gesture window. Test the trigger or shortcut key.&lt;br /&gt;
&lt;br /&gt;
You should also look at existing gestures to understand how to construct them from scratch.&lt;br /&gt;
&lt;br /&gt;
Since gestures are best shown in action, watch this video tutorial to learn more:&lt;br /&gt;
&lt;br /&gt;
{{KBvideo|4168991}}&lt;br /&gt;
&lt;br /&gt;
Also, did you know gestures can be used as a productivity tool? With text chat macros, you can type in abbreviations which expand into phrases, or even paragraphs.&lt;br /&gt;
&lt;br /&gt;
{{KBvideo|4242104}}&lt;br /&gt;
&lt;br /&gt;
== How do I see all my active gestures? ==&lt;br /&gt;
&lt;br /&gt;
There are several ways:&lt;br /&gt;
&lt;br /&gt;
* Search your inventory for &amp;quot;&amp;lt;code&amp;gt;(active)&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
* There&#039;s a dropdown called &#039;&#039;&#039;Gestures&#039;&#039;&#039; to the right of your chat bar. Click it to see gestures sorted by text trigger.&lt;br /&gt;
* Go to &#039;&#039;&#039;View&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Active Gestures&#039;&#039;&#039;. A special window opens that shows you the trigger, key, and name for all your activated gestures.&lt;br /&gt;
&lt;br /&gt;
== Why don&#039;t my gestures work? ==&lt;br /&gt;
&lt;br /&gt;
You&#039;re either not using the correct trigger or they&#039;re deactivated. Gestures &#039;&#039;must&#039;&#039; be activated to be triggered. Activated gestures appear in &#039;&#039;&#039;bold&#039;&#039;&#039; in your inventory and have &amp;quot;(active)&amp;quot; next to their names.&lt;br /&gt;
&lt;br /&gt;
There are a few ways to activate gestures:&lt;br /&gt;
&lt;br /&gt;
* Right-click a gesture and choose &#039;&#039;&#039;Activate&#039;&#039;&#039;.&lt;br /&gt;
** You can also Shift-click a range of gestures, then choose &#039;&#039;&#039;Activate&#039;&#039;&#039; to activate multiple gestures at once.&lt;br /&gt;
* Drag a gesture from your inventory onto your avatar to activate it.&lt;br /&gt;
** This also works with folders containing gestures. It works similar to wearing clothes or attaching objects — active gestures are effectively &amp;quot;worn&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Conversely, you can follow the same steps, then choose &#039;&#039;&#039;Deactivate&#039;&#039;&#039; to turn off gestures.&lt;br /&gt;
&lt;br /&gt;
== Why do I sound like a woman if I have a male avatar (and vice-versa)? ==&lt;br /&gt;
&lt;br /&gt;
The default gestures come in two folders, one for &#039;&#039;&#039;Male Gestures&#039;&#039;&#039; and another for &#039;&#039;&#039;Female Gestures&#039;&#039;&#039; depending on which gender you picked when you first logged into Second Life. Their steps are the same except for the sound files they reference. You can always switch to the other by as described above.&lt;br /&gt;
&lt;br /&gt;
If you have a microphone, you can record your own voice, upload sound clips, then use them in gestures for an extra-personal touch.&lt;br /&gt;
&lt;br /&gt;
== Why can&#039;t I use an animation or sound in a gesture? ==&lt;br /&gt;
&lt;br /&gt;
In other words, why doesn&#039;t an animation or sound appear in the dropdown list when you&#039;re editing a gesture?&lt;br /&gt;
&lt;br /&gt;
Check if it has full permissions. &#039;&#039;&#039;Animations and sounds must have &#039;&#039;full&#039;&#039; permissions to be included in a gesture.&#039;&#039;&#039; This is because a gesture functions like a &amp;quot;wrapper&amp;quot; that references individual animations and sounds. If an animation was no-transfer but the gesture could include it, that&#039;d be an unfair way to work around the creator&#039;s permissions. A similar case applies for non-copyable animations and sounds.&lt;br /&gt;
&lt;br /&gt;
It&#039;s true you can&#039;t do much to modify animations and sounds after uploading them aside from renaming and changing their description, but the rule still holds true.&lt;br /&gt;
&lt;br /&gt;
== Can I trigger multiple gestures in a single line of chat? ==&lt;br /&gt;
&lt;br /&gt;
No. The Viewer only reads the first trigger. If you have many actions you want to do, you can include them with multiple actions in a single gesture.&lt;br /&gt;
&lt;br /&gt;
If you want to show someone a gesture trigger, type it twice in text chat. For example, with the default &amp;quot;/bow&amp;quot; gesture activated, type: &amp;quot;&amp;lt;code&amp;gt;/bow /bow&amp;lt;/code&amp;gt;&amp;quot;. It appears as a single &amp;quot;&amp;lt;code&amp;gt;/bow&amp;lt;/code&amp;gt;&amp;quot; — other avatars see you bowing but also see the trigger.&lt;br /&gt;
&lt;br /&gt;
== How come my text trigger disappears? ==&lt;br /&gt;
&lt;br /&gt;
In the Gesture editor window, the &#039;&#039;&#039;Trigger&#039;&#039;&#039; is what&#039;s used to start the gesture, but is independent from what shows up. For example, if you have &amp;quot;&amp;lt;code&amp;gt;/wave&amp;lt;/code&amp;gt;&amp;quot; used to do a wave animation, you might want the text chat that appears to everyone else to be &amp;quot;&amp;lt;code&amp;gt;Friendly greetings!&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you want your trigger and the emitted text output (independent of further &#039;&#039;&#039;Steps&#039;&#039;&#039;) to be the same, simply enter the same text next to &#039;&#039;&#039;Trigger&#039;&#039;&#039; and &#039;&#039;&#039;Replace with&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== How do I use voice levels to trigger gestures? ==&lt;br /&gt;
&lt;br /&gt;
There exist &#039;&#039;special&#039;&#039; triggers to do this. They are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;/voicelevel1&lt;br /&gt;
/voicelevel2&lt;br /&gt;
/voicelevel3&amp;lt;/pre&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
Each basically correlates to the loudness (amplitude) of your incoming [[How_to_use_voice|voice chat]], from 1 being softest to 3 being loudest. When there are several speech gestures which share the same trigger, they&#039;re randomly shuffled to add variety.&lt;br /&gt;
&lt;br /&gt;
To get started, search your inventory for the &#039;&#039;&#039;Speech Gestures&#039;&#039;&#039; folder (which is included in the &#039;&#039;&#039;Library&#039;&#039;&#039; &amp;gt; &#039;&#039;&#039;Gestures&#039;&#039;&#039; folder), then drag that folder onto your avatar. Then, try talking on voice chat, from quiet to loud. Your avatar&#039;s arms should gesticulate more dramatically when speaking loudly, as shown here:&lt;br /&gt;
&lt;br /&gt;
{{KBvideo|4243627}}&lt;br /&gt;
&lt;br /&gt;
{{KBnote|The &#039;&#039;&#039;Speech Gestures&#039;&#039;&#039; folder may not appear copied into your own inventory until after relogging. This is a bug.}} &lt;br /&gt;
&lt;br /&gt;
Like any other gesture, you can edit a speech gesture. Leave its trigger alone, but you can change its steps. For more info, see these videos:&lt;br /&gt;
&lt;br /&gt;
{{KBvideo|4168800}}&lt;br /&gt;
&lt;br /&gt;
== Tips &amp;amp; tricks ==&lt;br /&gt;
&lt;br /&gt;
For the experienced gesture connoisseur.&lt;br /&gt;
&lt;br /&gt;
* Active gestures starting with a slash &amp;quot;&amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;&amp;quot; in the chat bar are autocompleted. Typing a preceding slash also hides the fact you&#039;re typing from others.&lt;br /&gt;
* In the Gesture editor window, default animations appear at the top of the dropdown menu and are sorted alphabetically, while custom ones appear below and are also sorted alphabetically.&lt;br /&gt;
* While you can string many steps together, there&#039;s a limit to how much can be packed into a gesture. You&#039;ll get an error message when you try to Save if you have exceeded that limit.&lt;br /&gt;
* More than one gesture can share the same trigger, meaning both &#039;&#039;&#039;Trigger&#039;&#039;&#039; and &#039;&#039;&#039;Shortcut Key&#039;&#039;&#039;, as shown with the speech gestures. Each time you use a shared trigger, it&#039;ll randomly pick one of the gestures — a great way to add life and variety. For example, if you have 4 different waving animations and trigger them all with &amp;quot;&amp;lt;code&amp;gt;/wave&amp;lt;/code&amp;gt;&amp;quot;, you can add nuances to your avatar body language.&lt;br /&gt;
* Trigger multiple gestures simultaneously to mix and mash them up.&lt;br /&gt;
* In an Animation step, the &#039;&#039;&#039;Start&#039;&#039;&#039; and &#039;&#039;&#039;Stop&#039;&#039;&#039; radio buttons are for looped animations like still poses and repetitive dances. If you don&#039;t want your avatar to groove into eternity, insert a &#039;&#039;&#039;Stop Animation&#039;&#039;&#039; step for the same animation sometime after the &#039;&#039;&#039;Start Animation&#039;&#039;&#039; one.&lt;br /&gt;
* Gestures can add emphasis for keywords. For example, if &#039;&#039;&#039;Trigger&#039;&#039;&#039; and &#039;&#039;&#039;Replace with&#039;&#039;&#039; are both &amp;quot;&amp;lt;code&amp;gt;cat&amp;lt;/code&amp;gt;&amp;quot; and you have a gesture set to play a meowing sound with an animated swipe of your hand, every time you type &amp;quot;&amp;lt;code&amp;gt;cat&amp;lt;/code&amp;gt;&amp;quot; in a sentence, you exhibit this feline behavior. Similarly, [http://en.wikipedia.org/wiki/Emoticon emoticons] can correspond with avatar body language. The Library&#039;s gesture provides many examples.&lt;br /&gt;
* Gestures can be connected to [[LSL Portal|scripts]]. If you have scripts which use channel commands like &amp;quot;&amp;lt;code&amp;gt;/1 activate&amp;lt;/code&amp;gt;, these can be triggered via gesture faster than typing the long way.&lt;br /&gt;
* See the [[Limits#Gestures|Limits]] page for some numerical limits.&lt;br /&gt;
* Share gestures you&#039;ve created with friends. It can be such a satisfying experience to trigger them one after another in a group. You know what they say about laughter being contagious!&lt;br /&gt;
** But at the same time, &#039;&#039;[http://secondlife.com/corporate/cs.php be considerate]&#039;&#039;. &#039;&#039;Don&#039;t&#039;&#039; gesture-spam others if they don&#039;t want to hear you going &amp;quot;Woooooo!&amp;quot; for the 100th time.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* &#039;&#039;&#039;Link helpful pages here!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Animations&amp;diff=929832</id>
		<title>Animations</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Animations&amp;diff=929832"/>
		<updated>2010-05-27T00:47:27Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{OSWikiFeatureNav}}&lt;br /&gt;
=== Feature Design Document ===&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
=== Functional Spec ===&lt;br /&gt;
The format uses normalized key framed quaternions stored in shorts. The format is closer to that of Poser than {{HoverText|BVH|Biovision file format for animations}}. It consists of a header that tells the viewer what morphs to set, how long the animation plays and at what priority. After that there is an array of bones with each set of positions and rotations. The position array is only used in the root bone (or you can use it to animate the HUD, course there is no default animation for the HUD so once you do, you can&#039;t get it back into the default position). Both position &amp;amp; rotations use 3 shorts (16 bits * 3 = 6 bytes) per entry. For quaternions, it regenerates the 4th value since the quaternion is normalized.&lt;br /&gt;
&lt;br /&gt;
=== Test scripts ===&lt;br /&gt;
[[Animation Test]]&lt;br /&gt;
&lt;br /&gt;
=== Discussion for future improvements ===&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
=== Relationship to other features ===&lt;br /&gt;
&amp;lt;b&amp;gt; List of features that need to be tested when this feature changes, and why. &amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Sitting]] - Make sure animations still work while sitting.&lt;br /&gt;
&lt;br /&gt;
[[Region crossing]] -  Make sure animations still work while sitting.. in vehicles.. while crossing a region boundary.&lt;br /&gt;
&lt;br /&gt;
[[Scripted permissions]] - specifically, animation permissions.&lt;br /&gt;
&lt;br /&gt;
[[llGetAnimationList]]&lt;br /&gt;
&lt;br /&gt;
[[Asset Upload]] - If animation uploading was changed, verify other uploads still work.&lt;br /&gt;
&lt;br /&gt;
=== User Guides ===&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
* [[Animation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LSO&amp;diff=929822</id>
		<title>LSO</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LSO&amp;diff=929822"/>
		<updated>2010-05-27T00:47:02Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header|ml=*}}{{RightToc}}&lt;br /&gt;
The compiled form of LSL scripts - a mostly stack-based language with a reference-counted heap and a very odd function calling convention in which the caller allocates storage for the callee&#039;s local variables. All the gory details can be found at http://www.libsecondlife.org/wiki/LSO, including some opcodes that are implemented in the interpreter but never outputted by the compiler (such as the handy DUP family of instructions for Forth-style programming, and PUSHIP/POPIP for implementing custom function calls/function pointers, jumptable-based switch statements and the like).&lt;br /&gt;
&lt;br /&gt;
It&#039;s actually a reasonably powerful instruction set in some ways, but the compiler doesn&#039;t make use of it very well. Of course, with the planned switch to [[Mono]], it&#039;s probably really not sensible to do anything with it. Besides, rumor has it that script compilation will move server-side in the near future.&lt;br /&gt;
&lt;br /&gt;
=Bytecodes=&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|style=&amp;quot;text-align: center;&amp;quot;|&#039;&#039;&#039;Argument Types&#039;&#039;&#039;&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: center;&amp;quot;|&#039;&#039;&#039;Variable type codes&#039;&#039;&#039;&lt;br /&gt;
|- vAlign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
{| {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
! Type&lt;br /&gt;
! title=&amp;quot;Size in Bytes&amp;quot; | Size&lt;br /&gt;
! &lt;br /&gt;
|-&lt;br /&gt;
| dword&lt;br /&gt;
| 4&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| short&lt;br /&gt;
| 2&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| byte&lt;br /&gt;
| 1&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| type&lt;br /&gt;
| 1&lt;br /&gt;
| upper 4 bits are type.Left &amp;lt;br/&amp;gt; lower 4 bits are type.Right&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
! Value&lt;br /&gt;
! Type&lt;br /&gt;
! title=&amp;quot;Size in Bytes&amp;quot; | Size&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| void&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| integer&lt;br /&gt;
| 4&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| float&lt;br /&gt;
| 4&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| string&lt;br /&gt;
| 4&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
! Value&lt;br /&gt;
! Type&lt;br /&gt;
! title=&amp;quot;Size in Bytes&amp;quot; | Size&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| key&lt;br /&gt;
| 4&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| vector&lt;br /&gt;
| 12&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| rotation&lt;br /&gt;
| 16&lt;br /&gt;
|-&lt;br /&gt;
| 7&lt;br /&gt;
| list&lt;br /&gt;
| 4&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
==By Task==&lt;br /&gt;
=== Pop Value ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg0 size&lt;br /&gt;
{{LSO Bytecodes/pop-value}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Duplicate Value ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
{{LSO Bytecodes/duplicate}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Store to Local ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg0 size&lt;br /&gt;
{{LSO Bytecodes/store-local}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Store to Global ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg0 size&lt;br /&gt;
{{LSO Bytecodes/store-global}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Load to Local ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg0 size&lt;br /&gt;
{{LSO Bytecodes/load-local}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Load to Global ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg0 size&lt;br /&gt;
{{LSO Bytecodes/load-global}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Push Local ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg0 size&lt;br /&gt;
{{LSO Bytecodes/push-local}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Push Global ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg0 size&lt;br /&gt;
{{LSO Bytecodes/push-global}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Push into List ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg0 size&lt;br /&gt;
{{LSO Bytecodes/push-list}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Push Zero Values ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg0 size&lt;br /&gt;
{{LSO Bytecodes/push-zeros}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg0 size&lt;br /&gt;
{{LSO Bytecodes/operators}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Jump ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg0 size&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg1 size&lt;br /&gt;
{{LSO Bytecodes/jump}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Return ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg0 size&lt;br /&gt;
{{LSO Bytecodes/return}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Stack to Heap ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg0 size&lt;br /&gt;
{{LSO Bytecodes/stack-to-heap}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Call Functions ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg0 size&lt;br /&gt;
{{LSO Bytecodes/functions}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Special Registers ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
{{LSO Bytecodes/push-register}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/pop-register}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous ===&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;|arg0 size&lt;br /&gt;
{{LSO Bytecodes/misc}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== All Bytecodes ==&lt;br /&gt;
{| class=&amp;quot;sortable&amp;quot; {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Name&lt;br /&gt;
!Value&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;{{!}}Description&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;{{!}}arg0 size&lt;br /&gt;
!class=&amp;quot;unsortable&amp;quot;{{!}}arg1 size&lt;br /&gt;
{{LSO Bytecodes/misc}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/pop-value}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/pop-register}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/duplicate}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/store-local}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/store-global}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/load-local}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/load-global}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/push-local}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/push-global}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/push-register}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/push-list}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/push-zeros}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/operators}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/jump}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/return}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/stack-to-heap}}&lt;br /&gt;
|-&lt;br /&gt;
{{LSO Bytecodes/functions}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Notecards&amp;diff=929812</id>
		<title>Notecards</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Notecards&amp;diff=929812"/>
		<updated>2010-05-27T00:46:24Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Help |Glossary=*}}&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;&#039;notecard&#039;&#039;&#039; is an [[inventory]] item containing text and/or embedded [[texture]]s, [[snapshot]]s, [[object]]s, or other notecards. Items embedded in notecards must have copy/modify/transfer [[permission]]s.&lt;br /&gt;
&lt;br /&gt;
The inventory [[icon]] for a notecard is [[Image:Inv_item_notecard.png]]. New notecards are stored in the inventory&#039;s &amp;quot;Notecards&amp;quot; folder [[Image:Inv_folder_notecard.png]] by default.&lt;br /&gt;
&lt;br /&gt;
The maximum size of a notecard is 65,536 [[byte]]s.&lt;br /&gt;
&lt;br /&gt;
==[[Open source]]==&lt;br /&gt;
The file format for a simple notecard (no embedded inventory items) looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Linden text version 1&lt;br /&gt;
{&lt;br /&gt;
LLEmbeddedItems version 1&lt;br /&gt;
{&lt;br /&gt;
count 0&lt;br /&gt;
}&lt;br /&gt;
Text length 21&lt;br /&gt;
Editing this notecard}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Scripting==&lt;br /&gt;
* [[:Category:LSL Notecard]]&lt;br /&gt;
&lt;br /&gt;
== Video tutorial ==&lt;br /&gt;
* [[Video Tutorial/Notecard attachments]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Primitive&amp;diff=929802</id>
		<title>Primitive</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Primitive&amp;diff=929802"/>
		<updated>2010-05-27T00:45:44Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Help&lt;br /&gt;
|BugFixes=&lt;br /&gt;
|Avatar=&lt;br /&gt;
|Object=&lt;br /&gt;
|LandSim=&lt;br /&gt;
|Community=&lt;br /&gt;
|Viewer=&lt;br /&gt;
|Communication=&lt;br /&gt;
|Multimedia=&lt;br /&gt;
|Navigation=&lt;br /&gt;
|Misc=&lt;br /&gt;
|Description=&lt;br /&gt;
|Wiki=&lt;br /&gt;
|Glossary=*&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Otheruses4‎|primitives|[[LSL]] related information|:Category:LSL Prim}}&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;&#039;primitive&#039;&#039;&#039;, or &#039;&#039;&#039;prim&#039;&#039;&#039;, is a single-part [[object]]. Multi-part objects will have multiple parts (&amp;quot;prims&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
In [[Second Life]], virtual physical objects such as cars, houses, jewelry, and even less obvious things like [[hair]] and [[clothing]] are made out of one or more prims. Objects made from prims are usually created in-world using the built-in [[edit window|object editing tool]]. This tool is used for all sorts of 3D modeling in Second Life, playing the same role as 3D Max, Maya, or Blender, but customized for the Second Life way of doing things. &lt;br /&gt;
&lt;br /&gt;
Each prim is represented by a set of parameters, including shape/type, [[position]], [[scale]]/size, [[rotation]], [[cut]], [[hollow]], [[twist]], [[shear]], etc. These parameters are sent from a [[server]] to the [[viewer]] running on the [[resident]]&#039;s desktop, where the local video card is used to render the visual appearance of everything. (Rendering on the server would probably create a much higher amount of network traffic.)&lt;br /&gt;
&lt;br /&gt;
The [[color]], [[texture]], [[bumpiness]], [[shininess]], and [[transparency]] of prims can also be adjusted, and images ([[textures]]) can be applied to each surface ([[face]]/side) of a prim to change its appearance. Box, cylinder, and prism prim shape types can also be made [[flexible]].&lt;br /&gt;
&lt;br /&gt;
Prims can be linked together into [[link set]]s. They can also be attached to avatars, but this process is separate from (thought similar to) linking. &lt;br /&gt;
&lt;br /&gt;
In the Viewer [[source code]], primitives are implemented in LLPrimitive, with vertex generation performed in LLVolume and rendering in LLVOVolume.&lt;br /&gt;
&lt;br /&gt;
==Shape types==&lt;br /&gt;
There are eight primitive shape types (&amp;quot;Building Block Type&amp;quot; in build tools):&lt;br /&gt;
# box: all kinds of rectangular shapes&lt;br /&gt;
# cylinder: round tables, floors, long pipes&lt;br /&gt;
# prism: a box with one very small face&lt;br /&gt;
# sphere: can be used for ellipsoids of all shapes&lt;br /&gt;
# torus: most complex among normal prims, can be modified in many exotic ways&lt;br /&gt;
# tube:  another form of hollow cylinder&lt;br /&gt;
# ring: another variant of torus&lt;br /&gt;
# [[sculpt]]ed: new as of 2007, used for highly variable organic shapes&lt;br /&gt;
&lt;br /&gt;
==Properties==&lt;br /&gt;
&lt;br /&gt;
==== Mass ====&lt;br /&gt;
&lt;br /&gt;
The [[mass]] of a prim is a function of it&#039;s volume, different prim shapes have different volumes thus different masses.&lt;br /&gt;
* [[Mass Lab]] demonstrates how different shapes have different masses.&lt;br /&gt;
&lt;br /&gt;
==== Survival ====&lt;br /&gt;
&lt;br /&gt;
The survival of properties depends upon the type of the property and what happens to the object.&lt;br /&gt;
&lt;br /&gt;
{| {{Prettytable}}&lt;br /&gt;
|+ &#039;&#039;&#039;Property survival&#039;&#039;&#039;&lt;br /&gt;
|- {{Hl2}}&lt;br /&gt;
! Property&lt;br /&gt;
! Script Set Not Running&lt;br /&gt;
! Script Removal&lt;br /&gt;
! Take unscripted and re-rez&lt;br /&gt;
! Shift-drag-copy&lt;br /&gt;
|-&lt;br /&gt;
|| [[llSitTarget|Sit Target]] || Yes || Yes || Yes || ?&lt;br /&gt;
|-&lt;br /&gt;
|| [[llParticleSystem|Particles]] || Yes || Yes || Yes || ?&lt;br /&gt;
|-&lt;br /&gt;
|| [[llSetText|Floating Text]] || Yes || Yes || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
|| [[llTargetOmega|Spin]] || Yes || No || ? || ?&lt;br /&gt;
|-&lt;br /&gt;
|| [[llCollisionSound|Collision Sound]] || Yes || Yes || ? || ?&lt;br /&gt;
|-&lt;br /&gt;
|| [[llLoopSound|Looped Sound]] || Yes || Yes || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
|| [[llSetRemoteScriptAccessPin|Remote Script Access Pin]] || Yes || Yes || ? || ?&lt;br /&gt;
|-&lt;br /&gt;
|| [[PRIM_POINT_LIGHT|Light]] || Yes || Yes || Yes || Yes&lt;br /&gt;
|-&lt;br /&gt;
|| {{LSLGC|Status}} || Yes || Yes || Yes || Yes&lt;br /&gt;
|-&lt;br /&gt;
|| [[llSetBuoyancy|Buoyancy]] &lt;br /&gt;
|| ? || No || No || ?&lt;br /&gt;
|-&lt;br /&gt;
|| [[llSetTextureAnim|Texture Animation]]&lt;br /&gt;
|| Yes || Yes || Yes || No&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
It should be noted that when a script (in an object) moves from one simulator into another while being set as &amp;quot;Not Running&amp;quot; (either by [[llSetScriptState]] or via the checkbox in the script editor) the script&#039;s state will be lost. See {{Jira|SVC-1853}} for details.&lt;br /&gt;
&lt;br /&gt;
* {{Jira|SVC-3925}}&lt;br /&gt;
* {{Jira|VWR-640}}&lt;br /&gt;
* {{Jira|SVC-1242}}&lt;br /&gt;
&lt;br /&gt;
==Materials==&lt;br /&gt;
There are seven primitive [[material]] types that determine things like friction and default [[llCollisionSound|collision sound]]:&lt;br /&gt;
# stone&lt;br /&gt;
# metal&lt;br /&gt;
# glass&lt;br /&gt;
# wood&lt;br /&gt;
# flesh&lt;br /&gt;
# plastic &lt;br /&gt;
# rubber&lt;br /&gt;
&lt;br /&gt;
==Help==&lt;br /&gt;
* [[Basic Prim Creation and Editing]]&lt;br /&gt;
&lt;br /&gt;
==Scripting==&lt;br /&gt;
* [[:Category:LSL_Prim]]&lt;br /&gt;
&lt;br /&gt;
==Video tutorials==&lt;br /&gt;
* [[Video Tutorial/What is a prim?]]&lt;br /&gt;
* [[Video Tutorial/Prim and mesh hair differences]]&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
* [[Invisiprim]]&lt;br /&gt;
* [[Mega Prim]]&lt;br /&gt;
* [[Object]]&lt;br /&gt;
* [[Prims]]&lt;br /&gt;
* [[Prim and Object Hierarchy]]&lt;br /&gt;
* [[Prim flicker]]&lt;br /&gt;
* [[Primfficiency]]&lt;br /&gt;
* [[Sculpted prim]]&lt;br /&gt;
&lt;br /&gt;
==External links==&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Geometric_primitive Wikipedia: Geometric primitive]&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Sounds&amp;diff=929792</id>
		<title>Sounds</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Sounds&amp;diff=929792"/>
		<updated>2010-05-27T00:44:17Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{OSWikiFeatureNav}}&lt;br /&gt;
=== Feature Design Document ===&lt;br /&gt;
The Sounds folder contains audio clips. (give specs for audio clips, max length, freq, codec, file extension)&lt;br /&gt;
&lt;br /&gt;
=== Functional Spec ===&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
=== Test scripts ===&lt;br /&gt;
[http://secondlife.com/knowledgebase/article.php?id=246 Audio test]&lt;br /&gt;
&lt;br /&gt;
=== Discussion for future improvements ===&lt;br /&gt;
Sound Synthesis&lt;br /&gt;
[pardon the ramble... if it is inappropriate here please contact me]&lt;br /&gt;
&lt;br /&gt;
IMHO a much ignored aspect of game sound design is Sound Synthesis. Presently the pervasive model is &#039;event driven file playback&#039; which, although often workable (e.g. gunshots, explosions, physical interactions), also limits the sound designer&#039;s ability to craft more dynamic, deeply interactive sonic events.&lt;br /&gt;
A simple example of this would be: &lt;br /&gt;
Imagine a &#039;machine&#039;, emitting a low rumble, with a switch on the side which when touched, changed the sound (say to a higher pitch).&lt;br /&gt;
In contrast, imagine the same machine with a lever on it, which allowed the user to arbitrarily change the sound (again say pitch) as they interacted with it.&lt;br /&gt;
&lt;br /&gt;
Whereas the former can be created with well crafted looping file playback and an interactive trigger to another looping file.... &lt;br /&gt;
the latter (arbitrary interaction on the users part) would be almost impossible to create using only &#039;file playback&#039;. &lt;br /&gt;
Instead, this type of dynamic interaction can only be created using standard sound design synthesis tools (oscillators, filters, etc.). &lt;br /&gt;
And a quick look at the API of sound engine for SL (FMOD) reveals that it is fully capable of this.&lt;br /&gt;
&lt;br /&gt;
So it is my suggestion that these features be revealed to the designer.&lt;br /&gt;
&lt;br /&gt;
Wether this is functionally possible I do not know... but if so: It would allow sound designers to craft much more dynamic and  interactive sonic content.&lt;br /&gt;
- Robb&lt;br /&gt;
&lt;br /&gt;
=== Relationship to other features ===&lt;br /&gt;
&amp;lt;b&amp;gt; List of features that need to be tested when this feature changes, and why. &amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
=== User Guides ===&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Textures&amp;diff=929782</id>
		<title>Textures</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Textures&amp;diff=929782"/>
		<updated>2010-05-27T00:43:54Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Help |Glossary=*}}&lt;br /&gt;
{{otheruses4|textures|[[LSL]] related info|:Category:LSL Texture|opensource specs|Textures (OS)}}&lt;br /&gt;
&lt;br /&gt;
A texture can be used to cover the faces of a prim as a visual representation of the material and look of an object or be used to make clothing or other tatoos or be put in a notecard.&lt;br /&gt;
&lt;br /&gt;
Textures can be purchased or found for free in-world, or created in third-party graphics programs and uploaded to Second Life for {{L$|10}} per image. &lt;br /&gt;
&lt;br /&gt;
Textures are marked with a texture icon [[Image:Inv_item_texture.png]] (and [[Image:Inv_item_snapshot.png]] for [[snapshots]]) in the [[inventory]].&lt;br /&gt;
&lt;br /&gt;
==Related Links==&lt;br /&gt;
* [[Saving Textures]]&lt;br /&gt;
* [[Sculpted_Prims:_Resident-made_Tools#Importers|Importing Textures]]&lt;br /&gt;
* [[Video Tutorial/Making transparent textures]]&lt;br /&gt;
* [[Profile Image]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=AssetType&amp;diff=929762</id>
		<title>AssetType</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=AssetType&amp;diff=929762"/>
		<updated>2010-05-27T00:34:30Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
    /// &amp;lt;summary&amp;gt;&lt;br /&gt;
    /// The different types of grid assets&lt;br /&gt;
    /// &amp;lt;/summary&amp;gt;&lt;br /&gt;
    public enum AssetType : sbyte&lt;br /&gt;
    {&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Unknown asset type&amp;lt;/summary&amp;gt;&lt;br /&gt;
        Unknown = -1,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Texture asset, stores in JPEG2000 J2C stream format&amp;lt;/summary&amp;gt;&lt;br /&gt;
        Texture = 0,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Sound asset&amp;lt;/summary&amp;gt;&lt;br /&gt;
        Sound = 1,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Calling card for another avatar&amp;lt;/summary&amp;gt;&lt;br /&gt;
        CallingCard = 2,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Link to a location in world&amp;lt;/summary&amp;gt;&lt;br /&gt;
        Landmark = 3,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Legacy script asset, you should never see one of these&amp;lt;/summary&amp;gt;&lt;br /&gt;
        //[Obsolete]&lt;br /&gt;
        //Script = 4,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Collection of textures and parameters that can be &lt;br /&gt;
        /// worn by an avatar&amp;lt;/summary&amp;gt;&lt;br /&gt;
        Clothing = 5,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Primitive that can contain textures, sounds, &lt;br /&gt;
        /// scripts and more&amp;lt;/summary&amp;gt;&lt;br /&gt;
        Object = 6,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Notecard asset&amp;lt;/summary&amp;gt;&lt;br /&gt;
        Notecard = 7,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Holds a collection of inventory items&amp;lt;/summary&amp;gt;&lt;br /&gt;
        Folder = 8,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Root inventory folder&amp;lt;/summary&amp;gt;&lt;br /&gt;
        RootFolder = 9,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Linden scripting language script&amp;lt;/summary&amp;gt;&lt;br /&gt;
        LSLText = 10,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;LSO bytecode for a script&amp;lt;/summary&amp;gt;&lt;br /&gt;
        LSLBytecode = 11,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Uncompressed TGA texture&amp;lt;/summary&amp;gt;&lt;br /&gt;
        TextureTGA = 12,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Collection of textures and shape parameters that can&lt;br /&gt;
        /// be worn&amp;lt;/summary&amp;gt;&lt;br /&gt;
        Bodypart = 13,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Trash folder&amp;lt;/summary&amp;gt;&lt;br /&gt;
        TrashFolder = 14,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Snapshot folder&amp;lt;/summary&amp;gt;&lt;br /&gt;
        SnapshotFolder = 15,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Lost and found folder&amp;lt;/summary&amp;gt;&lt;br /&gt;
        LostAndFoundFolder = 16,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Uncompressed sound&amp;lt;/summary&amp;gt;&lt;br /&gt;
        SoundWAV = 17,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Uncompressed TGA non-square image, not to be used as a&lt;br /&gt;
        /// texture&amp;lt;/summary&amp;gt;&lt;br /&gt;
        ImageTGA = 18,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Compressed JPEG non-square image, not to be used as a&lt;br /&gt;
        /// texture&amp;lt;/summary&amp;gt;&lt;br /&gt;
        ImageJPEG = 19,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Animation&amp;lt;/summary&amp;gt;&lt;br /&gt;
        Animation = 20,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Sequence of animations, sounds, chat, and pauses&amp;lt;/summary&amp;gt;&lt;br /&gt;
        Gesture = 21,&lt;br /&gt;
        /// &amp;lt;summary&amp;gt;Simstate file&amp;lt;/summary&amp;gt;&lt;br /&gt;
        Simstate = 22,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Category:Assets&amp;diff=929712</id>
		<title>Category:Assets</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Category:Assets&amp;diff=929712"/>
		<updated>2010-05-27T00:05:54Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Assets are the serialized representation of the objects and entities of Second Life.&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Build_clothing&amp;diff=929692</id>
		<title>Build clothing</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Build_clothing&amp;diff=929692"/>
		<updated>2010-05-27T00:04:41Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{OSWikiFeatureNav}}&lt;br /&gt;
=== Feature Design Document ===&lt;br /&gt;
Clothing are asset that can be worn on the avatar. They each have at least one texture swatch, a color swatch, some modification sliders, and a unique Inventory icon.&lt;br /&gt;
&lt;br /&gt;
[[Undershirt]]&lt;br /&gt;
&lt;br /&gt;
[[Shirt]]&lt;br /&gt;
&lt;br /&gt;
[[Underpants]]&lt;br /&gt;
&lt;br /&gt;
[[Pants]] &lt;br /&gt;
&lt;br /&gt;
[[Jacket]] &lt;br /&gt;
&lt;br /&gt;
[[Gloves]] &lt;br /&gt;
&lt;br /&gt;
[[Socks]] &lt;br /&gt;
&lt;br /&gt;
[[Shoes]] &lt;br /&gt;
&lt;br /&gt;
[[Dress]]&lt;br /&gt;
&lt;br /&gt;
=== Functional Spec ===&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
=== Test scripts ===&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
=== Discussion for future improvements ===&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
=== Relationship to other features ===&lt;br /&gt;
&amp;lt;b&amp;gt; List of features that need to be tested when this feature changes, and why. &amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
=== User Guides ===&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
=== See also ===&lt;br /&gt;
* [[Clothing Tutorials]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Landmarks&amp;diff=929682</id>
		<title>Landmarks</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Landmarks&amp;diff=929682"/>
		<updated>2010-05-27T00:03:41Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{OSWikiFeatureNav}}&lt;br /&gt;
=== Feature Design Document ===&lt;br /&gt;
Landmarks are inventory assets that contain precise locations in Second Life. Their main purpose is to enable teleportation to that location from somewhere else. Landmarks are stored, by default, in the Landmarks folder in My Inventory. Landmarks may be given to others, stored in notecards and in any field used for teleportation. There are two versions of landmarks, one of which is obsolete but still functional. The previous version stored a location in the form of a global position. Version 2 stores the local position and the RegionID of the region in question.&lt;br /&gt;
&lt;br /&gt;
You may create landmarks in your own inventory by use of the Create Landmark Here option on the World menu. It is possible to edit the underlying landmark asset, however not via the Second Life client.&lt;br /&gt;
&lt;br /&gt;
=== Functional Spec ===&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
=== Test scripts ===&lt;br /&gt;
[[Landmarks test]]&lt;br /&gt;
&lt;br /&gt;
=== Discussion for future improvements ===&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
=== Relationship to other features ===&lt;br /&gt;
&amp;lt;b&amp;gt; List of features that need to be tested when this feature changes, and why. &amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Teleport OS|Teleport]]&lt;br /&gt;
&lt;br /&gt;
=== User Guides ===&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Asset_System&amp;diff=929672</id>
		<title>Asset System</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Asset_System&amp;diff=929672"/>
		<updated>2010-05-27T00:03:04Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ViewerArchNav}}&lt;br /&gt;
[[Category:Viewer Architecture]]&lt;br /&gt;
The asset system is the primary interface for requesting assets from an upstream provider. The upstream provider for the client is the current region with the main agent.&lt;br /&gt;
&lt;br /&gt;
{{All Asset Types}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Category:LSL_Permissions/Asset&amp;diff=929642</id>
		<title>Category:LSL Permissions/Asset</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Category:LSL_Permissions/Asset&amp;diff=929642"/>
		<updated>2010-05-26T23:48:56Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header|ml=*}}&lt;br /&gt;
{{LSLC|Permissions}}&lt;br /&gt;
&lt;br /&gt;
==Articles==&lt;br /&gt;
*[[Help:Permissions]]&lt;br /&gt;
*[[Permissions Explained]]&lt;br /&gt;
&lt;br /&gt;
==Constants==&lt;br /&gt;
{{LSL Constants Perm Mask}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Category:LSL_Notecard&amp;diff=929632</id>
		<title>Category:LSL Notecard</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Category:LSL_Notecard&amp;diff=929632"/>
		<updated>2010-05-26T23:43:33Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header|ml=*}}&lt;br /&gt;
{{LSLC|}}{{LSLC|Inventory}}&lt;br /&gt;
&lt;br /&gt;
== Notecards &amp;amp; Parameters ==&lt;br /&gt;
&lt;br /&gt;
In public domain scripts released with modify privileges, operational parameters (e.g. opening sounds for drawers, etc.) are usually set and changed right in the script by editing the script.&lt;br /&gt;
&lt;br /&gt;
Scripted products that are sold, however, often use instead a notecard as the place where customers can change parameters to meet their individual needs. Doing this negates both the need to distribute proprietary scripts with modify privileges, and the need for customers to edit scripts (which most find frightening.)&lt;br /&gt;
&lt;br /&gt;
To pull information from a notecard, you use the [[llGetNotecardLine]] function. As it comes into the script, it is captured in the [[dataserver]] event, during which event you parse the information and assign it to variables. There is an illustration of the procedure here: [[Notecard_reading]].&lt;br /&gt;
&lt;br /&gt;
== Limits ==&lt;br /&gt;
&lt;br /&gt;
Notecards are limited in several ways:&lt;br /&gt;
* 64KiB &lt;br /&gt;
* When read by script:&lt;br /&gt;
** Only the first 255 bytes of each line are returned.&lt;br /&gt;
** Cannot contain embedded assets.&lt;br /&gt;
* Immutability.  (They don&#039;t appear to be immutable, but they really are.)  &lt;br /&gt;
&lt;br /&gt;
== Notecard Immutability ==&lt;br /&gt;
&lt;br /&gt;
If you create a notecard, then you can easily edit the notecard and save changes.  However internally within the Second Life asset server, notecard objects are immutable.  This means that when you are editing the notecard, you are actually creating a new notecard with an entirely different key than the original notecard.  (The avatar&#039;s or object&#039;s inventory will not contain a reference to the old notecard any more -- it is updated to reference the key of the new notecard.)  The user probably thinks it is the same notecard object, but it is really an entirely new object.  &lt;br /&gt;
&lt;br /&gt;
This can be exploited in a script, to detect changes to a notecard and ignore other changes in an object&#039;s inventory.  The following script illustrates this technique.  The configuration notecard is read when the script is started, or when the configuration notecard itself changes.  (It will have a new key, and this will trigger reading it to get the changes.)  If something else changes in the object&#039;s inventory, then the change is ignored and the configuration notecard is not re-read.  This can save a lot of overhead.  &lt;br /&gt;
&lt;br /&gt;
This script assumes that there is a notecard named &amp;quot;Configuration&amp;quot; in the object&#039;s inventory, and that one or more lines of text are stored in the notecard.  &lt;br /&gt;
&amp;lt;lsl&amp;gt;key kQuery;&lt;br /&gt;
integer iLine = 0;&lt;br /&gt;
string notecard_name = &amp;quot;Configuration&amp;quot;;&lt;br /&gt;
key notecard_key = NULL_KEY;&lt;br /&gt;
&lt;br /&gt;
config_init()&lt;br /&gt;
{&lt;br /&gt;
    key nc_key = llGetInventoryKey(notecard_name);&lt;br /&gt;
    if (nc_key == notecard_key)&lt;br /&gt;
    {&lt;br /&gt;
        // Some other inventory item changed, not the configuration notecard.&lt;br /&gt;
        return; // Skip reading the notecard in this case.&lt;br /&gt;
    }&lt;br /&gt;
    // Remember the new notecard key from now on.&lt;br /&gt;
    notecard_key = nc_key;&lt;br /&gt;
    kQuery = llGetNotecardLine(notecard_name, iLine);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        // Read the notecard once at startup.&lt;br /&gt;
        config_init();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    changed(integer change)&lt;br /&gt;
    {&lt;br /&gt;
        if (change &amp;amp; CHANGED_INVENTORY)         &lt;br /&gt;
        {&lt;br /&gt;
            // Read the notecard when the inventory has changed.&lt;br /&gt;
            config_init();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    dataserver(key query_id, string data) &lt;br /&gt;
    {&lt;br /&gt;
        if (query_id == kQuery) &lt;br /&gt;
        {&lt;br /&gt;
            // this is a line of our notecard&lt;br /&gt;
            if (data == EOF) &lt;br /&gt;
            {&lt;br /&gt;
                llOwnerSay(&amp;quot;Finished reading configuration.&amp;quot;);&lt;br /&gt;
            } &lt;br /&gt;
            else &lt;br /&gt;
            {&lt;br /&gt;
                // TODO: handle notecard line here.  For not just inform the owner.&lt;br /&gt;
                llOwnerSay(&amp;quot;Read notecard line: &amp;quot; + data);&lt;br /&gt;
                // increment line count&lt;br /&gt;
                ++iLine;&lt;br /&gt;
                //request next line of notecard.&lt;br /&gt;
                kQuery = llGetNotecardLine(notecard_name, iLine);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sharing Notecard Access ==&lt;br /&gt;
&lt;br /&gt;
In the course of shared projects, you may often need to let team members access notecards in objects owned by you, or need yourself to access notecards in objects owned by them.&lt;br /&gt;
&lt;br /&gt;
To enable this, see: [[Editing someone else&#039;s scripts and notecards]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Embedded Assets in Notecards ==&lt;br /&gt;
Notecards can contain embedded assets, such as textures, landmarks, etc.&lt;br /&gt;
&lt;br /&gt;
These cannot be accessed via script.&lt;br /&gt;
&lt;br /&gt;
Tip! While it appears that the contents of one notecard, text and embedded objects, can manually be copied from one notecard to a second notecard, in fact you won&#039;t be able to save that second notecard. What you must do is drag the embedded objects to your inventory, and then from there drag into the second notecard.&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Upload_Assets&amp;diff=929592</id>
		<title>Upload Assets</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Upload_Assets&amp;diff=929592"/>
		<updated>2010-05-26T23:34:13Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{OSWikiFeatureNav}}&lt;br /&gt;
=== Feature Design Document ===&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
=== Functional Spec ===&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
=== Test scripts ===&lt;br /&gt;
[[Upload Audio test]]&lt;br /&gt;
&lt;br /&gt;
[[Animation Test]]&lt;br /&gt;
&lt;br /&gt;
[[Upload Texture test]]&lt;br /&gt;
&lt;br /&gt;
[[Upload Heightfield test]]&lt;br /&gt;
&lt;br /&gt;
=== Discussion for future improvements ===&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
=== Relationship to other features ===&lt;br /&gt;
&amp;lt;b&amp;gt; List of features that need to be tested when this feature changes, and why. &amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(none)&lt;br /&gt;
&lt;br /&gt;
=== User Guides ===&lt;br /&gt;
[http://secondlife.com/knowledgebase/article.php?id=142 Uploading Files]&lt;br /&gt;
&lt;br /&gt;
[http://secondlife.com/knowledgebase/article.php?id=288 Uploading Heightfields]&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Asset_Server&amp;diff=929582</id>
		<title>Asset Server</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Asset_Server&amp;diff=929582"/>
		<updated>2010-05-26T23:33:41Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Help |Glossary=*}}&lt;br /&gt;
&lt;br /&gt;
Database that tracks all Second Life objects in-world and in inventory. Overloaded asset servers can cause search, inventory, rez, teleport, and friends list failures.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Inventory Recovery Steps]]&lt;br /&gt;
* [[Asset]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Asset&amp;diff=929572</id>
		<title>Asset</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Asset&amp;diff=929572"/>
		<updated>2010-05-26T23:33:30Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Help |Glossary=*}}&lt;br /&gt;
&lt;br /&gt;
A data resource such as an image, sound, script, object, etc. Assets can be downloaded to the viewer or uploaded into a central asset store. Assets are identified by [[UUID]] and type (Types are in llassettype.h)&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Inventory Recovery Steps]]&lt;br /&gt;
* [[Asset Server]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Transfer_Manager&amp;diff=929562</id>
		<title>Transfer Manager</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Transfer_Manager&amp;diff=929562"/>
		<updated>2010-05-26T23:30:33Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ViewerArchNav}}&lt;br /&gt;
&lt;br /&gt;
The LLTransferManager class is a throttled data transfer system which is used primarily by the [[Asset System]] to fetch assets from Second Life. A transfer manager client makes a new instance of a class derived from LLTransferSourceParams, a new instance of a class derived from LLTransferTargetParams, and issues the request with a [[TransferRequest]] message. The source parameters are thrown away, and the client process creates an appropriate LLTransferTarget instance which copies the target parameters.&lt;br /&gt;
&lt;br /&gt;
When the [[TransferRequest]] comes in, the transfer id is used as a primary key in the server to index the transfers. Since duplicates are discarded and the key should be unguessable, it should be safe to key on a client generated uuid in this case. Colluding clients generating identical keys will get one successful request and one client with a likely memory leak.&lt;br /&gt;
&lt;br /&gt;
Requests for file sources will fail. Requests for assets are constrained to assets which the viewer is allowed to request via asset id. Asset requests are never prioritized in the asset queue regardless of client specified priority. Requests for inventory items are constrained to the assets in agent or task inventory according to the client source parameters on initialization. &lt;br /&gt;
&lt;br /&gt;
Textures are moved the through the [[Texture Pipeline]] -- not the transfer manager.&lt;br /&gt;
&lt;br /&gt;
When the server has collected the requested data, it sends a [[TransferInfo]] message to the viewer, followed by as many [[TransferPacket]] messages as necessary to transmit all data. If a [[TransferPacket]] is received before the [[TransferInfo]], or out of order, the data will be stored and replayed once the information shows up or the preceding packets arrive. If too many [[TransferPacket]] are queued for delayed delivery, the transfer will be aborted.&lt;br /&gt;
&lt;br /&gt;
The [[TransferAbort]] message can be sent from either side to end a transfer. The message is sent in response to incorrect accounting information, reliable packet delivery failure, or too many delayed packets.&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Protocol&amp;diff=929552</id>
		<title>Protocol</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Protocol&amp;diff=929552"/>
		<updated>2010-05-26T23:28:17Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{OSWikiLearnBox}}&lt;br /&gt;
&lt;br /&gt;
==Message Formats==&lt;br /&gt;
===Binary UDP===&lt;br /&gt;
* [[Message Layout]] -- Explanation of message format and the message template &lt;br /&gt;
* [[Packet Layout]] -- the layout of the UDP payload.&lt;br /&gt;
* [[Circuits]] -- Establishment and common operation of UDP circuits between two nodes&lt;br /&gt;
* [[Packet Accounting]] -- how the message system handles packet sequencing, reliability, suppression, throttling, etc.&lt;br /&gt;
* [[:Category:Common Messages|Common Messages]] -- messages that are handled by every Indra message system instance.&lt;br /&gt;
* [[Xfer Manager]] -- messages used by the &amp;lt;code&amp;gt;LLXFerManager&amp;lt;/code&amp;gt; class.&lt;br /&gt;
* [[Transfer Manager]] -- messages used by the &amp;lt;code&amp;gt;LLTransferManger&amp;lt;/code&amp;gt; class.&lt;br /&gt;
* [[:Category:Messages|All messages]] -- an alphabetical listing of all messages in the system&lt;br /&gt;
&lt;br /&gt;
===Capabilities===&lt;br /&gt;
The Capabilities system allows viewers to request abilities and be temporarily granted those abilities through a unique URL. The transport format is LLSD XML, and clients can either post new events to CAPS URLs or wait for events to come from the server on the event queue connection the client holds open.&lt;br /&gt;
&lt;br /&gt;
* [[Capabilities]]&lt;br /&gt;
* [[Message_System_and_Capabilities]]&lt;br /&gt;
&lt;br /&gt;
Capabilities use the Linden Lab Structured Data system to represent data.&lt;br /&gt;
See [[LLSD]].&lt;br /&gt;
&lt;br /&gt;
===XML-RPC===&lt;br /&gt;
Older releases of the official viewer used XML-RPC as part of the [[Login Protocol]]. The official viewer now uses a web based authentication protocol, however non-official viewers may still use XML-RPC for login.&lt;br /&gt;
&lt;br /&gt;
See also [[Authentication Flow]].&lt;br /&gt;
&lt;br /&gt;
==Protocol Systems==&lt;br /&gt;
===Animations===&lt;br /&gt;
&lt;br /&gt;
See [[Internal Animation Format]].&lt;br /&gt;
&lt;br /&gt;
===Appearance===&lt;br /&gt;
See [[Avatar Appearance]].&lt;br /&gt;
&lt;br /&gt;
===Assets===&lt;br /&gt;
&lt;br /&gt;
===Avatars===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Channels and Versions===&lt;br /&gt;
&lt;br /&gt;
* [[Channel]] - definition of a channel&lt;br /&gt;
** [[Channel and Version Requirements]] - Linden Lab policy on the use of channels.&lt;br /&gt;
&lt;br /&gt;
===Directory Searches===&lt;br /&gt;
See [[:Category:Search Messages|Search Messages]].&lt;br /&gt;
&lt;br /&gt;
===Estate Tools===&lt;br /&gt;
===Friends===&lt;br /&gt;
See:&lt;br /&gt;
* [[:Category:Relationship Messages|Relationship Messages]]&lt;br /&gt;
* [[Mute List]]&lt;br /&gt;
&lt;br /&gt;
===Grid===&lt;br /&gt;
===Groups===&lt;br /&gt;
* [[Group Messages]]&lt;br /&gt;
&lt;br /&gt;
===Inventory===&lt;br /&gt;
* [[:Category:Inventory Messages|Inventory Messages]]&lt;br /&gt;
* [[Task Inventory]]&lt;br /&gt;
&lt;br /&gt;
===Agent===&lt;br /&gt;
* [[:Category:Agent Messages|Agent Messages]]&lt;br /&gt;
* [[:Category:Money Messages|Money Messages]]&lt;br /&gt;
* [[:Category:Communication Messages|Communication Messages]]&lt;br /&gt;
* [[Buying Land and Currency]]&lt;br /&gt;
===Login===&lt;br /&gt;
* [[Login_Protocol|Login]]&lt;br /&gt;
&lt;br /&gt;
===Movement===&lt;br /&gt;
===Objects===&lt;br /&gt;
* [[:Category:Object Messages|Object Messages]]&lt;br /&gt;
&lt;br /&gt;
===Images===&lt;br /&gt;
===Parcels===&lt;br /&gt;
* [[:Category:Parcel Messages|Parcel Messages]]&lt;br /&gt;
&lt;br /&gt;
===Simulators===&lt;br /&gt;
* [[:Category:Region Messages|Region Messages]]&lt;br /&gt;
&lt;br /&gt;
===Sounds===&lt;br /&gt;
===Terrain===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==File Formats==&lt;br /&gt;
===Asset Files===&lt;br /&gt;
{{All Asset Types}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Assets]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Category:Assets&amp;diff=929542</id>
		<title>Category:Assets</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Category:Assets&amp;diff=929542"/>
		<updated>2010-05-26T23:27:56Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: Created page with &amp;#039;Assets are the on-disk representation of the objects and entities of Second Life.&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Assets are the on-disk representation of the objects and entities of Second Life.&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Asset&amp;diff=929422</id>
		<title>Asset</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Asset&amp;diff=929422"/>
		<updated>2010-05-26T22:47:02Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Help |Glossary=*}}&lt;br /&gt;
&lt;br /&gt;
A data resource such as an image, sound, script, object, etc. Assets can be downloaded to the viewer or uploaded into a central asset store. Assets are identified by [[UUID]] and type (Types are in llassettype.h)&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Inventory Recovery Steps]]&lt;br /&gt;
* [[Asset Server]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Asset_Server&amp;diff=929412</id>
		<title>Asset Server</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Asset_Server&amp;diff=929412"/>
		<updated>2010-05-26T22:46:13Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Help |Glossary=*}}&lt;br /&gt;
&lt;br /&gt;
Database that tracks all Second Life objects in-world and in inventory. Overloaded asset servers can cause search, inventory, rez, teleport, and friends list failures.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Inventory Recovery Steps]]&lt;br /&gt;
* [[Asset]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LLSD&amp;diff=915882</id>
		<title>LLSD</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LLSD&amp;diff=915882"/>
		<updated>2010-05-14T22:01:35Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: /* Notation Serialization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
Linden Lab Structured Data (LLSD) provides a flexible data system similar to the data facilities of dynamic languages like Perl and Python.  It supports exchange of structured data between loosely-coupled systems (those not compiled into the same module).&lt;br /&gt;
	&lt;br /&gt;
Data in such exchanges must be highly tolerant of:&lt;br /&gt;
* Recompilation&lt;br /&gt;
* Implementation in a different language&lt;br /&gt;
* Addition of extra parameters&lt;br /&gt;
* Execution of older versions (with fewer parameters)&lt;br /&gt;
&lt;br /&gt;
To this end, LLSD strives to be easy to use, and to default to &amp;quot;the right thing&amp;quot; wherever possible.  It is extremely tolerant of errors and unexpected situations.&lt;br /&gt;
	&lt;br /&gt;
The fundamental class is LLSD.  LLSD is a value holding object.  It holds one value that is either undefined, one of the scalar types, or a map or an array.  LLSD objects have value semantics (copying them copies the value, though it can be considered efficient, due to sharing), and are mutable.&lt;br /&gt;
&lt;br /&gt;
Undefined is the singular value given to LLSD objects that are not initialized with any data.&lt;br /&gt;
	&lt;br /&gt;
The scalar data types are:&lt;br /&gt;
* Boolean	- true or false&lt;br /&gt;
* Integer	- a 32 bit signed integer&lt;br /&gt;
* Real		- a 64 bit IEEE 754 floating point value&lt;br /&gt;
* UUID		- a 128 bit unique value&lt;br /&gt;
* String	- a sequence of zero or more Unicode chracters&lt;br /&gt;
* Date		- an absolute point in time, UTC, with resolution to the second&lt;br /&gt;
* URI		- a String that is a URI&lt;br /&gt;
* Binary	- a sequence of zero or more octets (unsigned bytes)&lt;br /&gt;
	&lt;br /&gt;
A map is a dictionary mapping String keys to LLSD values.  The keys are unique within a map, and have only one value (though that value could be an LLSD array).&lt;br /&gt;
	&lt;br /&gt;
An array is a sequence of zero or more LLSD values.&lt;br /&gt;
&lt;br /&gt;
== Scalar Accessors ==&lt;br /&gt;
&lt;br /&gt;
Function: Fetch a scalar value, converting if needed and possible.&lt;br /&gt;
&lt;br /&gt;
Conversion among the basic types, Boolean, Integer, Real and String, is fully defined.  Each type can be converted to another with a reasonable interpretation.  These conversions can be used as a convenience even when you know the data is in one format, but you want it in another.  Of course, many of these conversions lose information.&lt;br /&gt;
&lt;br /&gt;
Note: These conversions are not the same as Perl&#039;s.  In particular, when converting a String to a Boolean, only the empty string converts to false.  Converting the String &amp;quot;0&amp;quot; to Boolean results in true.&lt;br /&gt;
&lt;br /&gt;
Conversion to and from UUID, Date, and URI is only defined to and from String.  Conversion is defined to be information preserving for valid values of those types.  These conversions can be used when one needs to convert data to or from another system that cannot handle these types natively, but can handle strings.&lt;br /&gt;
&lt;br /&gt;
Conversion to and from Binary isn&#039;t defined.&lt;br /&gt;
&lt;br /&gt;
Conversion of the Undefined value to any scalar type results in a reasonable null or zero value for the type.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Automatic Cast Protection ==&lt;br /&gt;
&lt;br /&gt;
These are not implemented on purpose.  Without them, C++ can perform some conversions that are clearly not what the programmer intended.&lt;br /&gt;
	&lt;br /&gt;
If you get a linker error about these being missing, you have made mistake in your code.  DO NOT IMPLEMENT THESE FUNCTIONS as a fix.&lt;br /&gt;
		&lt;br /&gt;
All of thse problems stem from trying to support char* in LLSD or in std::string.  There are too many automatic casts that will lead to using an arbitrary pointer or scalar type to std::string.&lt;br /&gt;
&lt;br /&gt;
== Attributes and Data ==&lt;br /&gt;
Attributes are only used for encoding parser and formatting instructions. The data in the elements is always data.&lt;br /&gt;
&lt;br /&gt;
== Root Element ==&lt;br /&gt;
The root element is llsd. The root must have only one child element which can be any container or atomic type.&lt;br /&gt;
&lt;br /&gt;
== Atomic Types ==&lt;br /&gt;
Each atomic type represents one value with type information. An atomic does not have a name, but may have attributes to specify format or processing considerations for the parser. &lt;br /&gt;
Consumers of atomics are encouraged to massage the data into the preferred native representation, but further serialization should honor the original type information if possible.&lt;br /&gt;
&lt;br /&gt;
The default value for any type is represented in XML as &amp;lt;code&amp;gt;&amp;lt;&#039;&#039;type&#039;&#039; /&amp;gt;&amp;lt;/code&amp;gt;.  For example, &amp;lt;code&amp;gt;&amp;lt;integer /&amp;gt;&amp;lt;/code&amp;gt; represents zero (0).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;lltable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Datatype&lt;br /&gt;
!width=&amp;quot;300&amp;quot;| Description&lt;br /&gt;
! Default Value&lt;br /&gt;
! Examples&lt;br /&gt;
&lt;br /&gt;
|---&lt;br /&gt;
| Undefined&lt;br /&gt;
| A placeholder for a value.&lt;br /&gt;
| &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|---&lt;br /&gt;
| Boolean&lt;br /&gt;
| A true or false value.&lt;br /&gt;
| False&lt;br /&gt;
| &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|---&lt;br /&gt;
| Integer&lt;br /&gt;
| A signed 32-bit integer value; any natural number between -2147483648 and 2147483647 inclusive.&lt;br /&gt;
| 0&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;integer&amp;gt;289343&amp;lt;/integer&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;-3&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|---&lt;br /&gt;
| Real&lt;br /&gt;
| A signed 64-bit floating point number.&lt;br /&gt;
| 0.0&lt;br /&gt;
|&amp;lt;code&amp;gt;-0.28334&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;2983287453.3848387&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|---&lt;br /&gt;
| String&lt;br /&gt;
| A sequence of zero or more Unicode characters intended to be human readable.  See the [http://tools.ietf.org/html/draft-hamrick-llsd-00#section-2.1.5 IETF draft] for details.&lt;br /&gt;
&lt;br /&gt;
|&amp;quot;&amp;quot; (the empty string)&lt;br /&gt;
|&amp;lt;code&amp;gt;The quick brown fox, etc.&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;foo&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|---&lt;br /&gt;
| UUID&lt;br /&gt;
| A universally unique identifier: an unsigned 128-bit integer.&lt;br /&gt;
| 00000000-0000-0000-&lt;br /&gt;
0000-000000000000&lt;br /&gt;
|&amp;lt;code&amp;gt;d7f4aeca-88f1-42a1-&amp;lt;br&amp;gt;b385-b9db18abb255&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|---&lt;br /&gt;
| Date&lt;br /&gt;
| A specific point in time, UTC; Values range between  January 1, 1970, through at least January 1, 2038.  The serialization and parser only understand ISO-8601 numeric encoding in UTC.&lt;br /&gt;
| The &amp;quot;epoch,&amp;quot; Midnight, January 1, 1970 (UTC).&lt;br /&gt;
| &amp;lt;code&amp;gt;2006-02-01T14:29:53.43Z&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|---&lt;br /&gt;
| URI&lt;br /&gt;
| A Uniform Resource Identifier, specifying a link to an external resource and conforming to [http://www.ietf.org/rfc/rfc2396.txt RFC 2396].&lt;br /&gt;
| The empty URI.&lt;br /&gt;
&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://sim956.agni.lindenlab.com:12035/runtime/agents&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|---&lt;br /&gt;
| Binary&lt;br /&gt;
|width=&amp;quot;300&amp;quot;| A sequence of zero or more octets. Serialization format may include base64 (the default), base16, and base85.&lt;br /&gt;
&lt;br /&gt;
| A sequence of zero octets&lt;br /&gt;
| base16: &amp;lt;code&amp;gt;cmFuZG9t&amp;lt;/code&amp;gt;&lt;br /&gt;
base64: &amp;lt;code&amp;gt;dGhlIHF1aWNrIGJyb3duIGZveA==&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== undefined ===&lt;br /&gt;
The undefined type is a placeholder to indicate something is there, but it has no value, and cannot be converted to any other atomic type. Though limited in this way, an undefined is still considered a first-class atomic, and is expected to behave like any other atomic structured data type at runtime.&lt;br /&gt;
==== Serialization example ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&amp;lt;undef /&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== boolean ===&lt;br /&gt;
A true or false value.&lt;br /&gt;
==== Conversion ====&lt;br /&gt;
{|&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;||&#039;&#039;&#039;rules&#039;&#039;&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|boolean||unity||&lt;br /&gt;
|-&lt;br /&gt;
|integer||true =&amp;gt; 1, false =&amp;gt; 0||&lt;br /&gt;
|-&lt;br /&gt;
|real||true =&amp;gt; 1.0, false =&amp;gt; 0.0||&lt;br /&gt;
|-&lt;br /&gt;
|uuid||n/a||&lt;br /&gt;
|-&lt;br /&gt;
|string||&#039;true&#039;, &#039;false&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|binary||one byte us-ascii where true =&amp;gt; 1, false =&amp;gt; 0||&lt;br /&gt;
|-&lt;br /&gt;
|date||n/a||&lt;br /&gt;
|-&lt;br /&gt;
|uri||n/a||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Serialization examples ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!-- true --&amp;gt;&lt;br /&gt;
&amp;lt;boolean&amp;gt;1&amp;lt;/boolean&amp;gt;&lt;br /&gt;
&amp;lt;boolean&amp;gt;true&amp;lt;/boolean&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- false --&amp;gt;&lt;br /&gt;
&amp;lt;boolean&amp;gt;0&amp;lt;/boolean&amp;gt;&lt;br /&gt;
&amp;lt;boolean&amp;gt;false&amp;lt;/boolean&amp;gt;&lt;br /&gt;
&amp;lt;boolean /&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== integer ===&lt;br /&gt;
A signed integer value with a representation of 32 bits.&lt;br /&gt;
==== Conversion ====&lt;br /&gt;
{|&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;||&#039;&#039;&#039;rules&#039;&#039;&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|boolean||0 =&amp;gt; false, all other values =&amp;gt; true||&lt;br /&gt;
|-&lt;br /&gt;
|integer||unity||&lt;br /&gt;
|-&lt;br /&gt;
|real||closest representable number||&lt;br /&gt;
|-&lt;br /&gt;
|uuid||n/a||&lt;br /&gt;
|-&lt;br /&gt;
|string||human readable string||&lt;br /&gt;
|-&lt;br /&gt;
|binary||8 byte network byte order representation||&lt;br /&gt;
|-&lt;br /&gt;
|date||seconds since epoch||&lt;br /&gt;
|-&lt;br /&gt;
|uri||n/a||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Serialization examples ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;integer&amp;gt;289343&amp;lt;/integer&amp;gt;&lt;br /&gt;
&amp;lt;integer&amp;gt;-3&amp;lt;/integer&amp;gt;&lt;br /&gt;
&amp;lt;integer /&amp;gt; &amp;lt;!-- zero --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== real ===&lt;br /&gt;
A 64 bit double as defined by IEEE.&lt;br /&gt;
==== Conversion ====&lt;br /&gt;
{|&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;||&#039;&#039;&#039;rules&#039;&#039;&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|boolean||exactly 0 =&amp;gt; false, all other values =&amp;gt; true||&lt;br /&gt;
|-&lt;br /&gt;
|integer||rounded to closest representable number||&lt;br /&gt;
|-&lt;br /&gt;
|real||unity||&lt;br /&gt;
|-&lt;br /&gt;
|uuid||n/a||&lt;br /&gt;
|-&lt;br /&gt;
|string||human readable string||&lt;br /&gt;
|-&lt;br /&gt;
|binary||8 byte network byte order representation||&lt;br /&gt;
|-&lt;br /&gt;
|date||seconds since epoch||&lt;br /&gt;
|-&lt;br /&gt;
|uri||n/a||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Serialization examples ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;real&amp;gt;-0.28334&amp;lt;/real&amp;gt;&lt;br /&gt;
&amp;lt;real&amp;gt;2983287453.3848387&amp;lt;/real&amp;gt;&lt;br /&gt;
&amp;lt;real /&amp;gt; &amp;lt;!-- exactly zero --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== uuid ===&lt;br /&gt;
A 128 bit unsigned integer.&lt;br /&gt;
==== Conversion ====&lt;br /&gt;
{|&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;||&#039;&#039;&#039;rules&#039;&#039;&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|boolean||null uuid =&amp;gt; false, all other values =&amp;gt; true||&lt;br /&gt;
|-&lt;br /&gt;
|integer||n/a||&lt;br /&gt;
|-&lt;br /&gt;
|real||n/a||&lt;br /&gt;
|-&lt;br /&gt;
|uuid||unity||&lt;br /&gt;
|-&lt;br /&gt;
|string||standard 8-4-4-4-12 serialization format||&lt;br /&gt;
|-&lt;br /&gt;
|binary||16 byte raw representation||&lt;br /&gt;
|-&lt;br /&gt;
|date||n/a||&lt;br /&gt;
|-&lt;br /&gt;
|uri||n/a||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Serialization examples ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;uuid&amp;gt;d7f4aeca-88f1-42a1-b385-b9db18abb255&amp;lt;/uuid&amp;gt;&lt;br /&gt;
&amp;lt;uuid /&amp;gt; &amp;lt;!-- null uuid &#039;00000000-0000-0000-0000-000000000000&#039; --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== string ===&lt;br /&gt;
A simple string of any character data which is intended to be human comprehensible.&lt;br /&gt;
&lt;br /&gt;
Strings in the system that hold text a user might see or enter (chat, IM, notecards, AV names, region names,... basically almost everything!) should move to using a consistent set of acceptable characters. This set is:&lt;br /&gt;
&lt;br /&gt;
* Unicode code points U+20 through U+10FFFD&lt;br /&gt;
** except U+D800 through U+DFFF&lt;br /&gt;
** except U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, U+2FFFE, U+2FFFF ... U+10FFFE, U+10FFFF&lt;br /&gt;
** except U+FDD0 through U+FDEF&lt;br /&gt;
* U+9 (tab, &#039;\t&#039;)&lt;br /&gt;
* U+A (newline or line feed, &#039;\n&#039;)&lt;br /&gt;
* U+D (carriage return, &#039;\r&#039;)&lt;br /&gt;
&lt;br /&gt;
Strings may be sequences of zero or more of these characters. Strings *may* be normalized by mapping line ending sequences to U+A. Do not rely on differences in strings that normalize to the same string.&lt;br /&gt;
&lt;br /&gt;
These choices of valid strings are chosen from Unicode 4.0 which defines the following valid code points:&lt;br /&gt;
* Unicode code points U+0 through U+10FFFD&lt;br /&gt;
** except U+D800 through U+DFFF (the UTF-16 surrogate pair range)&lt;br /&gt;
** except U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, U+2FFFE, U+2FFFF ... U+10FFFE, U+10FFFF&lt;br /&gt;
** except U+FDD0 through U+FDEF (some historical screw up with Arabic)&lt;br /&gt;
&lt;br /&gt;
The choice for special characters &amp;lt; U+20 is because XML defines acceptable text as all valid Unicode code points &amp;gt;= U+20, and U+9, U+A and U+D. The normalization is because XML defines that all line ending sequences are normalized to U+A.&lt;br /&gt;
&lt;br /&gt;
See: [[Unicode In 5 Minutes]] for a brief introduction to Unicode.&lt;br /&gt;
&lt;br /&gt;
==== String escaping ====&lt;br /&gt;
Strings that contain non-printable characters delimited with quotes or double quotes require escaping. If a single quote delimited string contains single quotes, those must be escaped. If a double quote delimited string contains double quotes, the double quotes must be escaped.&lt;br /&gt;
&lt;br /&gt;
To escape the delimiter character, prefix a backslash. Backslashes must always be escaped with another backslash.&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;And then he said, \&amp;quot;I have nothing more to say on the subject.\&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 &#039;Look in &amp;quot;C:\\linden\\&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
The most generic escaping is to specify a hex value of the byte after a literal backslash and character &#039;x&#039;. This can be used for any character and is required for all non-printable characters which do not have an abbreviation. For example:&lt;br /&gt;
&lt;br /&gt;
  \x0C&lt;br /&gt;
&lt;br /&gt;
Serialized strings should only contain UTF-8 characters, so non-printable characters other than tab, newline, and carriage return should be avoided. However, common non-printable characters have short-hand abbreviations.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;lltable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|+ Notation abbreviations&lt;br /&gt;
! character !! value !! serialization&lt;br /&gt;
|-&lt;br /&gt;
| alert/bell ||  0x7 || \a&lt;br /&gt;
|-&lt;br /&gt;
| backspace || 0x8 || \b&lt;br /&gt;
|-&lt;br /&gt;
| form feed || 0xc || \f&lt;br /&gt;
|-&lt;br /&gt;
| newline || 0xa || \n&lt;br /&gt;
|-&lt;br /&gt;
| carriage return || 0xd || \r&lt;br /&gt;
|-&lt;br /&gt;
| horizontal tab || 0x9 || \t&lt;br /&gt;
|-&lt;br /&gt;
| vertical tab || 0xb || \v&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Conversion ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;lltable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type&lt;br /&gt;
! Rules&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|boolean||Empty =&amp;gt; false, all other values =&amp;gt; true&lt;br /&gt;
|-&lt;br /&gt;
|integer||A simple conversion of the initial characters to an integer&lt;br /&gt;
|-&lt;br /&gt;
|real||A simple conversion of the initial characters to a real number&lt;br /&gt;
|-&lt;br /&gt;
|uuid||A valid 8-4-4-4-12 is converted to a uuid, all other values =&amp;gt; null uuid&lt;br /&gt;
|-&lt;br /&gt;
|string||Unity&lt;br /&gt;
|-&lt;br /&gt;
|binary||Raw representation of the characters&lt;br /&gt;
|-&lt;br /&gt;
|date||An interpretation of the string as a date&lt;br /&gt;
|-&lt;br /&gt;
|uri||An interpretation of the string as a link&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Serialization examples ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;string&amp;gt;The quick brown fox jumped over the lazy dog.&amp;lt;/string&amp;gt;&lt;br /&gt;
&amp;lt;string&amp;gt;540943c1-7142-4fdd-996f-fc90ed5dd3fa&amp;lt;/string&amp;gt;&lt;br /&gt;
&amp;lt;string /&amp;gt; &amp;lt;!-- empty string --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== binary data ===&lt;br /&gt;
A chunk of binary data.&lt;br /&gt;
The serialization format is allowed to specify an encoding. Parsers must support base64 encoding. Parsers may support base16 and base85.&lt;br /&gt;
==== Conversion ====&lt;br /&gt;
{|&lt;br /&gt;
||&#039;&#039;&#039;type&#039;&#039;&#039;||&#039;&#039;&#039;rules&#039;&#039;&#039;||&lt;br /&gt;
|-&lt;br /&gt;
||boolean||empty =&amp;gt; false, all other values =&amp;gt; true||&lt;br /&gt;
|-&lt;br /&gt;
||integer||len &amp;lt; 4 =&amp;gt; 0, otherwise first four bytes are interpreted as a network byte order integer||&lt;br /&gt;
|-&lt;br /&gt;
||real||len &amp;lt; 8 =&amp;gt; 0, otherwise first eight bytes are interpreted as a network byte order double||&lt;br /&gt;
|-&lt;br /&gt;
||uuid||len &amp;lt; 16 =&amp;gt; null uuid, otherwise first sixteen bytes are interpreted as the raw binary uuid||&lt;br /&gt;
|-&lt;br /&gt;
||string||the raw binary data interpreted as utf-8 character data||&lt;br /&gt;
|-&lt;br /&gt;
||binary||unity||&lt;br /&gt;
|-&lt;br /&gt;
||date||n/a||&lt;br /&gt;
|-&lt;br /&gt;
||uri||the raw binary data interpreted as a utf-8 serialized link||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Serialization examples ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;binary encoding=&amp;quot;base64&amp;quot;&amp;gt;cmFuZG9t&amp;lt;/binary&amp;gt; &amp;lt;!-- base 64 encoded binary data --&amp;gt;&lt;br /&gt;
&amp;lt;binary&amp;gt;dGhlIHF1aWNrIGJyb3duIGZveA==&amp;lt;/binary&amp;gt; &amp;lt;!-- base 64 encoded binary data is default --&amp;gt;&lt;br /&gt;
&amp;lt;binary /&amp;gt; &amp;lt;!-- empty binary blob --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== date ===&lt;br /&gt;
A specific point in time. Intervals or relative dates are not supported. The serialization and parser only understand ISO-8601 numeric encoding in UTC. The time may be omitted which will be interpreted as midnight at the start of the day. &lt;br /&gt;
==== Conversion ====&lt;br /&gt;
{|&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;||&#039;&#039;&#039;rules&#039;&#039;&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|boolean||n/a||&lt;br /&gt;
|-&lt;br /&gt;
|integer||seconds since epoch||&lt;br /&gt;
|-&lt;br /&gt;
|real||seconds since epoch||&lt;br /&gt;
|-&lt;br /&gt;
|uuid||n/a||&lt;br /&gt;
|-&lt;br /&gt;
|string||standard serialization format||&lt;br /&gt;
|-&lt;br /&gt;
|binary||n/a||&lt;br /&gt;
|-&lt;br /&gt;
|date||unity||&lt;br /&gt;
|-&lt;br /&gt;
|uri||n/a||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Serialization examples ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;date&amp;gt;2006-02-01T14:29:53.43Z&amp;lt;/date&amp;gt;&lt;br /&gt;
&amp;lt;date /&amp;gt; &amp;lt;!-- epoch --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== uri ===&lt;br /&gt;
A link to an external resource. The data is expected to conform to [http://www.ietf.org/rfc/rfc2396.txt rfc 2396] for interpretation, meaning, serialization, and deserialization.&lt;br /&gt;
==== Conversion ====&lt;br /&gt;
{|&lt;br /&gt;
||&#039;&#039;&#039;type&#039;&#039;&#039;||&#039;&#039;&#039;rules&#039;&#039;&#039;||&lt;br /&gt;
|-&lt;br /&gt;
||boolean||n/a||&lt;br /&gt;
|-&lt;br /&gt;
||integer||n/a||&lt;br /&gt;
|-&lt;br /&gt;
||real||n/a||&lt;br /&gt;
|-&lt;br /&gt;
||uuid||n/a||&lt;br /&gt;
|-&lt;br /&gt;
||string||standard serialization format||&lt;br /&gt;
|-&lt;br /&gt;
||binary||n/a||&lt;br /&gt;
|-&lt;br /&gt;
||date||n/a||&lt;br /&gt;
|-&lt;br /&gt;
||uri||unity||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Serialization examples ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;uri&amp;gt;http://sim956.agni.lindenlab.com:12035/runtime/agents&amp;lt;/uri&amp;gt;&lt;br /&gt;
&amp;lt;uri /&amp;gt; &amp;lt;!-- an empty link --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Containers ==&lt;br /&gt;
Containers is a special data type which can contain any other data type including other containers.&lt;br /&gt;
&lt;br /&gt;
=== map ===&lt;br /&gt;
A map of key and value pairs where key ordering is unspecified and keys are unique. The key is always interpreted as a character string and any character string is acceptable. If there are any elements in the map, it is serialized as a key followed by an atomic or container value. For every key, there must be one value.&lt;br /&gt;
Well formed and valid serialized maps may contain more non-unique keys. When a deserialized, the implementation should choose one of the the value objects, but that choice is not specified.&lt;br /&gt;
==== Serialization example ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;map&amp;gt;&lt;br /&gt;
 &amp;lt;key&amp;gt;foo&amp;lt;/key&amp;gt;&lt;br /&gt;
 &amp;lt;string&amp;gt;bar&amp;lt;/string&amp;gt;&lt;br /&gt;
 &amp;lt;key&amp;gt;agent info&amp;lt;/key&amp;gt;&lt;br /&gt;
 &amp;lt;map&amp;gt;&lt;br /&gt;
  &amp;lt;key&amp;gt;agent_id&amp;lt;/key&amp;gt;&lt;br /&gt;
  &amp;lt;uuid&amp;gt;93c73b16-cd86-434d-8b4a-76e12eee950a&amp;lt;/uuid&amp;gt;&lt;br /&gt;
  &amp;lt;key&amp;gt;name&amp;lt;/key&amp;gt;&lt;br /&gt;
  &amp;lt;string&amp;gt;testtest tester&amp;lt;/string&amp;gt;&lt;br /&gt;
 &amp;lt;/map&amp;gt;&lt;br /&gt;
&amp;lt;/map&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== array ===&lt;br /&gt;
An ordered collection of data members. Any member can be any atomic or container type.&lt;br /&gt;
==== Serialization example ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;array&amp;gt;&lt;br /&gt;
 &amp;lt;real&amp;gt;7343.0194&amp;lt;/real&amp;gt;&lt;br /&gt;
 &amp;lt;string&amp;gt;foo&amp;lt;/string&amp;gt;&lt;br /&gt;
 &amp;lt;array&amp;gt;&lt;br /&gt;
  &amp;lt;map&amp;gt;&lt;br /&gt;
   &amp;lt;key&amp;gt;offset&amp;lt;/key&amp;gt;&lt;br /&gt;
   &amp;lt;integer&amp;gt;9847&amp;lt;/integer&amp;gt;&lt;br /&gt;
  &amp;lt;/map&amp;gt;&lt;br /&gt;
  &amp;lt;string&amp;gt;da boom&amp;lt;/string&amp;gt;&lt;br /&gt;
 &amp;lt;/array&amp;gt;&lt;br /&gt;
&amp;lt;/array&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== XML Serialization ==&lt;br /&gt;
MIME type: &amp;lt;code&amp;gt;application/llsd+xml&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When possible, prefer using us-ascii or or UTF-8 xml encoding.&lt;br /&gt;
&lt;br /&gt;
XML is the &amp;quot;standard&amp;quot; serialization format, being future-proof and readable by a wide variety of tools. The XML serialization should be preferred unless profiling reveals that the [[#Binary_Serialization | binary serialization]] provides an essential performance benefit.  All the serialization examples in the above sections are of the XML serialization.&lt;br /&gt;
&lt;br /&gt;
=== DTD ===&lt;br /&gt;
&amp;lt;xml&amp;gt;&amp;lt;!DOCTYPE llsd [&lt;br /&gt;
&amp;lt;!ELEMENT llsd (DATA)&amp;gt;&lt;br /&gt;
&amp;lt;!ELEMENT DATA (ATOMIC|map|array)&amp;gt;&lt;br /&gt;
&amp;lt;!ELEMENT ATOMIC (undef|boolean|integer|real|uuid|string|date|uri|binary)&amp;gt;&lt;br /&gt;
&amp;lt;!ELEMENT KEYDATA (key,DATA)&amp;gt;&lt;br /&gt;
&amp;lt;!ELEMENT key (#PCDATA)&amp;gt;&lt;br /&gt;
&amp;lt;!ELEMENT map (KEYDATA*)&amp;gt;&lt;br /&gt;
&amp;lt;!ELEMENT array (DATA*)&amp;gt;&lt;br /&gt;
&amp;lt;!ELEMENT undef (EMPTY)&amp;gt;&lt;br /&gt;
&amp;lt;!ELEMENT boolean (#PCDATA)&amp;gt;&lt;br /&gt;
&amp;lt;!ELEMENT integer (#PCDATA)&amp;gt;&lt;br /&gt;
&amp;lt;!ELEMENT real (#PCDATA)&amp;gt;&lt;br /&gt;
&amp;lt;!ELEMENT uuid (#PCDATA)&amp;gt;&lt;br /&gt;
&amp;lt;!ELEMENT string (#PCDATA)&amp;gt;&lt;br /&gt;
&amp;lt;!ELEMENT date (#PCDATA)&amp;gt;&lt;br /&gt;
&amp;lt;!ELEMENT uri (#PCDATA)&amp;gt;&lt;br /&gt;
&amp;lt;!ELEMENT binary (#PCDATA)&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!ATTLIST string xml:space (default|preserve) &#039;preserve&#039;&amp;gt;&lt;br /&gt;
&amp;lt;!ATTLIST binary encoding (base64|base16|base85) &#039;base64&#039;&amp;gt;&lt;br /&gt;
]&amp;gt;&amp;lt;/xml&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example XML Output ===&lt;br /&gt;
This is a sample from a recently running sim (indention for readability):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;xml&amp;gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;llsd&amp;gt;&lt;br /&gt;
&amp;lt;map&amp;gt;&lt;br /&gt;
  &amp;lt;key&amp;gt;region_id&amp;lt;/key&amp;gt;&lt;br /&gt;
    &amp;lt;uuid&amp;gt;67153d5b-3659-afb4-8510-adda2c034649&amp;lt;/uuid&amp;gt;&lt;br /&gt;
  &amp;lt;key&amp;gt;scale&amp;lt;/key&amp;gt;&lt;br /&gt;
    &amp;lt;string&amp;gt;one minute&amp;lt;/string&amp;gt;&lt;br /&gt;
  &amp;lt;key&amp;gt;simulator statistics&amp;lt;/key&amp;gt;&lt;br /&gt;
  &amp;lt;map&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;time dilation&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;0.9878624&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;sim fps&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;44.38898&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;pysics fps&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;44.38906&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;agent updates per second&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;nan&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;lsl instructions per second&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;0&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;total task count&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;4&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;active task count&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;0&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;active script count&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;4&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;main agent count&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;0&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;child agent count&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;0&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;inbound packets per second&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;1.228283&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;outbound packets per second&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;1.277508&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;pending downloads&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;0&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;pending uploads&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;0.0001096525&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;frame ms&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;0.7757886&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;net ms&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;0.3152919&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;sim other ms&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;0.1826937&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;sim physics ms&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;0.04323055&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;agent ms&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;0.01599029&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;image ms&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;0.01865955&amp;lt;/real&amp;gt;&lt;br /&gt;
    &amp;lt;key&amp;gt;script ms&amp;lt;/key&amp;gt;&amp;lt;real&amp;gt;0.1338836&amp;lt;/real&amp;gt;&lt;br /&gt;
  &amp;lt;/map&amp;gt;&lt;br /&gt;
&amp;lt;/map&amp;gt;&lt;br /&gt;
&amp;lt;/llsd&amp;gt;&amp;lt;/xml&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Binary Serialization =&lt;br /&gt;
MIME type: &amp;lt;code&amp;gt;application/llsd+binary&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also have support for binary serialization and deserialization in c++ and python. The binary format is useful when dealing where optimal parse time is necessary. Binary LLSD is the binary llsd prefix followed by a single LLSD element of any type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?llsd/binary?&amp;gt;\n&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;lltable&amp;quot;&lt;br /&gt;
|+ Binary element serialization&lt;br /&gt;
! type !! serialization !! notes&lt;br /&gt;
|-&lt;br /&gt;
| undef || &#039;!&#039;&lt;br /&gt;
|-&lt;br /&gt;
| true || &#039;1&#039;&lt;br /&gt;
|-&lt;br /&gt;
| false || &#039;0&#039;&lt;br /&gt;
|-&lt;br /&gt;
| integer || &#039;i&#039; + htonl(value)&lt;br /&gt;
|-&lt;br /&gt;
| real || &#039;r&#039; + htond(value)&lt;br /&gt;
|-&lt;br /&gt;
| uuid || &#039;u&#039; + uuid || uuid is 16 bytes&lt;br /&gt;
|-&lt;br /&gt;
| binary || &#039;b&#039; + htonl(binary.size()) + binary&lt;br /&gt;
|-&lt;br /&gt;
| string || &#039;s&#039; + htonl(string.size()) + string || notation serialization is considered valid&lt;br /&gt;
|-&lt;br /&gt;
| uri || &#039;l&#039; + htonl(uri.size()) + uri&lt;br /&gt;
|-&lt;br /&gt;
| date || &#039;d&#039; + htond(seconds_since_epoch)&lt;br /&gt;
|-&lt;br /&gt;
| array || &#039;[&#039; + htonl(array.length()) + (child0, child1, ...) + &#039;]&#039; || order is always preserved&lt;br /&gt;
|-&lt;br /&gt;
| map || &#039;{&#039; + htonl(map.length()) + ((key0,value0), (key1, value1), ...)+ &#039;}&#039; || order is not always preserved.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;size()&amp;lt;/b&amp;gt; is a byte count.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;length()&amp;lt;/b&amp;gt; is a child count.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;htonl()&amp;lt;/b&amp;gt; is a function to generate a 4 byte network byte order integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;htond()&amp;lt;/b&amp;gt; is a function to generate an 8 byte network byte order double. htond is not a standard system call, but you can find a c implementation in &amp;lt;code&amp;gt;indra/llcommon/llsdserialize.cpp&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Notation Serialization =&lt;br /&gt;
The (&amp;lt;strike&amp;gt;deprecated&amp;lt;/strike&amp;gt;?) notation serialization format is meant for human readability.  It is similar to, but different from, JSON.  See the [[LLSD#Notation_versus_JSON |comparison notes]] below.&lt;br /&gt;
&lt;br /&gt;
Parsing and formatting are currently available &amp;lt;strike&amp;gt;only in c++&amp;lt;/strike&amp;gt; in c++ (indra/llcommon/llsd.h) and in python (llbase.llsd). Notation LLSD is the notation llsd prefix followed by a single LLSD element of any type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?llsd/notation?&amp;gt;\n&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;lltable&amp;quot;&lt;br /&gt;
|+ Binary element serialization&lt;br /&gt;
! type !! serialization !! notes&lt;br /&gt;
|-&lt;br /&gt;
| undef || &#039;!&#039;&lt;br /&gt;
|-&lt;br /&gt;
| true || &amp;lt;nowiki&amp;gt;&#039;1&#039; |  &#039;t&#039; | &#039;T&#039; | &#039;true&#039; | &#039;TRUE&#039;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| false || &amp;lt;nowiki&amp;gt;&#039;0&#039; |  &#039;f&#039; | &#039;F&#039; | &#039;false&#039; | &#039;FALSE&#039;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| integer || &#039;i&#039; str(value)&lt;br /&gt;
|-&lt;br /&gt;
| real || &#039;r&#039; str(value)&lt;br /&gt;
|-&lt;br /&gt;
| uuid || &#039;u&#039; str(uuid)&lt;br /&gt;
|-&lt;br /&gt;
| binary || &amp;lt;nowiki&amp;gt;&#039;b(&#039; str(size) &#039;)&amp;quot;&#039;  raw_data &#039;&amp;quot;&#039; | &#039;b&#039; base &#039;&amp;quot;&#039; encoded_data &#039;&amp;quot;&#039;&amp;lt;/nowiki&amp;gt;  || Base 16 and 64 encodings are supported.&lt;br /&gt;
|-&lt;br /&gt;
| string || &amp;lt;nowiki&amp;gt;&amp;quot; escaped_string &amp;quot; | &#039; escaped_string &#039; | &#039;s(&#039; str(size) &#039;)&amp;quot;&#039; raw_string &#039;&amp;quot;&#039;&amp;lt;/nowiki&amp;gt; || When using single quotes, double quotes do not need escaping and vice versa.&lt;br /&gt;
|-&lt;br /&gt;
| uri || &#039;l&amp;quot;&#039; escaped_uri &#039;&amp;quot;&#039; || See [http://www.faqs.org/rfcs/rfc1738.html rfc 1738] for encoding rules.&lt;br /&gt;
|-&lt;br /&gt;
| date || &#039;d&amp;quot;&#039; YYYY-MM-DD &#039;T&#039; HH:MM:SS [.FF] &#039;Z&amp;quot;&#039; || Fractional seconds are optional&lt;br /&gt;
|-&lt;br /&gt;
| array || &#039;[&#039; object0 &#039;,&#039; object1 &#039;,&#039; ... &#039;]&#039; || order is always preserved&lt;br /&gt;
|-&lt;br /&gt;
| map || &#039;{&#039; string0:object0 &#039;,&#039; string1:object1 &#039;,&#039; ... &#039;}&#039; || order is not always preserved. The string is any supported string serialization format&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Example Notation Output ==&lt;br /&gt;
This is an excerpt from an agent request to enter a region serialized as notation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
  {&#039;destination&#039;:&#039;http://secondlife.com&#039;}, &lt;br /&gt;
  {&#039;version&#039;:i1}, &lt;br /&gt;
  {&lt;br /&gt;
    &#039;agent_id&#039;:u3c115e51-04f4-523c-9fa6-98aff1034730, &lt;br /&gt;
    &#039;session_id&#039;:u2c585cec-038c-40b0-b42e-a25ebab4d132, &lt;br /&gt;
    &#039;circuit_code&#039;:i1075, &lt;br /&gt;
    &#039;first_name&#039;:&#039;Phoenix&#039;, &lt;br /&gt;
    &#039;last_name&#039;:&#039;Linden&#039;,&lt;br /&gt;
    &#039;position&#039;:[r70.9247,r254.378,r38.7304], &lt;br /&gt;
    &#039;look_at&#039;:[r-0.043753,r-0.999042,r0], &lt;br /&gt;
    &#039;granters&#039;:[ua2e76fcd-9360-4f6d-a924-000000000003],&lt;br /&gt;
    &#039;attachment_data&#039;:&lt;br /&gt;
    [&lt;br /&gt;
      {&lt;br /&gt;
        &#039;attachment_point&#039;:i2,&lt;br /&gt;
        &#039;item_id&#039;:ud6852c11-a74e-309a-0462-50533f1ef9b3,&lt;br /&gt;
        &#039;asset_id&#039;:uc69b29b1-8944-58ae-a7c5-2ca7b23e22fb&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &#039;attachment_point&#039;:i10, &lt;br /&gt;
        &#039;item_id&#039;:uff852c22-a74e-309a-0462-50533f1ef900,&lt;br /&gt;
        &#039;asset_id&#039;:u5868dd20-c25a-47bd-8b4c-dedc99ef9479&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &#039;creation-date&#039;:d&amp;quot;2007-03-15T18:30:18Z&amp;quot;, &lt;br /&gt;
    &#039;creator-id&#039;:u3c115e51-04f4-523c-9fa6-98aff1034730&lt;br /&gt;
  },&lt;br /&gt;
  s(10)&amp;quot;0123456789&amp;quot;,&lt;br /&gt;
  &amp;quot;Where&#039;s the beef?&amp;quot;,&lt;br /&gt;
  &#039;Over here.&#039;,  &lt;br /&gt;
  b(160)&amp;quot;default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSay(0, &amp;quot;Hello, Avatar!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    touch_start(integer total_number)&lt;br /&gt;
    {&lt;br /&gt;
        llSay(0, &amp;quot;Touched.&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;quot;,&lt;br /&gt;
  b64&amp;quot;AABAAAAAAAAAAAIAAAA//wAAP/8AAADgAAAA5wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&lt;br /&gt;
AABkAAAAZAAAAAAAAAAAAAAAZAAAAAAAAAABAAAAAAAAAAAAAAAAAAAABQAAAAEAAAAQAAAAAAAA&lt;br /&gt;
AAUAAAAFAAAAABAAAAAAAAAAPgAAAAQAAAAFAGNbXgAAAABgSGVsbG8sIEF2YXRhciEAZgAAAABc&lt;br /&gt;
XgAAAAhwEQjRABeVAAAABQBjW14AAAAAYFRvdWNoZWQuAGYAAAAAXF4AAAAIcBEI0QAXAZUAAEAA&lt;br /&gt;
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;quot; &lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notation versus JSON ==&lt;br /&gt;
&lt;br /&gt;
The plan is to eventually move to JSON, after its spec in ECMAScript 5th edition is finalized.  There are three reasons this is not a current priority:&lt;br /&gt;
&lt;br /&gt;
# The binary and XML serialization formats work for our use cases, so there&#039;s no driving need for JSON.&lt;br /&gt;
# The notation format has not been useful in our experience and we expect JSON to fill a similar use niche.&lt;br /&gt;
# JSON was not in wide, common use when LLSD was invented.&lt;br /&gt;
&lt;br /&gt;
= Guidelines =&lt;br /&gt;
&lt;br /&gt;
=== Questions &amp;amp; Things To Do ===&lt;br /&gt;
&lt;br /&gt;
Would Binary be more convenient as usigned char* buffer semantics?&lt;br /&gt;
&lt;br /&gt;
Should Binary be convertable to/from String, and if so how?&lt;br /&gt;
* as UTF8 encoded strings (making not like UUID&amp;lt;-&amp;gt;String)&lt;br /&gt;
* as Base64 or Base96 encoded (making like UUID&amp;lt;-&amp;gt;String)&lt;br /&gt;
&lt;br /&gt;
Conversions to std::string and LLUUID do not result in easy assignment to std::string, LLString or LLUUID due to non-unique conversion paths.&lt;br /&gt;
&lt;br /&gt;
[[Category:Open Source Portal]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=File:PoppyLinden.png&amp;diff=912272</id>
		<title>File:PoppyLinden.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=File:PoppyLinden.png&amp;diff=912272"/>
		<updated>2010-05-12T21:51:35Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=725292</id>
		<title>LLMessageSystem Burst Metrics</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=725292"/>
		<updated>2010-02-10T00:59:38Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: /* Examples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Why care about message processing? ==&lt;br /&gt;
&lt;br /&gt;
The dataserver receives a message, makes a database query or two, then sends a response. The next message isn&#039;t received until the response is sent. LLMessageSystem in other LLApp instances is used in a similar way - receive message, do processing, receive next message. The question becomes, what is the longest amount of time that a message has to wait to be processed? In many instances, this wait manifests itself as &amp;quot;lag&amp;quot;, and in the worst cases can result in timeouts and failed operations.&lt;br /&gt;
&lt;br /&gt;
== What do we want to know about messages? ==&lt;br /&gt;
&lt;br /&gt;
There are several concerns. Among the reasons this metric was added:&lt;br /&gt;
* How much longer is response time when database network latency is increased? (dataserver specific)&lt;br /&gt;
* What is gridwide message response time? For which application?&lt;br /&gt;
&lt;br /&gt;
Ideally, we would like to be able to make a list of information about each message:&lt;br /&gt;
* time received&lt;br /&gt;
* time processing started&lt;br /&gt;
* time processing finished&lt;br /&gt;
&lt;br /&gt;
In the case of the dataserver, over a specified time period the maximum time processing finished minus time received would be the worst case of message latency on that app. Think about this instance:&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_1.png]]&lt;br /&gt;
&lt;br /&gt;
Message E has the highest response latency - it wasn&#039;t done processing until 15ms after it was received.&lt;br /&gt;
&lt;br /&gt;
== The way the world actually works ==&lt;br /&gt;
&lt;br /&gt;
Unfortunately, with the way the message system currently works, there is no way to tell when a message was received. Worse, the packet buffer is extremely small and there is no way to tell if a message is dropped. Let&#039;s run through the above example in a more realistic environment.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_2.png]]&lt;br /&gt;
&lt;br /&gt;
Message A, B, C received in the same order, but C doesn&#039;t fit in the buffer, so is silently dropped. In this case we&#039;re assuming the sender will re-send after a certain time if an ACK isn&#039;t sent back. For the sake of the example, assume an ACK is sent right when a message begins processing, and resends are at 4ms. (it&#039;s more complicated than this, but this example is far more convoluted than the previous one already.)&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_3.png]]&lt;br /&gt;
&lt;br /&gt;
Time 4 comes around, A is pulled out of the buffer for processing, B moves forward in the incoming queue, and D is received. E is dropped, because by the time 5ms rolls around, the buffer is full again. B is resent because it hasn&#039;t been ACK&#039;d by 6ms - A is still processing until 7ms. The resend of B happens to a full buffer, and is dropped.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_4.png]]&lt;br /&gt;
&lt;br /&gt;
At the tick of 8ms message B is pulled in for processing, and the resend of C hits the buffer. Before B is done processing, E gets resent, but dropped again.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_5.png]]&lt;br /&gt;
&lt;br /&gt;
By the time D gets pulled in, the third E comes around and makes it to the buffer. There are no more new packets in the rest of the timeframe we&#039;re looking at, so we can see what times all of these packets came in and out.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_6.png]]&lt;br /&gt;
&lt;br /&gt;
Looks a little different than the ideal example, but the sum of the processing times remains the same. The receiving application was constantly busy in either case. The worst case wait is still message E and is also matched by C - 15ms (20 - 5, and 18 - 3, respectively).&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_7.png]]&lt;br /&gt;
&lt;br /&gt;
The end result is the same as if all of the messages had arrived at once. And we&#039;ve got a little bit more information in the diagrams than there is in the system itself - remember, there&#039;s no way to tell what the actual arrival times are. Hence, from the system, we can&#039;t tell the difference between this case and the previous case.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_8.png]]&lt;br /&gt;
&lt;br /&gt;
This is all the information we have - we may know a message is a resend, but we don&#039;t know when the original was intended to be received.&lt;br /&gt;
&lt;br /&gt;
== The Burst, defined ==&lt;br /&gt;
&lt;br /&gt;
This brings us to the concept of the message burst. If we started processing messages at 4ms, and stopped at 20ms, we know that the theoretical worst case would be if all the messages arrived simultaneously the last message would be waiting 16ms for a reply. That&#039;s worse than the truth, but it&#039;s the closest thing we have. There&#039;s also another approximation - that we&#039;re always processing messages, and they don&#039;t have to wait long to start processing (clearly not the case for packet A).&lt;br /&gt;
&lt;br /&gt;
A burst is this constant arrival of packets. It ends when the buffer is found to be empty. Second Life backend traffic tends to be very bursty with long break periods. Unfortunately, these bursts can last many full seconds, causing terrible lag. This metric, combined with the many others that we already have, should give us a better idea about what our current message latency is today, and if changes we make help or hurt it. It&#039;s just one part of the connection, but hopefully it helps.&lt;br /&gt;
&lt;br /&gt;
== Implementation details ==&lt;br /&gt;
&lt;br /&gt;
* Burst metrics are disabled by default, because timer calls can be expensive - 12ns * 4 may be significant if you are expecting to process several messages per 1ms!&lt;br /&gt;
* The bursts are recorded as matching lists of the duration of the burst and the count of messages in the burst.&lt;br /&gt;
* The metrics are available both as calculated statistics, and raw data (if you have need of more accurate stats)&lt;br /&gt;
* If burst tracking is enabled, but you want to dynamically suppress either log output, you need merely add a &amp;quot;log-messages&amp;quot; section to you app&#039;s LiveConfig file, add a key for the log message (&amp;quot;logMessageBurstStats&amp;quot; and &amp;quot;logMessageBurstData&amp;quot;, respectively) and set &amp;quot;use-syslog&amp;quot; to integer 0.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
This is an example from an artificially-busy development LLApp I&#039;ve been working on so the numbers look &#039;&#039;really huge&#039;&#039; but that&#039;s, unfortunately, not real.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
2010-02-09T04:48:47Z INFO: log: LLLOGMESSAGE (1) logMessageBurstStats {&#039;avg_message_burst_throughput_rate&#039;:r1768.89, &#039;data_points&#039;:i702, &#039;frame_time_dur&#039;:r53.1146, &#039;max_message_break_duration&#039;:r5.85154, &#039;max_message_burst_count&#039;:i227, &#039;max_message_burst_duration&#039;:r0.307471, &#039;max_message_burst_throughput_rate&#039;:r12422.4, &#039;min_message_burst_throughput_rate&#039;:r163.62, &#039;mode&#039;:&#039;worker&#039;, &#039;total_message_break_duration&#039;:r47.1424, &#039;total_message_burst_duration&#039;:r6.48097, &#039;total_message_count&#039;:i6341, &#039;total_message_throughput_rate&#039;:r119.383}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
2010-02-09T04:48:57Z INFO: log: LLLOGMESSAGE (2) logMessageBurstStats {&#039;avg_message_burst_throughput_rate&#039;:r1097.77, &#039;data_points&#039;:i115, &#039;frame_time_dur&#039;:r10.1428, &#039;max_message_break_duration&#039;:r2.9249, &#039;max_message_burst_count&#039;:i216, &#039;max_message_burst_duration&#039;:r0.314165, &#039;max_message_burst_throughput_rate&#039;:r3458.5, &#039;min_message_burst_throughput_rate&#039;:r438.102, &#039;mode&#039;:&#039;worker&#039;, &#039;total_message_break_duration&#039;:r9.07722, &#039;total_message_burst_duration&#039;:r1.16166, &#039;total_message_count&#039;:i1082, &#039;total_message_throughput_rate&#039;:r106.676}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Homework ==&lt;br /&gt;
* I&#039;ve only looked at the dataserver. What would the viewer message system output look like?&lt;br /&gt;
* What is the highest message latency that you&#039;ve seen?&lt;br /&gt;
* What in-world experience corresponds to what burst statistics?&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=725282</id>
		<title>LLMessageSystem Burst Metrics</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=725282"/>
		<updated>2010-02-10T00:59:16Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: /* Examples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Why care about message processing? ==&lt;br /&gt;
&lt;br /&gt;
The dataserver receives a message, makes a database query or two, then sends a response. The next message isn&#039;t received until the response is sent. LLMessageSystem in other LLApp instances is used in a similar way - receive message, do processing, receive next message. The question becomes, what is the longest amount of time that a message has to wait to be processed? In many instances, this wait manifests itself as &amp;quot;lag&amp;quot;, and in the worst cases can result in timeouts and failed operations.&lt;br /&gt;
&lt;br /&gt;
== What do we want to know about messages? ==&lt;br /&gt;
&lt;br /&gt;
There are several concerns. Among the reasons this metric was added:&lt;br /&gt;
* How much longer is response time when database network latency is increased? (dataserver specific)&lt;br /&gt;
* What is gridwide message response time? For which application?&lt;br /&gt;
&lt;br /&gt;
Ideally, we would like to be able to make a list of information about each message:&lt;br /&gt;
* time received&lt;br /&gt;
* time processing started&lt;br /&gt;
* time processing finished&lt;br /&gt;
&lt;br /&gt;
In the case of the dataserver, over a specified time period the maximum time processing finished minus time received would be the worst case of message latency on that app. Think about this instance:&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_1.png]]&lt;br /&gt;
&lt;br /&gt;
Message E has the highest response latency - it wasn&#039;t done processing until 15ms after it was received.&lt;br /&gt;
&lt;br /&gt;
== The way the world actually works ==&lt;br /&gt;
&lt;br /&gt;
Unfortunately, with the way the message system currently works, there is no way to tell when a message was received. Worse, the packet buffer is extremely small and there is no way to tell if a message is dropped. Let&#039;s run through the above example in a more realistic environment.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_2.png]]&lt;br /&gt;
&lt;br /&gt;
Message A, B, C received in the same order, but C doesn&#039;t fit in the buffer, so is silently dropped. In this case we&#039;re assuming the sender will re-send after a certain time if an ACK isn&#039;t sent back. For the sake of the example, assume an ACK is sent right when a message begins processing, and resends are at 4ms. (it&#039;s more complicated than this, but this example is far more convoluted than the previous one already.)&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_3.png]]&lt;br /&gt;
&lt;br /&gt;
Time 4 comes around, A is pulled out of the buffer for processing, B moves forward in the incoming queue, and D is received. E is dropped, because by the time 5ms rolls around, the buffer is full again. B is resent because it hasn&#039;t been ACK&#039;d by 6ms - A is still processing until 7ms. The resend of B happens to a full buffer, and is dropped.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_4.png]]&lt;br /&gt;
&lt;br /&gt;
At the tick of 8ms message B is pulled in for processing, and the resend of C hits the buffer. Before B is done processing, E gets resent, but dropped again.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_5.png]]&lt;br /&gt;
&lt;br /&gt;
By the time D gets pulled in, the third E comes around and makes it to the buffer. There are no more new packets in the rest of the timeframe we&#039;re looking at, so we can see what times all of these packets came in and out.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_6.png]]&lt;br /&gt;
&lt;br /&gt;
Looks a little different than the ideal example, but the sum of the processing times remains the same. The receiving application was constantly busy in either case. The worst case wait is still message E and is also matched by C - 15ms (20 - 5, and 18 - 3, respectively).&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_7.png]]&lt;br /&gt;
&lt;br /&gt;
The end result is the same as if all of the messages had arrived at once. And we&#039;ve got a little bit more information in the diagrams than there is in the system itself - remember, there&#039;s no way to tell what the actual arrival times are. Hence, from the system, we can&#039;t tell the difference between this case and the previous case.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_8.png]]&lt;br /&gt;
&lt;br /&gt;
This is all the information we have - we may know a message is a resend, but we don&#039;t know when the original was intended to be received.&lt;br /&gt;
&lt;br /&gt;
== The Burst, defined ==&lt;br /&gt;
&lt;br /&gt;
This brings us to the concept of the message burst. If we started processing messages at 4ms, and stopped at 20ms, we know that the theoretical worst case would be if all the messages arrived simultaneously the last message would be waiting 16ms for a reply. That&#039;s worse than the truth, but it&#039;s the closest thing we have. There&#039;s also another approximation - that we&#039;re always processing messages, and they don&#039;t have to wait long to start processing (clearly not the case for packet A).&lt;br /&gt;
&lt;br /&gt;
A burst is this constant arrival of packets. It ends when the buffer is found to be empty. Second Life backend traffic tends to be very bursty with long break periods. Unfortunately, these bursts can last many full seconds, causing terrible lag. This metric, combined with the many others that we already have, should give us a better idea about what our current message latency is today, and if changes we make help or hurt it. It&#039;s just one part of the connection, but hopefully it helps.&lt;br /&gt;
&lt;br /&gt;
== Implementation details ==&lt;br /&gt;
&lt;br /&gt;
* Burst metrics are disabled by default, because timer calls can be expensive - 12ns * 4 may be significant if you are expecting to process several messages per 1ms!&lt;br /&gt;
* The bursts are recorded as matching lists of the duration of the burst and the count of messages in the burst.&lt;br /&gt;
* The metrics are available both as calculated statistics, and raw data (if you have need of more accurate stats)&lt;br /&gt;
* If burst tracking is enabled, but you want to dynamically suppress either log output, you need merely add a &amp;quot;log-messages&amp;quot; section to you app&#039;s LiveConfig file, add a key for the log message (&amp;quot;logMessageBurstStats&amp;quot; and &amp;quot;logMessageBurstData&amp;quot;, respectively) and set &amp;quot;use-syslog&amp;quot; to integer 0.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
This is an example from an artificially-busy development LLApp I&#039;ve been working on, so the numbers look &#039;&#039;really huge&#039;&#039; but that&#039;s, unfortunately, not real.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
2010-02-09T04:48:47Z INFO: log: LLLOGMESSAGE (1) logMessageBurstStats {&#039;avg_message_burst_throughput_rate&#039;:r1768.89, &#039;data_points&#039;:i702, &#039;frame_time_dur&#039;:r53.1146, &#039;max_message_break_duration&#039;:r5.85154, &#039;max_message_burst_count&#039;:i227, &#039;max_message_burst_duration&#039;:r0.307471, &#039;max_message_burst_throughput_rate&#039;:r12422.4, &#039;min_message_burst_throughput_rate&#039;:r163.62, &#039;mode&#039;:&#039;worker&#039;, &#039;total_message_break_duration&#039;:r47.1424, &#039;total_message_burst_duration&#039;:r6.48097, &#039;total_message_count&#039;:i6341, &#039;total_message_throughput_rate&#039;:r119.383}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
2010-02-09T04:48:57Z INFO: log: LLLOGMESSAGE (2) logMessageBurstStats {&#039;avg_message_burst_throughput_rate&#039;:r1097.77, &#039;data_points&#039;:i115, &#039;frame_time_dur&#039;:r10.1428, &#039;max_message_break_duration&#039;:r2.9249, &#039;max_message_burst_count&#039;:i216, &#039;max_message_burst_duration&#039;:r0.314165, &#039;max_message_burst_throughput_rate&#039;:r3458.5, &#039;min_message_burst_throughput_rate&#039;:r438.102, &#039;mode&#039;:&#039;worker&#039;, &#039;total_message_break_duration&#039;:r9.07722, &#039;total_message_burst_duration&#039;:r1.16166, &#039;total_message_count&#039;:i1082, &#039;total_message_throughput_rate&#039;:r106.676}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Homework ==&lt;br /&gt;
* I&#039;ve only looked at the dataserver. What would the viewer message system output look like?&lt;br /&gt;
* What is the highest message latency that you&#039;ve seen?&lt;br /&gt;
* What in-world experience corresponds to what burst statistics?&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=725272</id>
		<title>LLMessageSystem Burst Metrics</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=725272"/>
		<updated>2010-02-10T00:56:54Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: /* Examples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Why care about message processing? ==&lt;br /&gt;
&lt;br /&gt;
The dataserver receives a message, makes a database query or two, then sends a response. The next message isn&#039;t received until the response is sent. LLMessageSystem in other LLApp instances is used in a similar way - receive message, do processing, receive next message. The question becomes, what is the longest amount of time that a message has to wait to be processed? In many instances, this wait manifests itself as &amp;quot;lag&amp;quot;, and in the worst cases can result in timeouts and failed operations.&lt;br /&gt;
&lt;br /&gt;
== What do we want to know about messages? ==&lt;br /&gt;
&lt;br /&gt;
There are several concerns. Among the reasons this metric was added:&lt;br /&gt;
* How much longer is response time when database network latency is increased? (dataserver specific)&lt;br /&gt;
* What is gridwide message response time? For which application?&lt;br /&gt;
&lt;br /&gt;
Ideally, we would like to be able to make a list of information about each message:&lt;br /&gt;
* time received&lt;br /&gt;
* time processing started&lt;br /&gt;
* time processing finished&lt;br /&gt;
&lt;br /&gt;
In the case of the dataserver, over a specified time period the maximum time processing finished minus time received would be the worst case of message latency on that app. Think about this instance:&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_1.png]]&lt;br /&gt;
&lt;br /&gt;
Message E has the highest response latency - it wasn&#039;t done processing until 15ms after it was received.&lt;br /&gt;
&lt;br /&gt;
== The way the world actually works ==&lt;br /&gt;
&lt;br /&gt;
Unfortunately, with the way the message system currently works, there is no way to tell when a message was received. Worse, the packet buffer is extremely small and there is no way to tell if a message is dropped. Let&#039;s run through the above example in a more realistic environment.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_2.png]]&lt;br /&gt;
&lt;br /&gt;
Message A, B, C received in the same order, but C doesn&#039;t fit in the buffer, so is silently dropped. In this case we&#039;re assuming the sender will re-send after a certain time if an ACK isn&#039;t sent back. For the sake of the example, assume an ACK is sent right when a message begins processing, and resends are at 4ms. (it&#039;s more complicated than this, but this example is far more convoluted than the previous one already.)&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_3.png]]&lt;br /&gt;
&lt;br /&gt;
Time 4 comes around, A is pulled out of the buffer for processing, B moves forward in the incoming queue, and D is received. E is dropped, because by the time 5ms rolls around, the buffer is full again. B is resent because it hasn&#039;t been ACK&#039;d by 6ms - A is still processing until 7ms. The resend of B happens to a full buffer, and is dropped.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_4.png]]&lt;br /&gt;
&lt;br /&gt;
At the tick of 8ms message B is pulled in for processing, and the resend of C hits the buffer. Before B is done processing, E gets resent, but dropped again.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_5.png]]&lt;br /&gt;
&lt;br /&gt;
By the time D gets pulled in, the third E comes around and makes it to the buffer. There are no more new packets in the rest of the timeframe we&#039;re looking at, so we can see what times all of these packets came in and out.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_6.png]]&lt;br /&gt;
&lt;br /&gt;
Looks a little different than the ideal example, but the sum of the processing times remains the same. The receiving application was constantly busy in either case. The worst case wait is still message E and is also matched by C - 15ms (20 - 5, and 18 - 3, respectively).&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_7.png]]&lt;br /&gt;
&lt;br /&gt;
The end result is the same as if all of the messages had arrived at once. And we&#039;ve got a little bit more information in the diagrams than there is in the system itself - remember, there&#039;s no way to tell what the actual arrival times are. Hence, from the system, we can&#039;t tell the difference between this case and the previous case.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_8.png]]&lt;br /&gt;
&lt;br /&gt;
This is all the information we have - we may know a message is a resend, but we don&#039;t know when the original was intended to be received.&lt;br /&gt;
&lt;br /&gt;
== The Burst, defined ==&lt;br /&gt;
&lt;br /&gt;
This brings us to the concept of the message burst. If we started processing messages at 4ms, and stopped at 20ms, we know that the theoretical worst case would be if all the messages arrived simultaneously the last message would be waiting 16ms for a reply. That&#039;s worse than the truth, but it&#039;s the closest thing we have. There&#039;s also another approximation - that we&#039;re always processing messages, and they don&#039;t have to wait long to start processing (clearly not the case for packet A).&lt;br /&gt;
&lt;br /&gt;
A burst is this constant arrival of packets. It ends when the buffer is found to be empty. Second Life backend traffic tends to be very bursty with long break periods. Unfortunately, these bursts can last many full seconds, causing terrible lag. This metric, combined with the many others that we already have, should give us a better idea about what our current message latency is today, and if changes we make help or hurt it. It&#039;s just one part of the connection, but hopefully it helps.&lt;br /&gt;
&lt;br /&gt;
== Implementation details ==&lt;br /&gt;
&lt;br /&gt;
* Burst metrics are disabled by default, because timer calls can be expensive - 12ns * 4 may be significant if you are expecting to process several messages per 1ms!&lt;br /&gt;
* The bursts are recorded as matching lists of the duration of the burst and the count of messages in the burst.&lt;br /&gt;
* The metrics are available both as calculated statistics, and raw data (if you have need of more accurate stats)&lt;br /&gt;
* If burst tracking is enabled, but you want to dynamically suppress either log output, you need merely add a &amp;quot;log-messages&amp;quot; section to you app&#039;s LiveConfig file, add a key for the log message (&amp;quot;logMessageBurstStats&amp;quot; and &amp;quot;logMessageBurstData&amp;quot;, respectively) and set &amp;quot;use-syslog&amp;quot; to integer 0.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
2010-02-09T04:48:47Z INFO: log: LLLOGMESSAGE (1) logMessageBurstStats {&#039;avg_message_burst_throughput_rate&#039;:r1768.89, &#039;data_points&#039;:i702, &#039;frame_time_dur&#039;:r53.1146, &#039;max_message_break_duration&#039;:r5.85154, &#039;max_message_burst_count&#039;:i227, &#039;max_message_burst_duration&#039;:r0.307471, &#039;max_message_burst_throughput_rate&#039;:r12422.4, &#039;min_message_burst_throughput_rate&#039;:r163.62, &#039;mode&#039;:&#039;worker&#039;, &#039;total_message_break_duration&#039;:r47.1424, &#039;total_message_burst_duration&#039;:r6.48097, &#039;total_message_count&#039;:i6341, &#039;total_message_throughput_rate&#039;:r119.383}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Homework ==&lt;br /&gt;
* I&#039;ve only looked at the dataserver. What would the viewer message system output look like?&lt;br /&gt;
* What is the highest message latency that you&#039;ve seen?&lt;br /&gt;
* What in-world experience corresponds to what burst statistics?&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=725262</id>
		<title>LLMessageSystem Burst Metrics</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=725262"/>
		<updated>2010-02-10T00:55:18Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: /* Examples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Why care about message processing? ==&lt;br /&gt;
&lt;br /&gt;
The dataserver receives a message, makes a database query or two, then sends a response. The next message isn&#039;t received until the response is sent. LLMessageSystem in other LLApp instances is used in a similar way - receive message, do processing, receive next message. The question becomes, what is the longest amount of time that a message has to wait to be processed? In many instances, this wait manifests itself as &amp;quot;lag&amp;quot;, and in the worst cases can result in timeouts and failed operations.&lt;br /&gt;
&lt;br /&gt;
== What do we want to know about messages? ==&lt;br /&gt;
&lt;br /&gt;
There are several concerns. Among the reasons this metric was added:&lt;br /&gt;
* How much longer is response time when database network latency is increased? (dataserver specific)&lt;br /&gt;
* What is gridwide message response time? For which application?&lt;br /&gt;
&lt;br /&gt;
Ideally, we would like to be able to make a list of information about each message:&lt;br /&gt;
* time received&lt;br /&gt;
* time processing started&lt;br /&gt;
* time processing finished&lt;br /&gt;
&lt;br /&gt;
In the case of the dataserver, over a specified time period the maximum time processing finished minus time received would be the worst case of message latency on that app. Think about this instance:&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_1.png]]&lt;br /&gt;
&lt;br /&gt;
Message E has the highest response latency - it wasn&#039;t done processing until 15ms after it was received.&lt;br /&gt;
&lt;br /&gt;
== The way the world actually works ==&lt;br /&gt;
&lt;br /&gt;
Unfortunately, with the way the message system currently works, there is no way to tell when a message was received. Worse, the packet buffer is extremely small and there is no way to tell if a message is dropped. Let&#039;s run through the above example in a more realistic environment.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_2.png]]&lt;br /&gt;
&lt;br /&gt;
Message A, B, C received in the same order, but C doesn&#039;t fit in the buffer, so is silently dropped. In this case we&#039;re assuming the sender will re-send after a certain time if an ACK isn&#039;t sent back. For the sake of the example, assume an ACK is sent right when a message begins processing, and resends are at 4ms. (it&#039;s more complicated than this, but this example is far more convoluted than the previous one already.)&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_3.png]]&lt;br /&gt;
&lt;br /&gt;
Time 4 comes around, A is pulled out of the buffer for processing, B moves forward in the incoming queue, and D is received. E is dropped, because by the time 5ms rolls around, the buffer is full again. B is resent because it hasn&#039;t been ACK&#039;d by 6ms - A is still processing until 7ms. The resend of B happens to a full buffer, and is dropped.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_4.png]]&lt;br /&gt;
&lt;br /&gt;
At the tick of 8ms message B is pulled in for processing, and the resend of C hits the buffer. Before B is done processing, E gets resent, but dropped again.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_5.png]]&lt;br /&gt;
&lt;br /&gt;
By the time D gets pulled in, the third E comes around and makes it to the buffer. There are no more new packets in the rest of the timeframe we&#039;re looking at, so we can see what times all of these packets came in and out.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_6.png]]&lt;br /&gt;
&lt;br /&gt;
Looks a little different than the ideal example, but the sum of the processing times remains the same. The receiving application was constantly busy in either case. The worst case wait is still message E and is also matched by C - 15ms (20 - 5, and 18 - 3, respectively).&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_7.png]]&lt;br /&gt;
&lt;br /&gt;
The end result is the same as if all of the messages had arrived at once. And we&#039;ve got a little bit more information in the diagrams than there is in the system itself - remember, there&#039;s no way to tell what the actual arrival times are. Hence, from the system, we can&#039;t tell the difference between this case and the previous case.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_8.png]]&lt;br /&gt;
&lt;br /&gt;
This is all the information we have - we may know a message is a resend, but we don&#039;t know when the original was intended to be received.&lt;br /&gt;
&lt;br /&gt;
== The Burst, defined ==&lt;br /&gt;
&lt;br /&gt;
This brings us to the concept of the message burst. If we started processing messages at 4ms, and stopped at 20ms, we know that the theoretical worst case would be if all the messages arrived simultaneously the last message would be waiting 16ms for a reply. That&#039;s worse than the truth, but it&#039;s the closest thing we have. There&#039;s also another approximation - that we&#039;re always processing messages, and they don&#039;t have to wait long to start processing (clearly not the case for packet A).&lt;br /&gt;
&lt;br /&gt;
A burst is this constant arrival of packets. It ends when the buffer is found to be empty. Second Life backend traffic tends to be very bursty with long break periods. Unfortunately, these bursts can last many full seconds, causing terrible lag. This metric, combined with the many others that we already have, should give us a better idea about what our current message latency is today, and if changes we make help or hurt it. It&#039;s just one part of the connection, but hopefully it helps.&lt;br /&gt;
&lt;br /&gt;
== Implementation details ==&lt;br /&gt;
&lt;br /&gt;
* Burst metrics are disabled by default, because timer calls can be expensive - 12ns * 4 may be significant if you are expecting to process several messages per 1ms!&lt;br /&gt;
* The bursts are recorded as matching lists of the duration of the burst and the count of messages in the burst.&lt;br /&gt;
* The metrics are available both as calculated statistics, and raw data (if you have need of more accurate stats)&lt;br /&gt;
* If burst tracking is enabled, but you want to dynamically suppress either log output, you need merely add a &amp;quot;log-messages&amp;quot; section to you app&#039;s LiveConfig file, add a key for the log message (&amp;quot;logMessageBurstStats&amp;quot; and &amp;quot;logMessageBurstData&amp;quot;, respectively) and set &amp;quot;use-syslog&amp;quot; to integer 0.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
2010-02-09T04:47:54Z INFO: log: LLLOGMESSAGE (0) logMessageBurstStats {&#039;data_points&#039;:i1, &#039;frame_time_dur&#039;:r0.12202, &#039;max_message_break_duration&#039;:r0.1219, &#039;max_message_burst_count&#039;:i0, &#039;max_message_burst_duration&#039;:r0, &#039;mode&#039;:&#039;worker&#039;, &#039;total_message_break_duration&#039;:r0.1219, &#039;total_message_burst_duration&#039;:r0, &#039;total_message_count&#039;:i0, &#039;total_message_throughput_rate&#039;:r0}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Homework ==&lt;br /&gt;
* I&#039;ve only looked at the dataserver. What would the viewer message system output look like?&lt;br /&gt;
* What is the highest message latency that you&#039;ve seen?&lt;br /&gt;
* What in-world experience corresponds to what burst statistics?&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=698032</id>
		<title>LLMessageSystem Burst Metrics</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=698032"/>
		<updated>2010-01-05T22:05:29Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Why care about message processing? ==&lt;br /&gt;
&lt;br /&gt;
The dataserver receives a message, makes a database query or two, then sends a response. The next message isn&#039;t received until the response is sent. LLMessageSystem in other LLApp instances is used in a similar way - receive message, do processing, receive next message. The question becomes, what is the longest amount of time that a message has to wait to be processed? In many instances, this wait manifests itself as &amp;quot;lag&amp;quot;, and in the worst cases can result in timeouts and failed operations.&lt;br /&gt;
&lt;br /&gt;
== What do we want to know about messages? ==&lt;br /&gt;
&lt;br /&gt;
There are several concerns. Among the reasons this metric was added:&lt;br /&gt;
* How much longer is response time when database network latency is increased? (dataserver specific)&lt;br /&gt;
* What is gridwide message response time? For which application?&lt;br /&gt;
&lt;br /&gt;
Ideally, we would like to be able to make a list of information about each message:&lt;br /&gt;
* time received&lt;br /&gt;
* time processing started&lt;br /&gt;
* time processing finished&lt;br /&gt;
&lt;br /&gt;
In the case of the dataserver, over a specified time period the maximum time processing finished minus time received would be the worst case of message latency on that app. Think about this instance:&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_1.png]]&lt;br /&gt;
&lt;br /&gt;
Message E has the highest response latency - it wasn&#039;t done processing until 15ms after it was received.&lt;br /&gt;
&lt;br /&gt;
== The way the world actually works ==&lt;br /&gt;
&lt;br /&gt;
Unfortunately, with the way the message system currently works, there is no way to tell when a message was received. Worse, the packet buffer is extremely small and there is no way to tell if a message is dropped. Let&#039;s run through the above example in a more realistic environment.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_2.png]]&lt;br /&gt;
&lt;br /&gt;
Message A, B, C received in the same order, but C doesn&#039;t fit in the buffer, so is silently dropped. In this case we&#039;re assuming the sender will re-send after a certain time if an ACK isn&#039;t sent back. For the sake of the example, assume an ACK is sent right when a message begins processing, and resends are at 4ms. (it&#039;s more complicated than this, but this example is far more convoluted than the previous one already.)&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_3.png]]&lt;br /&gt;
&lt;br /&gt;
Time 4 comes around, A is pulled out of the buffer for processing, B moves forward in the incoming queue, and D is received. E is dropped, because by the time 5ms rolls around, the buffer is full again. B is resent because it hasn&#039;t been ACK&#039;d by 6ms - A is still processing until 7ms. The resend of B happens to a full buffer, and is dropped.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_4.png]]&lt;br /&gt;
&lt;br /&gt;
At the tick of 8ms message B is pulled in for processing, and the resend of C hits the buffer. Before B is done processing, E gets resent, but dropped again.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_5.png]]&lt;br /&gt;
&lt;br /&gt;
By the time D gets pulled in, the third E comes around and makes it to the buffer. There are no more new packets in the rest of the timeframe we&#039;re looking at, so we can see what times all of these packets came in and out.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_6.png]]&lt;br /&gt;
&lt;br /&gt;
Looks a little different than the ideal example, but the sum of the processing times remains the same. The receiving application was constantly busy in either case. The worst case wait is still message E and is also matched by C - 15ms (20 - 5, and 18 - 3, respectively).&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_7.png]]&lt;br /&gt;
&lt;br /&gt;
The end result is the same as if all of the messages had arrived at once. And we&#039;ve got a little bit more information in the diagrams than there is in the system itself - remember, there&#039;s no way to tell what the actual arrival times are. Hence, from the system, we can&#039;t tell the difference between this case and the previous case.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_8.png]]&lt;br /&gt;
&lt;br /&gt;
This is all the information we have - we may know a message is a resend, but we don&#039;t know when the original was intended to be received.&lt;br /&gt;
&lt;br /&gt;
== The Burst, defined ==&lt;br /&gt;
&lt;br /&gt;
This brings us to the concept of the message burst. If we started processing messages at 4ms, and stopped at 20ms, we know that the theoretical worst case would be if all the messages arrived simultaneously the last message would be waiting 16ms for a reply. That&#039;s worse than the truth, but it&#039;s the closest thing we have. There&#039;s also another approximation - that we&#039;re always processing messages, and they don&#039;t have to wait long to start processing (clearly not the case for packet A).&lt;br /&gt;
&lt;br /&gt;
A burst is this constant arrival of packets. It ends when the buffer is found to be empty. Second Life backend traffic tends to be very bursty with long break periods. Unfortunately, these bursts can last many full seconds, causing terrible lag. This metric, combined with the many others that we already have, should give us a better idea about what our current message latency is today, and if changes we make help or hurt it. It&#039;s just one part of the connection, but hopefully it helps.&lt;br /&gt;
&lt;br /&gt;
== Implementation details ==&lt;br /&gt;
&lt;br /&gt;
* Burst metrics are disabled by default, because timer calls can be expensive - 12ns * 4 may be significant if you are expecting to process several messages per 1ms!&lt;br /&gt;
* The bursts are recorded as matching lists of the duration of the burst and the count of messages in the burst.&lt;br /&gt;
* The metrics are available both as calculated statistics, and raw data (if you have need of more accurate stats)&lt;br /&gt;
* If burst tracking is enabled, but you want to dynamically suppress either log output, you need merely add a &amp;quot;log-messages&amp;quot; section to you app&#039;s LiveConfig file, add a key for the log message (&amp;quot;logMessageBurstStats&amp;quot; and &amp;quot;logMessageBurstData&amp;quot;, respectively) and set &amp;quot;use-syslog&amp;quot; to integer 0.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Forthcoming.&lt;br /&gt;
&lt;br /&gt;
== Homework ==&lt;br /&gt;
* I&#039;ve only looked at the dataserver. What would the viewer message system output look like?&lt;br /&gt;
* What is the highest message latency that you&#039;ve seen?&lt;br /&gt;
* What in-world experience corresponds to what burst statistics?&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=698022</id>
		<title>LLMessageSystem Burst Metrics</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=698022"/>
		<updated>2010-01-05T21:59:11Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Why care about message processing? ==&lt;br /&gt;
&lt;br /&gt;
The dataserver receives a message, makes a database query or two, then sends a response. The next message isn&#039;t received until the response is sent. LLMessageSystem in other LLApp instances is used in a similar way - receive message, do processing, receive next message. The question becomes, what is the longest amount of time that a message has to wait to be processed? In many instances, this wait manifests itself as &amp;quot;lag&amp;quot;, and in the worst cases can result in timeouts and failed operations.&lt;br /&gt;
&lt;br /&gt;
== What do we want to know about messages? ==&lt;br /&gt;
&lt;br /&gt;
There are several concerns. Among the reasons this metric was added:&lt;br /&gt;
* How much longer is response time when database network latency is increased? (dataserver specific)&lt;br /&gt;
* What is gridwide message response time? For which application?&lt;br /&gt;
&lt;br /&gt;
Ideally, we would like to be able to make a list of information about each message:&lt;br /&gt;
* time received&lt;br /&gt;
* time processing started&lt;br /&gt;
* time processing finished&lt;br /&gt;
&lt;br /&gt;
In the case of the dataserver, over a specified time period the maximum time processing finished minus time received would be the worst case of message latency on that app. Think about this instance:&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_1.png]]&lt;br /&gt;
&lt;br /&gt;
Message E has the highest response latency - it wasn&#039;t done processing until 15ms after it was received.&lt;br /&gt;
&lt;br /&gt;
== The way the world actually works ==&lt;br /&gt;
&lt;br /&gt;
Unfortunately, with the way the message system currently works, there is no way to tell when a message was received. Worse, the packet buffer is extremely small and there is no way to tell if a message is dropped. Let&#039;s run through the above example in a more realistic environment.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_2.png]]&lt;br /&gt;
&lt;br /&gt;
Message A, B, C received in the same order, but C doesn&#039;t fit in the buffer, so is silently dropped. In this case we&#039;re assuming the sender will re-send after a certain time if an ACK isn&#039;t sent back. For the sake of the example, assume an ACK is sent right when a message begins processing, and resends are at 4ms. (it&#039;s more complicated than this, but this example is far more convoluted than the previous one already.)&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_3.png]]&lt;br /&gt;
&lt;br /&gt;
Time 4 comes around, A is pulled out of the buffer for processing, B moves forward in the incoming queue, and D is received. E is dropped, because by the time 5ms rolls around, the buffer is full again. B is resent because it hasn&#039;t been ACK&#039;d by 6ms - A is still processing until 7ms. The resend of B happens to a full buffer, and is dropped.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_4.png]]&lt;br /&gt;
&lt;br /&gt;
At the tick of 8ms message B is pulled in for processing, and the resend of C hits the buffer. Before B is done processing, E gets resent, but dropped again.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_5.png]]&lt;br /&gt;
&lt;br /&gt;
By the time D gets pulled in, the third E comes around and makes it to the buffer. There are no more new packets in the rest of the timeframe we&#039;re looking at, so we can see what times all of these packets came in and out.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_6.png]]&lt;br /&gt;
&lt;br /&gt;
Looks a little different than the ideal example, but the sum of the processing times remains the same. The receiving application was constantly busy in either case. The worst case wait is still message E and is also matched by C - 15ms (20 - 5, and 18 - 3, respectively).&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_7.png]]&lt;br /&gt;
&lt;br /&gt;
The end result is the same as if all of the messages had arrived at once. And we&#039;ve got a little bit more information in the diagrams than there is in the system itself - remember, there&#039;s no way to tell what the actual arrival times are. Hence, from the system, we can&#039;t tell the difference between this case and the previous case.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_8.png]]&lt;br /&gt;
&lt;br /&gt;
This is all the information we have - we may know a message is a resend, but we don&#039;t know when the original was intended to be received.&lt;br /&gt;
&lt;br /&gt;
== The Burst, defined ==&lt;br /&gt;
&lt;br /&gt;
This brings us to the concept of the message burst. If we started processing messages at 4ms, and stopped at 20ms, we know that the theoretical worst case would be if all the messages arrived simultaneously the last message would be waiting 16ms for a reply. That&#039;s worse than the truth, but it&#039;s the closest thing we have. There&#039;s also another approximation - that we&#039;re always processing messages, and they don&#039;t have to wait long to start processing (clearly not the case for packet A).&lt;br /&gt;
&lt;br /&gt;
A burst is this constant arrival of packets. It ends when the buffer is found to be empty. Second Life backend traffic tends to be very bursty with long break periods. Unfortunately, these bursts can last many full seconds, causing terrible lag. This metric, combined with the many others that we already have, should give us a better idea about what our current message latency is today, and if changes we make help or hurt it. It&#039;s just one part of the connection, but hopefully it helps.&lt;br /&gt;
&lt;br /&gt;
== Implementation details ==&lt;br /&gt;
&lt;br /&gt;
* Burst metrics are disabled by default, because timer calls can be expensive - 12ns * 4 may be significant if you are expecting to process several messages per 1ms!&lt;br /&gt;
* The bursts are recorded as matching lists of the duration of the burst and the count of messages in the burst.&lt;br /&gt;
* The metrics are available both as calculated statistics, and raw data (if you have need of more accurate stats)&lt;br /&gt;
* If burst tracking is enabled, but you want to dynamically suppress either log output, you need merely add a &amp;quot;log-messages&amp;quot; section to you app&#039;s LiveConfig file, add a key for the log message (&amp;quot;logMessageBurstStats&amp;quot; and &amp;quot;logMessageBurstData&amp;quot;, respectively) and set &amp;quot;use-syslog&amp;quot; to integer 0.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Forthcoming.&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_8.png&amp;diff=698012</id>
		<title>File:MessageBurstTiming 8.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_8.png&amp;diff=698012"/>
		<updated>2010-01-05T21:55:48Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_7.png&amp;diff=698002</id>
		<title>File:MessageBurstTiming 7.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_7.png&amp;diff=698002"/>
		<updated>2010-01-05T21:55:35Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_6.png&amp;diff=697992</id>
		<title>File:MessageBurstTiming 6.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_6.png&amp;diff=697992"/>
		<updated>2010-01-05T21:54:30Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_5.png&amp;diff=697982</id>
		<title>File:MessageBurstTiming 5.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_5.png&amp;diff=697982"/>
		<updated>2010-01-05T21:54:17Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_4.png&amp;diff=697972</id>
		<title>File:MessageBurstTiming 4.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_4.png&amp;diff=697972"/>
		<updated>2010-01-05T21:54:04Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_3.png&amp;diff=697962</id>
		<title>File:MessageBurstTiming 3.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_3.png&amp;diff=697962"/>
		<updated>2010-01-05T21:53:47Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_2.png&amp;diff=697952</id>
		<title>File:MessageBurstTiming 2.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_2.png&amp;diff=697952"/>
		<updated>2010-01-05T21:53:22Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_1.png&amp;diff=697942</id>
		<title>File:MessageBurstTiming 1.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=File:MessageBurstTiming_1.png&amp;diff=697942"/>
		<updated>2010-01-05T21:52:12Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=697932</id>
		<title>LLMessageSystem Burst Metrics</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=697932"/>
		<updated>2010-01-05T21:51:18Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Why care about message processing? ==&lt;br /&gt;
&lt;br /&gt;
The dataserver receives a message, makes a database query or two, then sends a response. The next message isn&#039;t received until the response is sent. LLMessageSystem in other LLApp instances is used in a similar way - receive message, do processing, receive next message. The question becomes, what is the longest amount of time that a message has to wait to be processed? In many instances, this wait manifests itself as &amp;quot;lag&amp;quot;, and in the worst cases can result in timeouts and failed operations.&lt;br /&gt;
&lt;br /&gt;
== What do we want to know about messages? ==&lt;br /&gt;
&lt;br /&gt;
There are several concerns. Among the reasons this metric was added:&lt;br /&gt;
* How much longer is response time when database network latency is increased? (dataserver specific)&lt;br /&gt;
* What is gridwide message response time? For which application?&lt;br /&gt;
&lt;br /&gt;
Ideally, we would like to be able to make a list of information about each message:&lt;br /&gt;
* time received&lt;br /&gt;
* time processing started&lt;br /&gt;
* time processing finished&lt;br /&gt;
&lt;br /&gt;
In the case of the dataserver, over a specified time period the maximum time processing finished minus time received would be the worst case of message latency on that app. Think about this instance:&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_1.png]]&lt;br /&gt;
&lt;br /&gt;
Message E has the highest response latency - it wasn&#039;t done processing until 15ms after it was received.&lt;br /&gt;
&lt;br /&gt;
== The way the world actually works ==&lt;br /&gt;
&lt;br /&gt;
Unfortunately, with the way the message system currently works, there is no way to tell when a message was received. Worse, the packet buffer is extremely small and there is no way to tell if a message is dropped. Let&#039;s run through the above example in a more realistic environment.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_2.png]]&lt;br /&gt;
&lt;br /&gt;
Message A, B, C received in the same order, but C doesn&#039;t fit in the buffer, so is silently dropped. In this case we&#039;re assuming the sender will re-send after a certain time if an ACK isn&#039;t sent back. For the sake of the example, assume an ACK is sent right when a message begins processing, and resends are at 4ms. (it&#039;s more complicated than this, but this example is far more convoluted than the previous one already.)&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_3.png]]&lt;br /&gt;
&lt;br /&gt;
Time 4 comes around, A is pulled out of the buffer for processing, B moves forward in the incoming queue, and D is received. E is dropped, because by the time 5ms rolls around, the buffer is full again. B is resent because it hasn&#039;t been ACK&#039;d by 6ms - A is still processing until 7ms. The resend of B happens to a full buffer, and is dropped.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_4.png]]&lt;br /&gt;
&lt;br /&gt;
At the tick of 8ms message B is pulled in for processing, and the resend of C hits the buffer. Before B is done processing, E gets resent, but dropped again.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_5.png]]&lt;br /&gt;
&lt;br /&gt;
By the time D gets pulled in, the third E comes around and makes it to the buffer. There are no more new packets in the rest of the timeframe we&#039;re looking at, so we can see what times all of these packets came in and out.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_6.png]]&lt;br /&gt;
&lt;br /&gt;
Looks a little different than the ideal example, but the sum of the processing times remains the same. The receiving application was constantly busy in either case. The worst case wait is still message E and is also matched by C - 15ms (20 - 5, and 18 - 3, respectively).&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_7.png]]&lt;br /&gt;
&lt;br /&gt;
The end result is the same as if all of the messages had arrived at once. And we&#039;ve got a little bit more information in the diagrams than there is in the system itself - remember, there&#039;s no way to tell what the actual arrival times are. Hence, from the system, we can&#039;t tell the difference between this case and the previous case.&lt;br /&gt;
&lt;br /&gt;
[[Image:MessageBurstTiming_8.png]]&lt;br /&gt;
&lt;br /&gt;
This is all the information we have - we may know a message is a resend, but we don&#039;t know when the original was intended to be received.&lt;br /&gt;
&lt;br /&gt;
== The Burst, defined ==&lt;br /&gt;
&lt;br /&gt;
This brings us to the concept of the message burst. If we started processing messages at 4ms, and stopped at 20ms, we know that the theoretical worst case would be if all the messages arrived simultaneously the last message would be waiting 16ms for a reply. That&#039;s worse than the truth, but it&#039;s the closest thing we have. There&#039;s also another approximation - that we&#039;re always processing messages, and they don&#039;t have to wait long to start processing (clearly not the case for packet A).&lt;br /&gt;
&lt;br /&gt;
A burst is this constant arrival of packets. It ends when the buffer is found to be empty. Second Life backend traffic tends to be very bursty with long break periods. Unfortunately, these bursts can last many full seconds, causing terrible lag. This metric, combined with the many others that we already have, should give us a better idea about what our current message latency is today, and if changes we make help or hurt it. It&#039;s just one part of the connection, but hopefully it helps.&lt;br /&gt;
&lt;br /&gt;
== Implementation details ==&lt;br /&gt;
&lt;br /&gt;
* Burst metrics are disabled by default, because timer calls can be expensive - 12ns * 4 may be significant if you are expecting to process several messages per 1ms!&lt;br /&gt;
* The bursts are recorded as matching lists of the duration of the burst and the count of messages in the burst.&lt;br /&gt;
* The metrics are available both as calculated statistics, and raw data (if you have need of more accurate stats)&lt;br /&gt;
* If burst tracking is enabled, but you want to dynamically suppress either log output, you need merely add a &amp;quot;log-messages&amp;quot; section to you app&#039;s LiveConfig file, add a key for the log message (&amp;quot;logMessageBurstStats&amp;quot; and &amp;quot;logMessageBurstData&amp;quot;, respectively) and set &amp;quot;use-syslog&amp;quot; to integer 0.&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=671273</id>
		<title>LLMessageSystem Burst Metrics</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LLMessageSystem_Burst_Metrics&amp;diff=671273"/>
		<updated>2009-11-24T21:47:02Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: Created page with &amp;#039;This is a placeholder page for LLMessageSystem Burst Metrics. I&amp;#039;m drafting this privately, and will post it when it starts to look useful. If it&amp;#039;s after 2009-12-15, please ping m...&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a placeholder page for LLMessageSystem Burst Metrics. I&#039;m drafting this privately, and will post it when it starts to look useful. If it&#039;s after 2009-12-15, please ping me (Poppy Linden) for this info! Until then search for &amp;quot;burst&amp;quot; in llmessage to find the code.&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Logging_System_Overview&amp;diff=502133</id>
		<title>Logging System Overview</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Logging_System_Overview&amp;diff=502133"/>
		<updated>2009-10-02T19:36:03Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: Created page with &amp;#039;This document explains both the usage of our log message system in code and how to control it at runtime to vary the granularity of logging that is actually done.  :Original auth...&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document explains both the usage of our log message system in code and how to control it at runtime to vary the granularity of logging that is actually done.&lt;br /&gt;
&lt;br /&gt;
:Original author is BigPapi Linden, I&#039;m just copying the doc from internal -&amp;gt; external. ([[User:Poppy Linden|Poppy Linden]] 19:36, 2 October 2009 (UTC))&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
All developer functionality is enabled by &amp;quot;&#039;&#039;&#039;llerror.h&#039;&#039;&#039;&amp;quot; (in llcommon).  &lt;br /&gt;
&lt;br /&gt;
All runtime changing of logging granularity is done by editing &amp;quot;&#039;&#039;&#039;logcontrol.xml&#039;&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;&#039;logcontrol-dev.xml&#039;&#039;&#039;&amp;quot;, which are located in the &amp;quot;&#039;&#039;&#039;app_settings/&#039;&#039;&#039;&amp;quot; directory for the viewer and in &amp;quot;&#039;&#039;&#039;/opt/linden/etc/&#039;&#039;&#039;&amp;quot; for the server (&amp;quot;&#039;&#039;&#039;&amp;lt;branch&amp;gt;/etc/&#039;&#039;&#039;&amp;quot; on Windows).&lt;br /&gt;
&lt;br /&gt;
In order to get the maximum utility out of the log system, you should make sure your classes include &amp;quot;&#039;&#039;&#039;LOG_CLASS&#039;&#039;&#039;(LLFoo);&amp;quot; in the private section of your class declaration.  For example:&lt;br /&gt;
&lt;br /&gt;
    class LLFoo&lt;br /&gt;
    {&lt;br /&gt;
        &#039;&#039;&#039;LOG_CLASS&#039;&#039;&#039;(LLFoo);&lt;br /&gt;
    public:&lt;br /&gt;
        ...&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Output==&lt;br /&gt;
For the viewer, log output ends up in &amp;lt;tt&amp;gt;LL_PATH_APP_SETTINGS/logs/SecondLife.log&amp;lt;/tt&amp;gt;, where LL_PATH_APP_SETTINGS is &amp;lt;tt&amp;gt;%APPDATA%\SecondLife\&amp;lt;/tt&amp;gt; on Windows, &amp;lt;tt&amp;gt;$HOME/Library/Application Support/SecondLife/&amp;lt;/tt&amp;gt; on Mac, and &amp;lt;tt&amp;gt;$HOME/.secondlife/&amp;lt;/tt&amp;gt; on Linux.&lt;br /&gt;
&lt;br /&gt;
For the server, log output ends up in &amp;lt;tt&amp;gt;/var/log/indra.log&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Logging Macros =&lt;br /&gt;
&lt;br /&gt;
The old &amp;quot;&#039;&#039;&#039;llerrs&#039;&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;&#039;llwarns&#039;&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;&#039;llinfos&#039;&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;&#039;lldebugs&#039;&#039;&#039;&amp;quot;, and &amp;quot;&#039;&#039;&#039;llendl&#039;&#039;&#039;&amp;quot; logging macros are &#039;&#039;&#039;deprecated&#039;&#039;&#039;, but still work for backwards compatibility.  The new ones are capitalized per our compiler preprocessor directives naming conventions in our [[Coding_Standard#Naming_Convention|Coding Standards]].&lt;br /&gt;
&lt;br /&gt;
The new base logging macros allow you to optionally add one or two arbitrary string tags to the log message (a &amp;quot;broad&amp;quot; scope tag and a &amp;quot;narrow&amp;quot; scope tag), which then allows you to enable or disable log messages at runtime based on their tag (see &#039;&#039;&#039;&amp;lt;key&amp;gt;tags&amp;lt;/key&amp;gt;&#039;&#039;&#039; block in sample &amp;quot;&#039;&#039;&#039;logcontrol.xml&#039;&#039;&#039;&amp;quot; [[Logging_System_Overview#Varying_amount_of_logging_at_runtime_.28logcontrol.xml.29|Here]]).  NULL can be passed in to the macro if you &#039;&#039;&#039;REALLY&#039;&#039;&#039; don&#039;t want to tag a message, but it only takes a second and will make logging much more useful for all of us (think of the children).  &lt;br /&gt;
&lt;br /&gt;
The new base macros are used as follows:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;&#039;LL_DEBUGS&#039;&#039;&#039;(&amp;quot;BroadScopeTag&amp;quot;) &amp;lt;&amp;lt; &amp;quot;A debug level log message&amp;quot;   &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;   // &#039;&#039;&#039;NOTE:&#039;&#039;&#039; This is a macro, not a string stream.  The &amp;quot;&#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;&amp;quot; is required.&lt;br /&gt;
    &#039;&#039;&#039;LL_INFOS&#039;&#039;&#039;(&amp;quot;BroadScopeTag&amp;quot;)  &amp;lt;&amp;lt; &amp;quot;An info level log message&amp;quot;   &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;&lt;br /&gt;
    &#039;&#039;&#039;LL_WARNS&#039;&#039;&#039;(&amp;quot;BroadScopeTag&amp;quot;)  &amp;lt;&amp;lt; &amp;quot;A warning level log message&amp;quot; &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;&lt;br /&gt;
    &#039;&#039;&#039;LL_ERRS&#039;&#039;&#039;(&amp;quot;BroadScopeTag&amp;quot;)   &amp;lt;&amp;lt; &amp;quot;An error level log message&amp;quot;  &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;    // &#039;&#039;&#039;NOTE:&#039;&#039;&#039; &#039;&#039;&#039;LL_ERRS&#039;&#039;&#039; force a crash of the viewer.&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Note:&#039;&#039;&#039; Tags should be formatted in [[Logging_System_Overview#Tag_Formatting|CamelCase]]&lt;br /&gt;
&lt;br /&gt;
The logging macros behave like iostreams, and can have anything appended to them that can be appended to an iostream.&lt;br /&gt;
&lt;br /&gt;
= Multiple Tag Logging Macros =&lt;br /&gt;
&lt;br /&gt;
There also exist versions of the macros that allow you to bind 2 string tags to a log message (a &amp;quot;broad&amp;quot; scope tag and a &amp;quot;narrow&amp;quot; scope tag), which is very useful when you want to have both high and low granularity for tagging a log message (for example &amp;quot;AppInit&amp;quot; and &amp;quot;SystemInfo&amp;quot;, where &amp;quot;AppInit&amp;quot; is the broad scope tag and describes the long Application Initialization process of which the narrow scope tag &amp;quot;SystemInfo&amp;quot; printing is a small portion).&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;&#039;LL_DEBUGS2&#039;&#039;&#039;(&amp;quot;BroadScopeTag&amp;quot;, &amp;quot;NarrowScopeTag&amp;quot;) &amp;lt;&amp;lt; &amp;quot;A debug level log message&amp;quot;   &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;   // &#039;&#039;&#039;NOTE:&#039;&#039;&#039; This is a macro, not a string stream.  The &amp;quot;&#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;&amp;quot; is required.&lt;br /&gt;
    &#039;&#039;&#039;LL_INFOS2&#039;&#039;&#039;(&amp;quot;BroadScopeTag&amp;quot;, &amp;quot;NarrowScopeTag&amp;quot;)  &amp;lt;&amp;lt; &amp;quot;An info level log message&amp;quot;   &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;&lt;br /&gt;
    &#039;&#039;&#039;LL_WARNS2&#039;&#039;&#039;(&amp;quot;BroadScopeTag&amp;quot;, &amp;quot;NarrowScopeTag&amp;quot;)  &amp;lt;&amp;lt; &amp;quot;A warning level log message&amp;quot; &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;&lt;br /&gt;
    &#039;&#039;&#039;LL_ERRS2&#039;&#039;&#039;(&amp;quot;BroadScopeTag&amp;quot;, &amp;quot;NarrowScopeTag&amp;quot;)   &amp;lt;&amp;lt; &amp;quot;An error level log message&amp;quot;  &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;    // &#039;&#039;&#039;NOTE:&#039;&#039;&#039; &#039;&#039;&#039;LL_ERRS2&#039;&#039;&#039; force a crash of the viewer.&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Note:&#039;&#039;&#039; Tags should be formatted in [[Logging_System_Overview#Tag_Formatting|CamelCase]]&lt;br /&gt;
&lt;br /&gt;
= Logging a repeating message only once =&lt;br /&gt;
&lt;br /&gt;
There are currently some log messages that if triggered end up spamming the log file with the same exact message string over and over.  As a result, we now also have the ability to use a special macro that keeps these messages from filling up the log and drowning out other messages.  These macros will print the message the first time it gets triggered and prepends &amp;quot;ONCE: &amp;quot; to the message string.  Any further time it is triggered &#039;&#039;&#039;with the same message&#039;&#039;&#039; it will not print it, unless it is the 10th, 50th, or every 100th time there after that it is encountered.  Then, it updates you by prepending &amp;quot;ONCE (Nth time seen): &amp;quot; to the log message, where N is the number of times it has been seen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; This works on unique final log messages, so log messages that depend on one or more variables have the final output treated as different messages if any part of the string changes.  Thus, you should not use _ONCE macros for log messages that will print many times but with different messages, as this would be slightly slower and would slowly fill up a std::map with memory occupying junk.&lt;br /&gt;
&lt;br /&gt;
   &#039;&#039;&#039;LL_DEBUGS_ONCE&#039;&#039;&#039;(&amp;quot;BroadScopeTag&amp;quot;) &amp;lt;&amp;lt; &amp;quot;A debug level log message&amp;quot;   &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;   // NOTE: This is a macro, not a string stream.  The &amp;quot;&#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;&amp;quot; is required.&lt;br /&gt;
   &#039;&#039;&#039;LL_INFOS_ONCE&#039;&#039;&#039;(&amp;quot;BroadScopeTag&amp;quot;)  &amp;lt;&amp;lt; &amp;quot;An info level log message&amp;quot;   &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;&lt;br /&gt;
   &#039;&#039;&#039;LL_WARNS_ONCE&#039;&#039;&#039;(&amp;quot;BroadScopeTag&amp;quot;)  &amp;lt;&amp;lt; &amp;quot;A warning level log message&amp;quot; &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;&lt;br /&gt;
   &lt;br /&gt;
   &#039;&#039;&#039;LL_DEBUGS2_ONCE&#039;&#039;&#039;(&amp;quot;BroadScopeTag&amp;quot;, &amp;quot;NarrowScopeTag&amp;quot;) &amp;lt;&amp;lt; &amp;quot;A debug level log message&amp;quot;   &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;   // NOTE: This is a macro, not a string stream.  The &amp;quot;&#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;&amp;quot; is required.&lt;br /&gt;
   &#039;&#039;&#039;LL_INFOS2_ONCE&#039;&#039;&#039;(&amp;quot;BroadScopeTag&amp;quot;, &amp;quot;NarrowScopeTag&amp;quot;)  &amp;lt;&amp;lt; &amp;quot;An info level log message&amp;quot;   &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;&lt;br /&gt;
   &#039;&#039;&#039;LL_WARNS2_ONCE&#039;&#039;&#039;(&amp;quot;BroadScopeTag&amp;quot;, &amp;quot;NarrowScopeTag&amp;quot;)  &amp;lt;&amp;lt; &amp;quot;A warning level log message&amp;quot; &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;&lt;br /&gt;
   &lt;br /&gt;
   &#039;&#039;&#039;Note:&#039;&#039;&#039; Tags should be formatted in [[Logging_System_Overview#Tag_Formatting|CamelCase]]&lt;br /&gt;
&lt;br /&gt;
For example, the following log message:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;&#039;LL_WARNS_ONCE&#039;&#039;&#039;(&amp;quot;Drawable&amp;quot;) &amp;lt;&amp;lt; &amp;quot;Drawable becomes static with active parent!&amp;quot; &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
would print the following messages to &amp;quot;&#039;&#039;&#039;SecondLife.log&#039;&#039;&#039;&amp;quot; if it kept getting called repeatedly:&lt;br /&gt;
&lt;br /&gt;
    WARNING: LLDrawable::makeStatic: ONCE: Drawable becomes static with active parent! &lt;br /&gt;
    WARNING: LLDrawable::makeStatic: ONCE (10th time seen): Drawable becomes static with active parent! &lt;br /&gt;
    WARNING: LLDrawable::makeStatic: ONCE (50th time seen): Drawable becomes static with active parent! &lt;br /&gt;
    WARNING: LLDrawable::makeStatic: ONCE (100th time seen): Drawable becomes static with active parent! &lt;br /&gt;
    WARNING: LLDrawable::makeStatic: ONCE (200th time seen): Drawable becomes static with active parent! &lt;br /&gt;
    ... etc ...&lt;br /&gt;
&lt;br /&gt;
= Tag Formatting =&lt;br /&gt;
&lt;br /&gt;
Tags should be formatted in &amp;quot;&#039;&#039;&#039;CamelCase&#039;&#039;&#039;&amp;quot;, such as &amp;quot;RenderInit&amp;quot; and &amp;quot;TextureCache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Varying amount of logging at runtime (logcontrol.xml) =&lt;br /&gt;
&lt;br /&gt;
Upon initialization of the application, the logging system tries to load a &amp;quot;&#039;&#039;&#039;logcontrol-dev.xml&#039;&#039;&#039;&amp;quot; file and if it doesn&#039;t exist, it loads &amp;quot;&#039;&#039;&#039;logcontrol.xml&#039;&#039;&#039;&amp;quot; instead.  These files are located in the &amp;quot;app_settings/&amp;quot; directory for the viewer and in &amp;quot;/opt/linden/etc/&amp;quot; for the server (&amp;quot;&amp;lt;branch&amp;gt;/etc/&amp;quot; on Windows).  Whichever file is loaded gets checked for changes every couple of seconds and reloaded if necessary.  The following is a sample &#039;&#039;&#039;logcontrol.xml&#039;&#039;&#039; file that sets the default loggging level to WARN and then conditionally turns on some warnings at INFO level and DEBUG level based on &amp;quot;function name&amp;quot;, &amp;quot;class name&amp;quot;, &amp;quot;file name&amp;quot;, and &amp;quot;tag&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Sample &amp;quot;&#039;&#039;&#039;logcontrol.xml&#039;&#039;&#039;&amp;quot; file:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;llsd&amp;gt;&lt;br /&gt;
   &amp;lt;map&amp;gt;&lt;br /&gt;
       &amp;lt;&#039;&#039;&#039;!--&#039;&#039;&#039; default-level can be &#039;&#039;&#039;ALL&#039;&#039;&#039;, &#039;&#039;&#039;DEBUG&#039;&#039;&#039;, &#039;&#039;&#039;INFO&#039;&#039;&#039;, &#039;&#039;&#039;WARN&#039;&#039;&#039;, &#039;&#039;&#039;ERROR&#039;&#039;&#039;, or &#039;&#039;&#039;NONE&#039;&#039;&#039; &#039;&#039;&#039;--&#039;&#039;&#039;&amp;gt;&lt;br /&gt;
       &amp;lt;key&amp;gt;&#039;&#039;&#039;default-level&#039;&#039;&#039;&amp;lt;/key&amp;gt;    &amp;lt;string&amp;gt;&#039;&#039;&#039;WARN&#039;&#039;&#039;&amp;lt;/string&amp;gt;&lt;br /&gt;
       &amp;lt;key&amp;gt;&#039;&#039;&#039;print-location&#039;&#039;&#039;&amp;lt;/key&amp;gt;   &amp;lt;boolean&amp;gt;&#039;&#039;&#039;false&#039;&#039;&#039;&amp;lt;/boolean&amp;gt;&lt;br /&gt;
       &amp;lt;key&amp;gt;&#039;&#039;&#039;settings&#039;&#039;&#039;&amp;lt;/key&lt;br /&gt;
           &amp;lt;array&amp;gt;&lt;br /&gt;
               &amp;lt;map&amp;gt;&lt;br /&gt;
                   &amp;lt;key&amp;gt;&#039;&#039;&#039;level&#039;&#039;&#039;&amp;lt;/key&amp;gt;&amp;lt;string&amp;gt;&#039;&#039;&#039;INFO&#039;&#039;&#039;&amp;lt;/string&amp;gt;&lt;br /&gt;
                   &amp;lt;key&amp;gt;&#039;&#039;&#039;functions&#039;&#039;&#039;&amp;lt;/key&amp;gt;&lt;br /&gt;
                       &amp;lt;array&amp;gt;&lt;br /&gt;
                           &amp;lt;string&amp;gt;&#039;&#039;&#039;LLAgentInfo::handleImageRequest&#039;&#039;&#039;&amp;lt;/string&amp;gt;&lt;br /&gt;
                       &amp;lt;/array&amp;gt;&lt;br /&gt;
                   &amp;lt;key&amp;gt;&#039;&#039;&#039;classes&#039;&#039;&#039;&amp;lt;/key&amp;gt;&lt;br /&gt;
                       &amp;lt;array&amp;gt;&lt;br /&gt;
                           &amp;lt;string&amp;gt;&#039;&#039;&#039;LLBufferArray&#039;&#039;&#039;&amp;lt;/string&amp;gt;&lt;br /&gt;
                       &amp;lt;/array&amp;gt;&lt;br /&gt;
                   &amp;lt;key&amp;gt;&#039;&#039;&#039;files&#039;&#039;&#039;&amp;lt;/key&amp;gt;&lt;br /&gt;
                       &amp;lt;array&amp;gt;&lt;br /&gt;
                           &amp;lt;string&amp;gt;&#039;&#039;&#039;lldrawpoolavatar.cpp&#039;&#039;&#039;&amp;lt;/string&amp;gt;&lt;br /&gt;
                       &amp;lt;/array&amp;gt;&lt;br /&gt;
                   &amp;lt;key&amp;gt;&#039;&#039;&#039;tags&#039;&#039;&#039;&amp;lt;/key&amp;gt;&lt;br /&gt;
                       &amp;lt;array&amp;gt;&lt;br /&gt;
                           &amp;lt;string&amp;gt;&#039;&#039;&#039;AppInit&#039;&#039;&#039;&amp;lt;/string&amp;gt;&lt;br /&gt;
                           &amp;lt;string&amp;gt;&#039;&#039;&#039;TextureCache&#039;&#039;&#039;&amp;lt;/string&amp;gt;&lt;br /&gt;
                       &amp;lt;/array&amp;gt;&lt;br /&gt;
               &amp;lt;/map&amp;gt;&lt;br /&gt;
               &amp;lt;map&amp;gt;&lt;br /&gt;
                   &amp;lt;key&amp;gt;&#039;&#039;&#039;level&#039;&#039;&#039;&amp;lt;/key&amp;gt;&amp;lt;string&amp;gt;&#039;&#039;&#039;DEBUG&#039;&#039;&#039;&amp;lt;/string&amp;gt;&lt;br /&gt;
                   &amp;lt;key&amp;gt;&#039;&#039;&#039;functions&#039;&#039;&#039;&amp;lt;/key&amp;gt;&lt;br /&gt;
                       &amp;lt;array&amp;gt;&lt;br /&gt;
                       &amp;lt;/array&amp;gt;&lt;br /&gt;
                   &amp;lt;key&amp;gt;&#039;&#039;&#039;classes&#039;&#039;&#039;&amp;lt;/key&amp;gt;&lt;br /&gt;
                       &amp;lt;array&amp;gt;&lt;br /&gt;
                       &amp;lt;/array&amp;gt;&lt;br /&gt;
                   &amp;lt;key&amp;gt;&#039;&#039;&#039;files&#039;&#039;&#039;&amp;lt;/key&amp;gt;&lt;br /&gt;
                       &amp;lt;array&amp;gt;&lt;br /&gt;
                           &amp;lt;string&amp;gt;&#039;&#039;&#039;llbutton.cpp&#039;&#039;&#039;&amp;lt;/string&amp;gt;&lt;br /&gt;
                           &amp;lt;string&amp;gt;&#039;&#039;&#039;llcombobox.cpp&#039;&#039;&#039;&amp;lt;/string&amp;gt;&lt;br /&gt;
                       &amp;lt;/array&amp;gt;&lt;br /&gt;
                   &amp;lt;key&amp;gt;&#039;&#039;&#039;tags&#039;&#039;&#039;&amp;lt;/key&amp;gt;&lt;br /&gt;
                       &amp;lt;array&amp;gt;&lt;br /&gt;
                           &amp;lt;string&amp;gt;&#039;&#039;&#039;RenderInit&#039;&#039;&#039;&amp;lt;/string&amp;gt;&lt;br /&gt;
                       &amp;lt;/array&amp;gt;&lt;br /&gt;
               &amp;lt;/map&amp;gt;&lt;br /&gt;
           &amp;lt;/array&amp;gt;&lt;br /&gt;
   &amp;lt;/map&amp;gt;&lt;br /&gt;
   &amp;lt;/llsd&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Logging granularity conflict resolution =&lt;br /&gt;
&lt;br /&gt;
The logging system decides in the following order what logging granularity to apply to a message:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Default log level&#039;&#039;&#039; &amp;lt; &#039;&#039;&#039;BroadScopeTag&#039;&#039;&#039; &amp;lt; &#039;&#039;&#039;File Name&#039;&#039;&#039; &amp;lt; &#039;&#039;&#039;Class Name&#039;&#039;&#039; &amp;lt; &#039;&#039;&#039;Function Name&#039;&#039;&#039; &amp;lt; &#039;&#039;&#039;NarrowScopeTag&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Thus, highest priority level match found in &amp;quot;&#039;&#039;&#039;logcontrol.xml&#039;&#039;&#039;&amp;quot; is used to decide if a particular log message should be printed.  For example, if a given log message is of a class that has been set in &amp;quot;&#039;&#039;&#039;logcontrol.xml&#039;&#039;&#039;&amp;quot; to print all &#039;&#039;&#039;LL_DEBUGS()&#039;&#039;&#039; and below, but there is an entry for its function name that states to only print &#039;&#039;&#039;LL_WARNS()&#039;&#039;&#039; and below, then only &#039;&#039;&#039;LL_WARNS()&#039;&#039;&#039; and &#039;&#039;&#039;LL_ERRS()&#039;&#039;&#039; will be printed.&lt;br /&gt;
&lt;br /&gt;
= Continuing a log message after further computation =&lt;br /&gt;
&lt;br /&gt;
Use the &#039;&#039;&#039;LL_CONT&#039;&#039;&#039; macro if you need to do computation in the middle of a log message:&lt;br /&gt;
		&lt;br /&gt;
    &#039;&#039;&#039;LL_DEBUGS&#039;&#039;&#039;(&amp;quot;AgentGesture&amp;quot;) &amp;lt;&amp;lt; &amp;quot;the agent &amp;quot; &amp;lt;&amp;lt; agend_id;&lt;br /&gt;
    switch (f)&lt;br /&gt;
    {&lt;br /&gt;
        case FOP_SHRUGS:   &#039;&#039;&#039;LL_CONT&#039;&#039;&#039; &amp;lt;&amp;lt; &amp;quot;shrugs&amp;quot;;              break;&lt;br /&gt;
        case FOP_TAPS:     &#039;&#039;&#039;LL_CONT&#039;&#039;&#039; &amp;lt;&amp;lt; &amp;quot;points at &amp;quot; &amp;lt;&amp;lt; who;   break;&lt;br /&gt;
        case FOP_SAYS:     &#039;&#039;&#039;LL_CONT&#039;&#039;&#039; &amp;lt;&amp;lt; &amp;quot;says &amp;quot; &amp;lt;&amp;lt; message;    break;&lt;br /&gt;
    }&lt;br /&gt;
    &#039;&#039;&#039;LL_CONT&#039;&#039;&#039; &amp;lt;&amp;lt; &amp;quot; for &amp;quot; &amp;lt;&amp;lt; t &amp;lt;&amp;lt; &amp;quot; seconds&amp;quot; &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;   // Make sure to remember the &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039; at the end and &#039;&#039;&#039;ONLY&#039;&#039;&#039; at the end.&lt;br /&gt;
		&lt;br /&gt;
Such computation is done only if the message will be logged.&lt;br /&gt;
&lt;br /&gt;
This means that you can also use the macro functionality to conditionally call separate functions only if that granularity of logging is enabled, such as in the following example from llfeaturemanager.cpp:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;&#039;LL_DEBUGS&#039;&#039;&#039;(&amp;quot;RenderInit&amp;quot;) &amp;lt;&amp;lt; &amp;quot;After applying mask &amp;quot; &amp;lt;&amp;lt; mask.mName &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
        // Will conditionally call dump only if the above message will be logged, thanks &lt;br /&gt;
        // to it being wrapped by the &#039;&#039;&#039;LL_DEBUGS&#039;&#039;&#039; and &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039; macros.&lt;br /&gt;
        dump();&lt;br /&gt;
    &#039;&#039;&#039;LL_CONT&#039;&#039;&#039; &amp;lt;&amp;lt; &#039;&#039;&#039;LL_ENDL&#039;&#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Design Documents]]&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=442633</id>
		<title>User:Poppy Linden/PyOGP \ libdev Initial Setup Experience</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=442633"/>
		<updated>2009-07-29T01:19:52Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: /* random hacking */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;sequential, oldest first.&lt;br /&gt;
&lt;br /&gt;
== bootstrapping ==&lt;br /&gt;
* omg tons of docs&lt;br /&gt;
* omg repeats internally / externally... lemme fix that...&lt;br /&gt;
* code?&lt;br /&gt;
* ok, what deps are required? wait.. how does python pathing work? oh, i can just put it in my python_path, cool&lt;br /&gt;
* wait, this says i need to install a friggin million things.&lt;br /&gt;
* I Hate Everything Python Right Now.&lt;br /&gt;
* I bootstrapped a wicked python env in my homedir.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir -p ~/local/lib/python2.4/site-packages&lt;br /&gt;
vi ~/.bashrc &lt;br /&gt;
&amp;gt;&amp;gt; export PYTHONPATH=$PYTHONPATH:~/local/lib/python2.4/site-packages&lt;br /&gt;
&amp;gt;&amp;gt; export PATH=$PATH:/usr/local/bin:~/bin:~/local/bin&lt;br /&gt;
. ~/.bashrc &lt;br /&gt;
&lt;br /&gt;
curl -L &#039;http://pypi.python.org/packages/2.4/s/setuptools/setuptools-0.6c9-py2.4.egg#md5=260a2be2e5388d66bdaee06abec6342a&#039; &amp;gt; setuptools-0.6c9-py2.4.egg&lt;br /&gt;
sh setuptools-0.6c9-py2.4.egg --prefix=~/local&lt;br /&gt;
easy_install --prefix=~/local pip&lt;br /&gt;
easy_install --prefix=~/local virtualenv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ok, now what again? Oh yeah, virtualenv for pyogp... the point of this...&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** bin/python bootstrap.py&lt;br /&gt;
** bin/buildout -v&lt;br /&gt;
** oh, so virtualenv is preventing the very borknorking i am trying to prevent to my system. Fair game.&lt;br /&gt;
&lt;br /&gt;
== bootstrap / sanity verification ==&lt;br /&gt;
* bin/client_unittest&lt;br /&gt;
** FAILBOAT&lt;br /&gt;
** pip -E . install greenlet&lt;br /&gt;
** bin/client_unittest&lt;br /&gt;
** now a bunch of crazy shit instead of tracebacks, that&#039;s... good?&lt;br /&gt;
** 114 tests and 0 failures! that&#039;s good!&lt;br /&gt;
&lt;br /&gt;
== initial investigations ==&lt;br /&gt;
* vi src/pyogp.lib.base/pyogp/lib/base/tests/base.py&lt;br /&gt;
** everything starts with login, even with base. What about the delicious primitives i crave?&lt;br /&gt;
** ls -l is your friend. There are subfolders in src/pyogp.lib.base/pyogp/lib/base/, namely one named network, and one named message.&lt;br /&gt;
* reading tests is like looking at a tautology; they have no docs. &amp;quot;Yes, i bet that does in fact work that way.&amp;quot; What do I see to bootstrap an app?&lt;br /&gt;
* i say: &amp;quot;(i want to know what code to see to understand) how to init main, send a message, quit&amp;quot; enus: &amp;quot;well, region.py uses UDPDispatcher. i&#039;ve not tried using it w/o the entire context&amp;quot; &amp;quot;maybe test_udpconnection.py is a useful reference. it instantiates UDPDispatcher, against a mock host, and sends a message&amp;quot;&lt;br /&gt;
* enus: &amp;quot;the Message usage is changing soon. look at the Message() class.&amp;quot; &amp;quot;packets.py transforms representations of packet data into Message instqances, but packets.py is going away soon&amp;quot;&lt;br /&gt;
* there *really* needs to be a step-by-step to get bootstrapped, I hope this helps write that! I&#039;m still not writing &amp;quot;Hello World&amp;quot; with pyogp yet!&lt;br /&gt;
* test app, try 1&lt;br /&gt;
** mkdir test_dataserver; cd test_dataserver&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** RTFM: pip help install | less&lt;br /&gt;
** pip install -E . -e ../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk libdev ... FAIL&lt;br /&gt;
** OH WAIT the problem isn&#039;t the dir, it&#039;s the &amp;quot;libdev&amp;quot; afterwards&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk ... FAIL but a new error, no setup.py... wait a sec...&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/pyogp.lib.base/trunk/ ... WIN&lt;br /&gt;
* should work to just copy a unit test into my src/ dir, copying test_udpconnection.py as it sounds like a good start&lt;br /&gt;
* pip install -E . greenlet&lt;br /&gt;
* bin/python src/test_udpconnection.py ... aaaaaand... no output. Is that a good thing for a test?&lt;br /&gt;
* need some of this:&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    unittest.main()&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
* tests pass. Rad! Let&#039;s send some garbage.&lt;br /&gt;
&lt;br /&gt;
== learn to send messages ==&lt;br /&gt;
* pyogp.lib.base/pyogp/lib/base/message/circuit.py - the Host class looks a little thin; doesn&#039;t take a FQDN, just an IP addy?&lt;br /&gt;
* resetting the host in test_find_circuit in my modified copy of test_udpconnection.py doesn&#039;t seem to be hitting the desired host / port&lt;br /&gt;
* try to reverse-engineer class diagram using pylint and graphviz... hmm...&lt;br /&gt;
* finally get *something* - a couple circuits established with the UDPConnectionTest replacing the mock server with my code&lt;br /&gt;
* it&#039;s making me crazy that MockupTestServer and Client don&#039;t seem to map to a real object. It appears to be impossible to trivially modify test_udpconnection.py to connect to a real server instead of a mock.&lt;br /&gt;
* so after some tinkering, this works:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        p = packet_types.AvatarPropertiesRequestPacket()&lt;br /&gt;
        poppy = UUID()&lt;br /&gt;
        print dir(poppy)&lt;br /&gt;
        print poppy.uuid.bytes&lt;br /&gt;
        p.AgentData[&#039;AgentID&#039;] = poppy&lt;br /&gt;
        p.AgentData[&#039;SessionID&#039;] = UUID()&lt;br /&gt;
        p.AgentData[&#039;AvatarID&#039;] = poppy&lt;br /&gt;
        self.send_message(p, True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* need a coroutine to sit and wait for response, not that far yet&lt;br /&gt;
* much of this functionality is in region.py, should definitely be brought out and into the message package somehow&lt;br /&gt;
* chat with enus about branching, possibly mercurial?&lt;br /&gt;
* full test, with reliable acks:&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
    def test_asdf(self):                                                                                              &lt;br /&gt;
        # build message, send it                                                                                      &lt;br /&gt;
        packet = packet_types.AvatarPropertiesRequestPacket()                                                         &lt;br /&gt;
        poppy = UUID()                                                          &lt;br /&gt;
        packet.AgentData[&#039;AgentID&#039;] = poppy                                                                           &lt;br /&gt;
        packet.AgentData[&#039;SessionID&#039;] = UUID()                                                                        &lt;br /&gt;
        packet.AgentData[&#039;AvatarID&#039;] = poppy                                                                          &lt;br /&gt;
        #self.messenger.send_message(packet, self.host)                                                               &lt;br /&gt;
        self.messenger.send_reliable(packet, self.host, 0)                                                            &lt;br /&gt;
        # wait for Ack, socket timeout after 1s wait (1000ms)                                                         &lt;br /&gt;
        self.messenger.socket.settimeout(1.0)                                                                         &lt;br /&gt;
        msg_buf, msg_size = self.messenger.udp_client.receive_packet(self.messenger.socket)                           &lt;br /&gt;
        recv = self.messenger.receive_check(self.messenger.udp_client.get_sender(), msg_buf, msg_size)                &lt;br /&gt;
        if recv is None or recv.name != &#039;PacketAck&#039;:                                                                  &lt;br /&gt;
            self.fail(&amp;quot;no data waiting after 1s&amp;quot;)                                                                     &lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== random hacking ==&lt;br /&gt;
* can&#039;t seem to introspect then send all the packet types from dir() on pyogp.lib.base.message.packets&lt;br /&gt;
* that&#039;s gone, but no obvious way to get message from template...&lt;br /&gt;
* eventlet 0.8.12 cheeseshop install seems borked, using &#039;pip install -E . -f http://pypi.python.org/packages/source/e/eventlet/eventlet-0.8.11.tar.gz eventlet-0.8.11&#039;&lt;br /&gt;
* install nose: easy_install --prefix=~/local nose&lt;br /&gt;
* bin/python `which nosetests` src/*&lt;br /&gt;
* yeah, i want to keep a mercurial fork: hg convert http://svn.secondlife.com/svn/linden/projects/2008/pyogp/pyogp.lib.base/trunk&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=442312</id>
		<title>User:Poppy Linden/PyOGP \ libdev Initial Setup Experience</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=442312"/>
		<updated>2009-07-28T05:42:47Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: /* random hacking */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;sequential, oldest first.&lt;br /&gt;
&lt;br /&gt;
== bootstrapping ==&lt;br /&gt;
* omg tons of docs&lt;br /&gt;
* omg repeats internally / externally... lemme fix that...&lt;br /&gt;
* code?&lt;br /&gt;
* ok, what deps are required? wait.. how does python pathing work? oh, i can just put it in my python_path, cool&lt;br /&gt;
* wait, this says i need to install a friggin million things.&lt;br /&gt;
* I Hate Everything Python Right Now.&lt;br /&gt;
* I bootstrapped a wicked python env in my homedir.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir -p ~/local/lib/python2.4/site-packages&lt;br /&gt;
vi ~/.bashrc &lt;br /&gt;
&amp;gt;&amp;gt; export PYTHONPATH=$PYTHONPATH:~/local/lib/python2.4/site-packages&lt;br /&gt;
&amp;gt;&amp;gt; export PATH=$PATH:/usr/local/bin:~/bin:~/local/bin&lt;br /&gt;
. ~/.bashrc &lt;br /&gt;
&lt;br /&gt;
curl -L &#039;http://pypi.python.org/packages/2.4/s/setuptools/setuptools-0.6c9-py2.4.egg#md5=260a2be2e5388d66bdaee06abec6342a&#039; &amp;gt; setuptools-0.6c9-py2.4.egg&lt;br /&gt;
sh setuptools-0.6c9-py2.4.egg --prefix=~/local&lt;br /&gt;
easy_install --prefix=~/local pip&lt;br /&gt;
easy_install --prefix=~/local virtualenv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ok, now what again? Oh yeah, virtualenv for pyogp... the point of this...&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** bin/python bootstrap.py&lt;br /&gt;
** bin/buildout -v&lt;br /&gt;
** oh, so virtualenv is preventing the very borknorking i am trying to prevent to my system. Fair game.&lt;br /&gt;
&lt;br /&gt;
== bootstrap / sanity verification ==&lt;br /&gt;
* bin/client_unittest&lt;br /&gt;
** FAILBOAT&lt;br /&gt;
** pip -E . install greenlet&lt;br /&gt;
** bin/client_unittest&lt;br /&gt;
** now a bunch of crazy shit instead of tracebacks, that&#039;s... good?&lt;br /&gt;
** 114 tests and 0 failures! that&#039;s good!&lt;br /&gt;
&lt;br /&gt;
== initial investigations ==&lt;br /&gt;
* vi src/pyogp.lib.base/pyogp/lib/base/tests/base.py&lt;br /&gt;
** everything starts with login, even with base. What about the delicious primitives i crave?&lt;br /&gt;
** ls -l is your friend. There are subfolders in src/pyogp.lib.base/pyogp/lib/base/, namely one named network, and one named message.&lt;br /&gt;
* reading tests is like looking at a tautology; they have no docs. &amp;quot;Yes, i bet that does in fact work that way.&amp;quot; What do I see to bootstrap an app?&lt;br /&gt;
* i say: &amp;quot;(i want to know what code to see to understand) how to init main, send a message, quit&amp;quot; enus: &amp;quot;well, region.py uses UDPDispatcher. i&#039;ve not tried using it w/o the entire context&amp;quot; &amp;quot;maybe test_udpconnection.py is a useful reference. it instantiates UDPDispatcher, against a mock host, and sends a message&amp;quot;&lt;br /&gt;
* enus: &amp;quot;the Message usage is changing soon. look at the Message() class.&amp;quot; &amp;quot;packets.py transforms representations of packet data into Message instqances, but packets.py is going away soon&amp;quot;&lt;br /&gt;
* there *really* needs to be a step-by-step to get bootstrapped, I hope this helps write that! I&#039;m still not writing &amp;quot;Hello World&amp;quot; with pyogp yet!&lt;br /&gt;
* test app, try 1&lt;br /&gt;
** mkdir test_dataserver; cd test_dataserver&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** RTFM: pip help install | less&lt;br /&gt;
** pip install -E . -e ../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk libdev ... FAIL&lt;br /&gt;
** OH WAIT the problem isn&#039;t the dir, it&#039;s the &amp;quot;libdev&amp;quot; afterwards&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk ... FAIL but a new error, no setup.py... wait a sec...&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/pyogp.lib.base/trunk/ ... WIN&lt;br /&gt;
* should work to just copy a unit test into my src/ dir, copying test_udpconnection.py as it sounds like a good start&lt;br /&gt;
* pip install -E . greenlet&lt;br /&gt;
* bin/python src/test_udpconnection.py ... aaaaaand... no output. Is that a good thing for a test?&lt;br /&gt;
* need some of this:&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    unittest.main()&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
* tests pass. Rad! Let&#039;s send some garbage.&lt;br /&gt;
&lt;br /&gt;
== learn to send messages ==&lt;br /&gt;
* pyogp.lib.base/pyogp/lib/base/message/circuit.py - the Host class looks a little thin; doesn&#039;t take a FQDN, just an IP addy?&lt;br /&gt;
* resetting the host in test_find_circuit in my modified copy of test_udpconnection.py doesn&#039;t seem to be hitting the desired host / port&lt;br /&gt;
* try to reverse-engineer class diagram using pylint and graphviz... hmm...&lt;br /&gt;
* finally get *something* - a couple circuits established with the UDPConnectionTest replacing the mock server with my code&lt;br /&gt;
* it&#039;s making me crazy that MockupTestServer and Client don&#039;t seem to map to a real object. It appears to be impossible to trivially modify test_udpconnection.py to connect to a real server instead of a mock.&lt;br /&gt;
* so after some tinkering, this works:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        p = packet_types.AvatarPropertiesRequestPacket()&lt;br /&gt;
        poppy = UUID()&lt;br /&gt;
        print dir(poppy)&lt;br /&gt;
        print poppy.uuid.bytes&lt;br /&gt;
        p.AgentData[&#039;AgentID&#039;] = poppy&lt;br /&gt;
        p.AgentData[&#039;SessionID&#039;] = UUID()&lt;br /&gt;
        p.AgentData[&#039;AvatarID&#039;] = poppy&lt;br /&gt;
        self.send_message(p, True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* need a coroutine to sit and wait for response, not that far yet&lt;br /&gt;
* much of this functionality is in region.py, should definitely be brought out and into the message package somehow&lt;br /&gt;
* chat with enus about branching, possibly mercurial?&lt;br /&gt;
* full test, with reliable acks:&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
    def test_asdf(self):                                                                                              &lt;br /&gt;
        # build message, send it                                                                                      &lt;br /&gt;
        packet = packet_types.AvatarPropertiesRequestPacket()                                                         &lt;br /&gt;
        poppy = UUID()                                                          &lt;br /&gt;
        packet.AgentData[&#039;AgentID&#039;] = poppy                                                                           &lt;br /&gt;
        packet.AgentData[&#039;SessionID&#039;] = UUID()                                                                        &lt;br /&gt;
        packet.AgentData[&#039;AvatarID&#039;] = poppy                                                                          &lt;br /&gt;
        #self.messenger.send_message(packet, self.host)                                                               &lt;br /&gt;
        self.messenger.send_reliable(packet, self.host, 0)                                                            &lt;br /&gt;
        # wait for Ack, socket timeout after 1s wait (1000ms)                                                         &lt;br /&gt;
        self.messenger.socket.settimeout(1.0)                                                                         &lt;br /&gt;
        msg_buf, msg_size = self.messenger.udp_client.receive_packet(self.messenger.socket)                           &lt;br /&gt;
        recv = self.messenger.receive_check(self.messenger.udp_client.get_sender(), msg_buf, msg_size)                &lt;br /&gt;
        if recv is None or recv.name != &#039;PacketAck&#039;:                                                                  &lt;br /&gt;
            self.fail(&amp;quot;no data waiting after 1s&amp;quot;)                                                                     &lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== random hacking ==&lt;br /&gt;
* can&#039;t seem to introspect then send all the packet types from dir() on pyogp.lib.base.message.packets&lt;br /&gt;
* that&#039;s gone, but no obvious way to get message from template...&lt;br /&gt;
* eventlet 0.8.12 cheeseshop install seems borked, using &#039;pip install -E . -f http://pypi.python.org/packages/source/e/eventlet/eventlet-0.8.11.tar.gz eventlet-0.8.11&#039;&lt;br /&gt;
* install nose: easy_install --prefix=~/local nose&lt;br /&gt;
* bin/python `which nosetests` src/*&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=442302</id>
		<title>User:Poppy Linden/PyOGP \ libdev Initial Setup Experience</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=442302"/>
		<updated>2009-07-28T05:30:40Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: /* random hacking */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;sequential, oldest first.&lt;br /&gt;
&lt;br /&gt;
== bootstrapping ==&lt;br /&gt;
* omg tons of docs&lt;br /&gt;
* omg repeats internally / externally... lemme fix that...&lt;br /&gt;
* code?&lt;br /&gt;
* ok, what deps are required? wait.. how does python pathing work? oh, i can just put it in my python_path, cool&lt;br /&gt;
* wait, this says i need to install a friggin million things.&lt;br /&gt;
* I Hate Everything Python Right Now.&lt;br /&gt;
* I bootstrapped a wicked python env in my homedir.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir -p ~/local/lib/python2.4/site-packages&lt;br /&gt;
vi ~/.bashrc &lt;br /&gt;
&amp;gt;&amp;gt; export PYTHONPATH=$PYTHONPATH:~/local/lib/python2.4/site-packages&lt;br /&gt;
&amp;gt;&amp;gt; export PATH=$PATH:/usr/local/bin:~/bin:~/local/bin&lt;br /&gt;
. ~/.bashrc &lt;br /&gt;
&lt;br /&gt;
curl -L &#039;http://pypi.python.org/packages/2.4/s/setuptools/setuptools-0.6c9-py2.4.egg#md5=260a2be2e5388d66bdaee06abec6342a&#039; &amp;gt; setuptools-0.6c9-py2.4.egg&lt;br /&gt;
sh setuptools-0.6c9-py2.4.egg --prefix=~/local&lt;br /&gt;
easy_install --prefix=~/local pip&lt;br /&gt;
easy_install --prefix=~/local virtualenv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ok, now what again? Oh yeah, virtualenv for pyogp... the point of this...&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** bin/python bootstrap.py&lt;br /&gt;
** bin/buildout -v&lt;br /&gt;
** oh, so virtualenv is preventing the very borknorking i am trying to prevent to my system. Fair game.&lt;br /&gt;
&lt;br /&gt;
== bootstrap / sanity verification ==&lt;br /&gt;
* bin/client_unittest&lt;br /&gt;
** FAILBOAT&lt;br /&gt;
** pip -E . install greenlet&lt;br /&gt;
** bin/client_unittest&lt;br /&gt;
** now a bunch of crazy shit instead of tracebacks, that&#039;s... good?&lt;br /&gt;
** 114 tests and 0 failures! that&#039;s good!&lt;br /&gt;
&lt;br /&gt;
== initial investigations ==&lt;br /&gt;
* vi src/pyogp.lib.base/pyogp/lib/base/tests/base.py&lt;br /&gt;
** everything starts with login, even with base. What about the delicious primitives i crave?&lt;br /&gt;
** ls -l is your friend. There are subfolders in src/pyogp.lib.base/pyogp/lib/base/, namely one named network, and one named message.&lt;br /&gt;
* reading tests is like looking at a tautology; they have no docs. &amp;quot;Yes, i bet that does in fact work that way.&amp;quot; What do I see to bootstrap an app?&lt;br /&gt;
* i say: &amp;quot;(i want to know what code to see to understand) how to init main, send a message, quit&amp;quot; enus: &amp;quot;well, region.py uses UDPDispatcher. i&#039;ve not tried using it w/o the entire context&amp;quot; &amp;quot;maybe test_udpconnection.py is a useful reference. it instantiates UDPDispatcher, against a mock host, and sends a message&amp;quot;&lt;br /&gt;
* enus: &amp;quot;the Message usage is changing soon. look at the Message() class.&amp;quot; &amp;quot;packets.py transforms representations of packet data into Message instqances, but packets.py is going away soon&amp;quot;&lt;br /&gt;
* there *really* needs to be a step-by-step to get bootstrapped, I hope this helps write that! I&#039;m still not writing &amp;quot;Hello World&amp;quot; with pyogp yet!&lt;br /&gt;
* test app, try 1&lt;br /&gt;
** mkdir test_dataserver; cd test_dataserver&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** RTFM: pip help install | less&lt;br /&gt;
** pip install -E . -e ../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk libdev ... FAIL&lt;br /&gt;
** OH WAIT the problem isn&#039;t the dir, it&#039;s the &amp;quot;libdev&amp;quot; afterwards&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk ... FAIL but a new error, no setup.py... wait a sec...&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/pyogp.lib.base/trunk/ ... WIN&lt;br /&gt;
* should work to just copy a unit test into my src/ dir, copying test_udpconnection.py as it sounds like a good start&lt;br /&gt;
* pip install -E . greenlet&lt;br /&gt;
* bin/python src/test_udpconnection.py ... aaaaaand... no output. Is that a good thing for a test?&lt;br /&gt;
* need some of this:&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    unittest.main()&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
* tests pass. Rad! Let&#039;s send some garbage.&lt;br /&gt;
&lt;br /&gt;
== learn to send messages ==&lt;br /&gt;
* pyogp.lib.base/pyogp/lib/base/message/circuit.py - the Host class looks a little thin; doesn&#039;t take a FQDN, just an IP addy?&lt;br /&gt;
* resetting the host in test_find_circuit in my modified copy of test_udpconnection.py doesn&#039;t seem to be hitting the desired host / port&lt;br /&gt;
* try to reverse-engineer class diagram using pylint and graphviz... hmm...&lt;br /&gt;
* finally get *something* - a couple circuits established with the UDPConnectionTest replacing the mock server with my code&lt;br /&gt;
* it&#039;s making me crazy that MockupTestServer and Client don&#039;t seem to map to a real object. It appears to be impossible to trivially modify test_udpconnection.py to connect to a real server instead of a mock.&lt;br /&gt;
* so after some tinkering, this works:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        p = packet_types.AvatarPropertiesRequestPacket()&lt;br /&gt;
        poppy = UUID()&lt;br /&gt;
        print dir(poppy)&lt;br /&gt;
        print poppy.uuid.bytes&lt;br /&gt;
        p.AgentData[&#039;AgentID&#039;] = poppy&lt;br /&gt;
        p.AgentData[&#039;SessionID&#039;] = UUID()&lt;br /&gt;
        p.AgentData[&#039;AvatarID&#039;] = poppy&lt;br /&gt;
        self.send_message(p, True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* need a coroutine to sit and wait for response, not that far yet&lt;br /&gt;
* much of this functionality is in region.py, should definitely be brought out and into the message package somehow&lt;br /&gt;
* chat with enus about branching, possibly mercurial?&lt;br /&gt;
* full test, with reliable acks:&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
    def test_asdf(self):                                                                                              &lt;br /&gt;
        # build message, send it                                                                                      &lt;br /&gt;
        packet = packet_types.AvatarPropertiesRequestPacket()                                                         &lt;br /&gt;
        poppy = UUID()                                                          &lt;br /&gt;
        packet.AgentData[&#039;AgentID&#039;] = poppy                                                                           &lt;br /&gt;
        packet.AgentData[&#039;SessionID&#039;] = UUID()                                                                        &lt;br /&gt;
        packet.AgentData[&#039;AvatarID&#039;] = poppy                                                                          &lt;br /&gt;
        #self.messenger.send_message(packet, self.host)                                                               &lt;br /&gt;
        self.messenger.send_reliable(packet, self.host, 0)                                                            &lt;br /&gt;
        # wait for Ack, socket timeout after 1s wait (1000ms)                                                         &lt;br /&gt;
        self.messenger.socket.settimeout(1.0)                                                                         &lt;br /&gt;
        msg_buf, msg_size = self.messenger.udp_client.receive_packet(self.messenger.socket)                           &lt;br /&gt;
        recv = self.messenger.receive_check(self.messenger.udp_client.get_sender(), msg_buf, msg_size)                &lt;br /&gt;
        if recv is None or recv.name != &#039;PacketAck&#039;:                                                                  &lt;br /&gt;
            self.fail(&amp;quot;no data waiting after 1s&amp;quot;)                                                                     &lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== random hacking ==&lt;br /&gt;
* can&#039;t seem to introspect then send all the packet types from dir() on pyogp.lib.base.message.packets&lt;br /&gt;
* that&#039;s gone, but no obvious way to get message from template...&lt;br /&gt;
* eventlet 0.8.12 cheeseshop install seems borked, using &#039;pip install -E . -f http://pypi.python.org/packages/source/e/eventlet/eventlet-0.8.11.tar.gz eventlet-0.8.11&#039;&lt;br /&gt;
* install nose: easy_install --prefix=~/local nose&lt;br /&gt;
* bin/python `which nosetests`&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=442262</id>
		<title>User:Poppy Linden/PyOGP \ libdev Initial Setup Experience</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=442262"/>
		<updated>2009-07-28T03:16:23Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: /* random hacking */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;sequential, oldest first.&lt;br /&gt;
&lt;br /&gt;
== bootstrapping ==&lt;br /&gt;
* omg tons of docs&lt;br /&gt;
* omg repeats internally / externally... lemme fix that...&lt;br /&gt;
* code?&lt;br /&gt;
* ok, what deps are required? wait.. how does python pathing work? oh, i can just put it in my python_path, cool&lt;br /&gt;
* wait, this says i need to install a friggin million things.&lt;br /&gt;
* I Hate Everything Python Right Now.&lt;br /&gt;
* I bootstrapped a wicked python env in my homedir.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir -p ~/local/lib/python2.4/site-packages&lt;br /&gt;
vi ~/.bashrc &lt;br /&gt;
&amp;gt;&amp;gt; export PYTHONPATH=$PYTHONPATH:~/local/lib/python2.4/site-packages&lt;br /&gt;
&amp;gt;&amp;gt; export PATH=$PATH:/usr/local/bin:~/bin:~/local/bin&lt;br /&gt;
. ~/.bashrc &lt;br /&gt;
&lt;br /&gt;
curl -L &#039;http://pypi.python.org/packages/2.4/s/setuptools/setuptools-0.6c9-py2.4.egg#md5=260a2be2e5388d66bdaee06abec6342a&#039; &amp;gt; setuptools-0.6c9-py2.4.egg&lt;br /&gt;
sh setuptools-0.6c9-py2.4.egg --prefix=~/local&lt;br /&gt;
easy_install --prefix=~/local pip&lt;br /&gt;
easy_install --prefix=~/local virtualenv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ok, now what again? Oh yeah, virtualenv for pyogp... the point of this...&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** bin/python bootstrap.py&lt;br /&gt;
** bin/buildout -v&lt;br /&gt;
** oh, so virtualenv is preventing the very borknorking i am trying to prevent to my system. Fair game.&lt;br /&gt;
&lt;br /&gt;
== bootstrap / sanity verification ==&lt;br /&gt;
* bin/client_unittest&lt;br /&gt;
** FAILBOAT&lt;br /&gt;
** pip -E . install greenlet&lt;br /&gt;
** bin/client_unittest&lt;br /&gt;
** now a bunch of crazy shit instead of tracebacks, that&#039;s... good?&lt;br /&gt;
** 114 tests and 0 failures! that&#039;s good!&lt;br /&gt;
&lt;br /&gt;
== initial investigations ==&lt;br /&gt;
* vi src/pyogp.lib.base/pyogp/lib/base/tests/base.py&lt;br /&gt;
** everything starts with login, even with base. What about the delicious primitives i crave?&lt;br /&gt;
** ls -l is your friend. There are subfolders in src/pyogp.lib.base/pyogp/lib/base/, namely one named network, and one named message.&lt;br /&gt;
* reading tests is like looking at a tautology; they have no docs. &amp;quot;Yes, i bet that does in fact work that way.&amp;quot; What do I see to bootstrap an app?&lt;br /&gt;
* i say: &amp;quot;(i want to know what code to see to understand) how to init main, send a message, quit&amp;quot; enus: &amp;quot;well, region.py uses UDPDispatcher. i&#039;ve not tried using it w/o the entire context&amp;quot; &amp;quot;maybe test_udpconnection.py is a useful reference. it instantiates UDPDispatcher, against a mock host, and sends a message&amp;quot;&lt;br /&gt;
* enus: &amp;quot;the Message usage is changing soon. look at the Message() class.&amp;quot; &amp;quot;packets.py transforms representations of packet data into Message instqances, but packets.py is going away soon&amp;quot;&lt;br /&gt;
* there *really* needs to be a step-by-step to get bootstrapped, I hope this helps write that! I&#039;m still not writing &amp;quot;Hello World&amp;quot; with pyogp yet!&lt;br /&gt;
* test app, try 1&lt;br /&gt;
** mkdir test_dataserver; cd test_dataserver&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** RTFM: pip help install | less&lt;br /&gt;
** pip install -E . -e ../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk libdev ... FAIL&lt;br /&gt;
** OH WAIT the problem isn&#039;t the dir, it&#039;s the &amp;quot;libdev&amp;quot; afterwards&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk ... FAIL but a new error, no setup.py... wait a sec...&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/pyogp.lib.base/trunk/ ... WIN&lt;br /&gt;
* should work to just copy a unit test into my src/ dir, copying test_udpconnection.py as it sounds like a good start&lt;br /&gt;
* pip install -E . greenlet&lt;br /&gt;
* bin/python src/test_udpconnection.py ... aaaaaand... no output. Is that a good thing for a test?&lt;br /&gt;
* need some of this:&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    unittest.main()&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
* tests pass. Rad! Let&#039;s send some garbage.&lt;br /&gt;
&lt;br /&gt;
== learn to send messages ==&lt;br /&gt;
* pyogp.lib.base/pyogp/lib/base/message/circuit.py - the Host class looks a little thin; doesn&#039;t take a FQDN, just an IP addy?&lt;br /&gt;
* resetting the host in test_find_circuit in my modified copy of test_udpconnection.py doesn&#039;t seem to be hitting the desired host / port&lt;br /&gt;
* try to reverse-engineer class diagram using pylint and graphviz... hmm...&lt;br /&gt;
* finally get *something* - a couple circuits established with the UDPConnectionTest replacing the mock server with my code&lt;br /&gt;
* it&#039;s making me crazy that MockupTestServer and Client don&#039;t seem to map to a real object. It appears to be impossible to trivially modify test_udpconnection.py to connect to a real server instead of a mock.&lt;br /&gt;
* so after some tinkering, this works:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        p = packet_types.AvatarPropertiesRequestPacket()&lt;br /&gt;
        poppy = UUID()&lt;br /&gt;
        print dir(poppy)&lt;br /&gt;
        print poppy.uuid.bytes&lt;br /&gt;
        p.AgentData[&#039;AgentID&#039;] = poppy&lt;br /&gt;
        p.AgentData[&#039;SessionID&#039;] = UUID()&lt;br /&gt;
        p.AgentData[&#039;AvatarID&#039;] = poppy&lt;br /&gt;
        self.send_message(p, True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* need a coroutine to sit and wait for response, not that far yet&lt;br /&gt;
* much of this functionality is in region.py, should definitely be brought out and into the message package somehow&lt;br /&gt;
* chat with enus about branching, possibly mercurial?&lt;br /&gt;
* full test, with reliable acks:&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
    def test_asdf(self):                                                                                              &lt;br /&gt;
        # build message, send it                                                                                      &lt;br /&gt;
        packet = packet_types.AvatarPropertiesRequestPacket()                                                         &lt;br /&gt;
        poppy = UUID()                                                          &lt;br /&gt;
        packet.AgentData[&#039;AgentID&#039;] = poppy                                                                           &lt;br /&gt;
        packet.AgentData[&#039;SessionID&#039;] = UUID()                                                                        &lt;br /&gt;
        packet.AgentData[&#039;AvatarID&#039;] = poppy                                                                          &lt;br /&gt;
        #self.messenger.send_message(packet, self.host)                                                               &lt;br /&gt;
        self.messenger.send_reliable(packet, self.host, 0)                                                            &lt;br /&gt;
        # wait for Ack, socket timeout after 1s wait (1000ms)                                                         &lt;br /&gt;
        self.messenger.socket.settimeout(1.0)                                                                         &lt;br /&gt;
        msg_buf, msg_size = self.messenger.udp_client.receive_packet(self.messenger.socket)                           &lt;br /&gt;
        recv = self.messenger.receive_check(self.messenger.udp_client.get_sender(), msg_buf, msg_size)                &lt;br /&gt;
        if recv is None or recv.name != &#039;PacketAck&#039;:                                                                  &lt;br /&gt;
            self.fail(&amp;quot;no data waiting after 1s&amp;quot;)                                                                     &lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== random hacking ==&lt;br /&gt;
* can&#039;t seem to introspect then send all the packet types from dir() on pyogp.lib.base.message.packets&lt;br /&gt;
* that&#039;s gone, but no obvious way to get message from template...&lt;br /&gt;
* eventlet 0.8.12 cheeseshop install seems borked, using &#039;pip install -E . -f http://pypi.python.org/packages/source/e/eventlet/eventlet-0.8.11.tar.gz eventlet-0.8.11&#039;&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=437602</id>
		<title>User:Poppy Linden/PyOGP \ libdev Initial Setup Experience</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=437602"/>
		<updated>2009-07-24T01:55:43Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;sequential, oldest first.&lt;br /&gt;
&lt;br /&gt;
== bootstrapping ==&lt;br /&gt;
* omg tons of docs&lt;br /&gt;
* omg repeats internally / externally... lemme fix that...&lt;br /&gt;
* code?&lt;br /&gt;
* ok, what deps are required? wait.. how does python pathing work? oh, i can just put it in my python_path, cool&lt;br /&gt;
* wait, this says i need to install a friggin million things.&lt;br /&gt;
* I Hate Everything Python Right Now.&lt;br /&gt;
* I bootstrapped a wicked python env in my homedir.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir -p ~/local/lib/python2.4/site-packages&lt;br /&gt;
vi ~/.bashrc &lt;br /&gt;
&amp;gt;&amp;gt; export PYTHONPATH=$PYTHONPATH:~/local/lib/python2.4/site-packages&lt;br /&gt;
&amp;gt;&amp;gt; export PATH=$PATH:/usr/local/bin:~/bin:~/local/bin&lt;br /&gt;
. ~/.bashrc &lt;br /&gt;
&lt;br /&gt;
curl -L &#039;http://pypi.python.org/packages/2.4/s/setuptools/setuptools-0.6c9-py2.4.egg#md5=260a2be2e5388d66bdaee06abec6342a&#039; &amp;gt; setuptools-0.6c9-py2.4.egg&lt;br /&gt;
sh setuptools-0.6c9-py2.4.egg --prefix=~/local&lt;br /&gt;
easy_install --prefix=~/local pip&lt;br /&gt;
easy_install --prefix=~/local virtualenv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ok, now what again? Oh yeah, virtualenv for pyogp... the point of this...&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** bin/python bootstrap.py&lt;br /&gt;
** bin/buildout -v&lt;br /&gt;
** oh, so virtualenv is preventing the very borknorking i am trying to prevent to my system. Fair game.&lt;br /&gt;
&lt;br /&gt;
== bootstrap / sanity verification ==&lt;br /&gt;
* bin/client_unittest&lt;br /&gt;
** FAILBOAT&lt;br /&gt;
** pip -E . install greenlet&lt;br /&gt;
** bin/client_unittest&lt;br /&gt;
** now a bunch of crazy shit instead of tracebacks, that&#039;s... good?&lt;br /&gt;
** 114 tests and 0 failures! that&#039;s good!&lt;br /&gt;
&lt;br /&gt;
== initial investigations ==&lt;br /&gt;
* vi src/pyogp.lib.base/pyogp/lib/base/tests/base.py&lt;br /&gt;
** everything starts with login, even with base. What about the delicious primitives i crave?&lt;br /&gt;
** ls -l is your friend. There are subfolders in src/pyogp.lib.base/pyogp/lib/base/, namely one named network, and one named message.&lt;br /&gt;
* reading tests is like looking at a tautology; they have no docs. &amp;quot;Yes, i bet that does in fact work that way.&amp;quot; What do I see to bootstrap an app?&lt;br /&gt;
* i say: &amp;quot;(i want to know what code to see to understand) how to init main, send a message, quit&amp;quot; enus: &amp;quot;well, region.py uses UDPDispatcher. i&#039;ve not tried using it w/o the entire context&amp;quot; &amp;quot;maybe test_udpconnection.py is a useful reference. it instantiates UDPDispatcher, against a mock host, and sends a message&amp;quot;&lt;br /&gt;
* enus: &amp;quot;the Message usage is changing soon. look at the Message() class.&amp;quot; &amp;quot;packets.py transforms representations of packet data into Message instqances, but packets.py is going away soon&amp;quot;&lt;br /&gt;
* there *really* needs to be a step-by-step to get bootstrapped, I hope this helps write that! I&#039;m still not writing &amp;quot;Hello World&amp;quot; with pyogp yet!&lt;br /&gt;
* test app, try 1&lt;br /&gt;
** mkdir test_dataserver; cd test_dataserver&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** RTFM: pip help install | less&lt;br /&gt;
** pip install -E . -e ../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk libdev ... FAIL&lt;br /&gt;
** OH WAIT the problem isn&#039;t the dir, it&#039;s the &amp;quot;libdev&amp;quot; afterwards&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk ... FAIL but a new error, no setup.py... wait a sec...&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/pyogp.lib.base/trunk/ ... WIN&lt;br /&gt;
* should work to just copy a unit test into my src/ dir, copying test_udpconnection.py as it sounds like a good start&lt;br /&gt;
* pip install -E . greenlet&lt;br /&gt;
* bin/python src/test_udpconnection.py ... aaaaaand... no output. Is that a good thing for a test?&lt;br /&gt;
* need some of this:&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    unittest.main()&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
* tests pass. Rad! Let&#039;s send some garbage.&lt;br /&gt;
&lt;br /&gt;
== learn to send messages ==&lt;br /&gt;
* pyogp.lib.base/pyogp/lib/base/message/circuit.py - the Host class looks a little thin; doesn&#039;t take a FQDN, just an IP addy?&lt;br /&gt;
* resetting the host in test_find_circuit in my modified copy of test_udpconnection.py doesn&#039;t seem to be hitting the desired host / port&lt;br /&gt;
* try to reverse-engineer class diagram using pylint and graphviz... hmm...&lt;br /&gt;
* finally get *something* - a couple circuits established with the UDPConnectionTest replacing the mock server with my code&lt;br /&gt;
* it&#039;s making me crazy that MockupTestServer and Client don&#039;t seem to map to a real object. It appears to be impossible to trivially modify test_udpconnection.py to connect to a real server instead of a mock.&lt;br /&gt;
* so after some tinkering, this works:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        p = packet_types.AvatarPropertiesRequestPacket()&lt;br /&gt;
        poppy = UUID()&lt;br /&gt;
        print dir(poppy)&lt;br /&gt;
        print poppy.uuid.bytes&lt;br /&gt;
        p.AgentData[&#039;AgentID&#039;] = poppy&lt;br /&gt;
        p.AgentData[&#039;SessionID&#039;] = UUID()&lt;br /&gt;
        p.AgentData[&#039;AvatarID&#039;] = poppy&lt;br /&gt;
        self.send_message(p, True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* need a coroutine to sit and wait for response, not that far yet&lt;br /&gt;
* much of this functionality is in region.py, should definitely be brought out and into the message package somehow&lt;br /&gt;
* chat with enus about branching, possibly mercurial?&lt;br /&gt;
* full test, with reliable acks:&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
    def test_asdf(self):                                                                                              &lt;br /&gt;
        # build message, send it                                                                                      &lt;br /&gt;
        packet = packet_types.AvatarPropertiesRequestPacket()                                                         &lt;br /&gt;
        poppy = UUID()                                                          &lt;br /&gt;
        packet.AgentData[&#039;AgentID&#039;] = poppy                                                                           &lt;br /&gt;
        packet.AgentData[&#039;SessionID&#039;] = UUID()                                                                        &lt;br /&gt;
        packet.AgentData[&#039;AvatarID&#039;] = poppy                                                                          &lt;br /&gt;
        #self.messenger.send_message(packet, self.host)                                                               &lt;br /&gt;
        self.messenger.send_reliable(packet, self.host, 0)                                                            &lt;br /&gt;
        # wait for Ack, socket timeout after 1s wait (1000ms)                                                         &lt;br /&gt;
        self.messenger.socket.settimeout(1.0)                                                                         &lt;br /&gt;
        msg_buf, msg_size = self.messenger.udp_client.receive_packet(self.messenger.socket)                           &lt;br /&gt;
        recv = self.messenger.receive_check(self.messenger.udp_client.get_sender(), msg_buf, msg_size)                &lt;br /&gt;
        if recv is None or recv.name != &#039;PacketAck&#039;:                                                                  &lt;br /&gt;
            self.fail(&amp;quot;no data waiting after 1s&amp;quot;)                                                                     &lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== random hacking ==&lt;br /&gt;
* can&#039;t seem to introspect then send all the packet types from dir() on pyogp.lib.base.message.packets&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=427982</id>
		<title>User:Poppy Linden/PyOGP \ libdev Initial Setup Experience</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=427982"/>
		<updated>2009-07-10T02:27:41Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: /* learn to send messages */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;sequential, oldest first.&lt;br /&gt;
&lt;br /&gt;
== bootstrapping ==&lt;br /&gt;
* omg tons of docs&lt;br /&gt;
* omg repeats internally / externally... lemme fix that...&lt;br /&gt;
* code?&lt;br /&gt;
* ok, what deps are required? wait.. how does python pathing work? oh, i can just put it in my python_path, cool&lt;br /&gt;
* wait, this says i need to install a friggin million things.&lt;br /&gt;
* I Hate Everything Python Right Now.&lt;br /&gt;
* I bootstrapped a wicked python env in my homedir.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir -p ~/local/lib/python2.4/site-packages&lt;br /&gt;
vi ~/.bashrc &lt;br /&gt;
&amp;gt;&amp;gt; export PYTHONPATH=$PYTHONPATH:~/local/lib/python2.4/site-packages&lt;br /&gt;
&amp;gt;&amp;gt; export PATH=$PATH:/usr/local/bin:~/bin:~/local/bin&lt;br /&gt;
. ~/.bashrc &lt;br /&gt;
&lt;br /&gt;
curl -L &#039;http://pypi.python.org/packages/2.4/s/setuptools/setuptools-0.6c9-py2.4.egg#md5=260a2be2e5388d66bdaee06abec6342a&#039; &amp;gt; setuptools-0.6c9-py2.4.egg&lt;br /&gt;
sh setuptools-0.6c9-py2.4.egg --prefix=~/local&lt;br /&gt;
easy_install --prefix=~/local pip&lt;br /&gt;
easy_install --prefix=~/local virtualenv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ok, now what again? Oh yeah, virtualenv for pyogp... the point of this...&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** bin/python bootstrap.py&lt;br /&gt;
** bin/buildout -v&lt;br /&gt;
** oh, so virtualenv is preventing the very borknorking i am trying to prevent to my system. Fair game.&lt;br /&gt;
&lt;br /&gt;
== bootstrap / sanity verification ==&lt;br /&gt;
* bin/client_unittest&lt;br /&gt;
** FAILBOAT&lt;br /&gt;
** pip -E . install greenlet&lt;br /&gt;
** bin/client_unittest&lt;br /&gt;
** now a bunch of crazy shit instead of tracebacks, that&#039;s... good?&lt;br /&gt;
** 114 tests and 0 failures! that&#039;s good!&lt;br /&gt;
&lt;br /&gt;
== initial investigations ==&lt;br /&gt;
* vi src/pyogp.lib.base/pyogp/lib/base/tests/base.py&lt;br /&gt;
** everything starts with login, even with base. What about the delicious primitives i crave?&lt;br /&gt;
** ls -l is your friend. There are subfolders in src/pyogp.lib.base/pyogp/lib/base/, namely one named network, and one named message.&lt;br /&gt;
* reading tests is like looking at a tautology; they have no docs. &amp;quot;Yes, i bet that does in fact work that way.&amp;quot; What do I see to bootstrap an app?&lt;br /&gt;
* i say: &amp;quot;(i want to know what code to see to understand) how to init main, send a message, quit&amp;quot; enus: &amp;quot;well, region.py uses UDPDispatcher. i&#039;ve not tried using it w/o the entire context&amp;quot; &amp;quot;maybe test_udpconnection.py is a useful reference. it instantiates UDPDispatcher, against a mock host, and sends a message&amp;quot;&lt;br /&gt;
* enus: &amp;quot;the Message usage is changing soon. look at the Message() class.&amp;quot; &amp;quot;packets.py transforms representations of packet data into Message instqances, but packets.py is going away soon&amp;quot;&lt;br /&gt;
* there *really* needs to be a step-by-step to get bootstrapped, I hope this helps write that! I&#039;m still not writing &amp;quot;Hello World&amp;quot; with pyogp yet!&lt;br /&gt;
* test app, try 1&lt;br /&gt;
** mkdir test_dataserver; cd test_dataserver&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** RTFM: pip help install | less&lt;br /&gt;
** pip install -E . -e ../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk libdev ... FAIL&lt;br /&gt;
** OH WAIT the problem isn&#039;t the dir, it&#039;s the &amp;quot;libdev&amp;quot; afterwards&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk ... FAIL but a new error, no setup.py... wait a sec...&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/pyogp.lib.base/trunk/ ... WIN&lt;br /&gt;
* should work to just copy a unit test into my src/ dir, copying test_udpconnection.py as it sounds like a good start&lt;br /&gt;
* pip install -E . greenlet&lt;br /&gt;
* bin/python src/test_udpconnection.py ... aaaaaand... no output. Is that a good thing for a test?&lt;br /&gt;
* need some of this:&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    unittest.main()&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
* tests pass. Rad! Let&#039;s send some garbage.&lt;br /&gt;
&lt;br /&gt;
== learn to send messages ==&lt;br /&gt;
* pyogp.lib.base/pyogp/lib/base/message/circuit.py - the Host class looks a little thin; doesn&#039;t take a FQDN, just an IP addy?&lt;br /&gt;
* resetting the host in test_find_circuit in my modified copy of test_udpconnection.py doesn&#039;t seem to be hitting the desired host / port&lt;br /&gt;
* try to reverse-engineer class diagram using pylint and graphviz... hmm...&lt;br /&gt;
* finally get *something* - a couple circuits established with the UDPConnectionTest replacing the mock server with my code&lt;br /&gt;
* it&#039;s making me crazy that MockupTestServer and Client don&#039;t seem to map to a real object. It appears to be impossible to trivially modify test_udpconnection.py to connect to a real server instead of a mock.&lt;br /&gt;
* so after some tinkering, this works:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        p = packet_types.AvatarPropertiesRequestPacket()&lt;br /&gt;
        poppy = UUID()&lt;br /&gt;
        print dir(poppy)&lt;br /&gt;
        print poppy.uuid.bytes&lt;br /&gt;
        p.AgentData[&#039;AgentID&#039;] = poppy&lt;br /&gt;
        p.AgentData[&#039;SessionID&#039;] = UUID()&lt;br /&gt;
        p.AgentData[&#039;AvatarID&#039;] = poppy&lt;br /&gt;
        self.send_message(p, True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* need a coroutine to sit and wait for response, not that far yet&lt;br /&gt;
* much of this functionality is in region.py, should definitely be brought out and into the message package somehow&lt;br /&gt;
* chat with enus about branching, possibly mercurial?&lt;br /&gt;
* full test, with reliable acks:&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
    def test_asdf(self):                                                                                              &lt;br /&gt;
        # build message, send it                                                                                      &lt;br /&gt;
        packet = packet_types.AvatarPropertiesRequestPacket()                                                         &lt;br /&gt;
        poppy = UUID()                                                          &lt;br /&gt;
        packet.AgentData[&#039;AgentID&#039;] = poppy                                                                           &lt;br /&gt;
        packet.AgentData[&#039;SessionID&#039;] = UUID()                                                                        &lt;br /&gt;
        packet.AgentData[&#039;AvatarID&#039;] = poppy                                                                          &lt;br /&gt;
        #self.messenger.send_message(packet, self.host)                                                               &lt;br /&gt;
        self.messenger.send_reliable(packet, self.host, 0)                                                            &lt;br /&gt;
        # wait for Ack, socket timeout after 1s wait (1000ms)                                                         &lt;br /&gt;
        self.messenger.socket.settimeout(1.0)                                                                         &lt;br /&gt;
        msg_buf, msg_size = self.messenger.udp_client.receive_packet(self.messenger.socket)                           &lt;br /&gt;
        recv = self.messenger.receive_check(self.messenger.udp_client.get_sender(), msg_buf, msg_size)                &lt;br /&gt;
        if recv is None or recv.name != &#039;PacketAck&#039;:                                                                  &lt;br /&gt;
            self.fail(&amp;quot;no data waiting after 1s&amp;quot;)                                                                     &lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=427362</id>
		<title>User:Poppy Linden/PyOGP \ libdev Initial Setup Experience</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=427362"/>
		<updated>2009-07-09T02:54:07Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: /* learn to send messages */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;sequential, oldest first.&lt;br /&gt;
&lt;br /&gt;
== bootstrapping ==&lt;br /&gt;
* omg tons of docs&lt;br /&gt;
* omg repeats internally / externally... lemme fix that...&lt;br /&gt;
* code?&lt;br /&gt;
* ok, what deps are required? wait.. how does python pathing work? oh, i can just put it in my python_path, cool&lt;br /&gt;
* wait, this says i need to install a friggin million things.&lt;br /&gt;
* I Hate Everything Python Right Now.&lt;br /&gt;
* I bootstrapped a wicked python env in my homedir.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir -p ~/local/lib/python2.4/site-packages&lt;br /&gt;
vi ~/.bashrc &lt;br /&gt;
&amp;gt;&amp;gt; export PYTHONPATH=$PYTHONPATH:~/local/lib/python2.4/site-packages&lt;br /&gt;
&amp;gt;&amp;gt; export PATH=$PATH:/usr/local/bin:~/bin:~/local/bin&lt;br /&gt;
. ~/.bashrc &lt;br /&gt;
&lt;br /&gt;
curl -L &#039;http://pypi.python.org/packages/2.4/s/setuptools/setuptools-0.6c9-py2.4.egg#md5=260a2be2e5388d66bdaee06abec6342a&#039; &amp;gt; setuptools-0.6c9-py2.4.egg&lt;br /&gt;
sh setuptools-0.6c9-py2.4.egg --prefix=~/local&lt;br /&gt;
easy_install --prefix=~/local pip&lt;br /&gt;
easy_install --prefix=~/local virtualenv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ok, now what again? Oh yeah, virtualenv for pyogp... the point of this...&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** bin/python bootstrap.py&lt;br /&gt;
** bin/buildout -v&lt;br /&gt;
** oh, so virtualenv is preventing the very borknorking i am trying to prevent to my system. Fair game.&lt;br /&gt;
&lt;br /&gt;
== bootstrap / sanity verification ==&lt;br /&gt;
* bin/client_unittest&lt;br /&gt;
** FAILBOAT&lt;br /&gt;
** pip -E . install greenlet&lt;br /&gt;
** bin/client_unittest&lt;br /&gt;
** now a bunch of crazy shit instead of tracebacks, that&#039;s... good?&lt;br /&gt;
** 114 tests and 0 failures! that&#039;s good!&lt;br /&gt;
&lt;br /&gt;
== initial investigations ==&lt;br /&gt;
* vi src/pyogp.lib.base/pyogp/lib/base/tests/base.py&lt;br /&gt;
** everything starts with login, even with base. What about the delicious primitives i crave?&lt;br /&gt;
** ls -l is your friend. There are subfolders in src/pyogp.lib.base/pyogp/lib/base/, namely one named network, and one named message.&lt;br /&gt;
* reading tests is like looking at a tautology; they have no docs. &amp;quot;Yes, i bet that does in fact work that way.&amp;quot; What do I see to bootstrap an app?&lt;br /&gt;
* i say: &amp;quot;(i want to know what code to see to understand) how to init main, send a message, quit&amp;quot; enus: &amp;quot;well, region.py uses UDPDispatcher. i&#039;ve not tried using it w/o the entire context&amp;quot; &amp;quot;maybe test_udpconnection.py is a useful reference. it instantiates UDPDispatcher, against a mock host, and sends a message&amp;quot;&lt;br /&gt;
* enus: &amp;quot;the Message usage is changing soon. look at the Message() class.&amp;quot; &amp;quot;packets.py transforms representations of packet data into Message instqances, but packets.py is going away soon&amp;quot;&lt;br /&gt;
* there *really* needs to be a step-by-step to get bootstrapped, I hope this helps write that! I&#039;m still not writing &amp;quot;Hello World&amp;quot; with pyogp yet!&lt;br /&gt;
* test app, try 1&lt;br /&gt;
** mkdir test_dataserver; cd test_dataserver&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** RTFM: pip help install | less&lt;br /&gt;
** pip install -E . -e ../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk libdev ... FAIL&lt;br /&gt;
** OH WAIT the problem isn&#039;t the dir, it&#039;s the &amp;quot;libdev&amp;quot; afterwards&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk ... FAIL but a new error, no setup.py... wait a sec...&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/pyogp.lib.base/trunk/ ... WIN&lt;br /&gt;
* should work to just copy a unit test into my src/ dir, copying test_udpconnection.py as it sounds like a good start&lt;br /&gt;
* pip install -E . greenlet&lt;br /&gt;
* bin/python src/test_udpconnection.py ... aaaaaand... no output. Is that a good thing for a test?&lt;br /&gt;
* need some of this:&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    unittest.main()&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
* tests pass. Rad! Let&#039;s send some garbage.&lt;br /&gt;
&lt;br /&gt;
== learn to send messages ==&lt;br /&gt;
* pyogp.lib.base/pyogp/lib/base/message/circuit.py - the Host class looks a little thin; doesn&#039;t take a FQDN, just an IP addy?&lt;br /&gt;
* resetting the host in test_find_circuit in my modified copy of test_udpconnection.py doesn&#039;t seem to be hitting the desired host / port&lt;br /&gt;
* try to reverse-engineer class diagram using pylint and graphviz... hmm...&lt;br /&gt;
* finally get *something* - a couple circuits established with the UDPConnectionTest replacing the mock server with my code&lt;br /&gt;
* it&#039;s making me crazy that MockupTestServer and Client don&#039;t seem to map to a real object. It appears to be impossible to trivially modify test_udpconnection.py to connect to a real server instead of a mock.&lt;br /&gt;
* so after some tinkering, this works:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        p = packet_types.AvatarPropertiesRequestPacket()&lt;br /&gt;
        poppy = UUID()&lt;br /&gt;
        print dir(poppy)&lt;br /&gt;
        print poppy.uuid.bytes&lt;br /&gt;
        p.AgentData[&#039;AgentID&#039;] = poppy&lt;br /&gt;
        p.AgentData[&#039;SessionID&#039;] = UUID()&lt;br /&gt;
        p.AgentData[&#039;AvatarID&#039;] = poppy&lt;br /&gt;
        self.send_message(p, True)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* need a coroutine to sit and wait for response, not that far yet&lt;br /&gt;
* much of this functionality is in region.py, should definitely be brought out and into the message package somehow&lt;br /&gt;
* chat with enus about branching, possibly mercurial?&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=427023</id>
		<title>User:Poppy Linden/PyOGP \ libdev Initial Setup Experience</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Poppy_Linden/PyOGP_%5C_libdev_Initial_Setup_Experience&amp;diff=427023"/>
		<updated>2009-07-08T23:28:14Z</updated>

		<summary type="html">&lt;p&gt;Poppy Linden: /* bootstrap / sanity verification */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;sequential, oldest first.&lt;br /&gt;
&lt;br /&gt;
== bootstrapping ==&lt;br /&gt;
* omg tons of docs&lt;br /&gt;
* omg repeats internally / externally... lemme fix that...&lt;br /&gt;
* code?&lt;br /&gt;
* ok, what deps are required? wait.. how does python pathing work? oh, i can just put it in my python_path, cool&lt;br /&gt;
* wait, this says i need to install a friggin million things.&lt;br /&gt;
* I Hate Everything Python Right Now.&lt;br /&gt;
* I bootstrapped a wicked python env in my homedir.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir -p ~/local/lib/python2.4/site-packages&lt;br /&gt;
vi ~/.bashrc &lt;br /&gt;
&amp;gt;&amp;gt; export PYTHONPATH=$PYTHONPATH:~/local/lib/python2.4/site-packages&lt;br /&gt;
&amp;gt;&amp;gt; export PATH=$PATH:/usr/local/bin:~/bin:~/local/bin&lt;br /&gt;
. ~/.bashrc &lt;br /&gt;
&lt;br /&gt;
curl -L &#039;http://pypi.python.org/packages/2.4/s/setuptools/setuptools-0.6c9-py2.4.egg#md5=260a2be2e5388d66bdaee06abec6342a&#039; &amp;gt; setuptools-0.6c9-py2.4.egg&lt;br /&gt;
sh setuptools-0.6c9-py2.4.egg --prefix=~/local&lt;br /&gt;
easy_install --prefix=~/local pip&lt;br /&gt;
easy_install --prefix=~/local virtualenv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ok, now what again? Oh yeah, virtualenv for pyogp... the point of this...&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** bin/python bootstrap.py&lt;br /&gt;
** bin/buildout -v&lt;br /&gt;
** oh, so virtualenv is preventing the very borknorking i am trying to prevent to my system. Fair game.&lt;br /&gt;
&lt;br /&gt;
== bootstrap / sanity verification ==&lt;br /&gt;
* bin/client_unittest&lt;br /&gt;
** FAILBOAT&lt;br /&gt;
** pip -E . install greenlet&lt;br /&gt;
** bin/client_unittest&lt;br /&gt;
** now a bunch of crazy shit instead of tracebacks, that&#039;s... good?&lt;br /&gt;
** 114 tests and 0 failures! that&#039;s good!&lt;br /&gt;
&lt;br /&gt;
== initial investigations ==&lt;br /&gt;
* vi src/pyogp.lib.base/pyogp/lib/base/tests/base.py&lt;br /&gt;
** everything starts with login, even with base. What about the delicious primitives i crave?&lt;br /&gt;
** ls -l is your friend. There are subfolders in src/pyogp.lib.base/pyogp/lib/base/, namely one named network, and one named message.&lt;br /&gt;
* reading tests is like looking at a tautology; they have no docs. &amp;quot;Yes, i bet that does in fact work that way.&amp;quot; What do I see to bootstrap an app?&lt;br /&gt;
* i say: &amp;quot;(i want to know what code to see to understand) how to init main, send a message, quit&amp;quot; enus: &amp;quot;well, region.py uses UDPDispatcher. i&#039;ve not tried using it w/o the entire context&amp;quot; &amp;quot;maybe test_udpconnection.py is a useful reference. it instantiates UDPDispatcher, against a mock host, and sends a message&amp;quot;&lt;br /&gt;
* enus: &amp;quot;the Message usage is changing soon. look at the Message() class.&amp;quot; &amp;quot;packets.py transforms representations of packet data into Message instqances, but packets.py is going away soon&amp;quot;&lt;br /&gt;
* there *really* needs to be a step-by-step to get bootstrapped, I hope this helps write that! I&#039;m still not writing &amp;quot;Hello World&amp;quot; with pyogp yet!&lt;br /&gt;
* test app, try 1&lt;br /&gt;
** mkdir test_dataserver; cd test_dataserver&lt;br /&gt;
** virtualenv . --no-site-packages&lt;br /&gt;
** RTFM: pip help install | less&lt;br /&gt;
** pip install -E . -e ../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+../libdev/ libdev ... FAIL&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk libdev ... FAIL&lt;br /&gt;
** OH WAIT the problem isn&#039;t the dir, it&#039;s the &amp;quot;libdev&amp;quot; afterwards&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/buildouts/libdev/trunk ... FAIL but a new error, no setup.py... wait a sec...&lt;br /&gt;
** pip install -E . -e svn+http://svn.secondlife.com/svn/linden/projects/2008/pyogp/pyogp.lib.base/trunk/ ... WIN&lt;br /&gt;
* should work to just copy a unit test into my src/ dir, copying test_udpconnection.py as it sounds like a good start&lt;br /&gt;
* pip install -E . greenlet&lt;br /&gt;
* bin/python src/test_udpconnection.py ... aaaaaand... no output. Is that a good thing for a test?&lt;br /&gt;
* need some of this:&lt;br /&gt;
&amp;lt;python&amp;gt;&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    unittest.main()&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
* tests pass. Rad! Let&#039;s send some garbage.&lt;br /&gt;
&lt;br /&gt;
== learn to send messages ==&lt;br /&gt;
* pyogp.lib.base/pyogp/lib/base/message/circuit.py - the Host class looks a little thin; doesn&#039;t take a FQDN, just an IP addy?&lt;br /&gt;
* resetting the host in test_find_circuit in my modified copy of test_udpconnection.py doesn&#039;t seem to be hitting the desired host / port&lt;br /&gt;
* try to reverse-engineer class diagram using pylint and graphviz... hmm...&lt;br /&gt;
* finally get *something* - a couple circuits established with the UDPConnectionTest replacing the mock server with my code&lt;br /&gt;
* it&#039;s making me crazy that MockupTestServer and Client don&#039;t seem to map to a real object. It appears to be impossible to trivially modify test_udpconnection.py to connect to a real server instead of a mock.&lt;/div&gt;</summary>
		<author><name>Poppy Linden</name></author>
	</entry>
</feed>