<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>hughpyle : Internals</title><link>http://blogs.msdn.com/hughpyle/archive/tags/Internals/default.aspx</link><description>Tags: Internals</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>GWS Security</title><link>http://blogs.msdn.com/hughpyle/archive/2005/08/15/443433.aspx</link><pubDate>Mon, 15 Aug 2005 16:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:443433</guid><dc:creator>hpyle</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/hughpyle/comments/443433.aspx</comments><wfw:commentRss>http://blogs.msdn.com/hughpyle/commentrss.aspx?PostID=443433</wfw:commentRss><description>&lt;P&gt;&lt;FONT face=Arial size=2&gt;Access to a Groove workstation is controlled by the account passphrase;&amp;nbsp; once the account is unlocked, you can create workspaces, and read and modify data within all your workspaces (according to the permissions you have in those workspaces).&amp;nbsp; Similarly, the web services interface doesn't introduce any additional access control restrictions.&amp;nbsp; The Groove Web Services APIs allow essentially unrestricted access to everything within an account.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The secret key to unlock GWS access, however, is not the account passphrase.&amp;nbsp; (Your account passphrase is never stored on disk, and we don't want to send it over a TCP port either; it's not just secret, it's personal too).&amp;nbsp; So the GWS designers needed to create something else for authentication -- authentication of an application (a process running on the local machine, usually) which wants access to your Groove data.&amp;nbsp; (The account must also be logged in, by the user typing their passphrase, because the passphrase really does key the cryptographic stuff of the account.&amp;nbsp; If a GWS application requests access to a workspace when the account is not logged in, Groove will pop up the login dialog).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The solution is implemented using a registry key in the HKCU hive.&amp;nbsp;&amp;nbsp; When Groove starts, it creates a strong random secret, and writes that to a "current user" registry location (HKCU\Software\Groove Networks, Inc.\Groove\WebServices\LocalRequestKey).&amp;nbsp; Local web services requests must provide that key value, which they can obtain by reading the registry (ie. by having a certain level of access to the local system).&amp;nbsp; The key value may change at any time.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;To avoid man-in-the-middle attacks on web services accesses, Groove also provides a LocalResponseKey in its SOAP responses, which again can be validated against the local registry if you want.&amp;nbsp; Groove also writes its process ID to HKCU\Software\Groove Networks, Inc.\Groove\GrooveLocalHTTPServerPID.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Remote access -- usually only deployed for EDB servers where an integration application is running on a separate server in the data center -- uses a slightly different method;&amp;nbsp; there's a different registry key (HKCU\...\RemoteRequestKey), but this one can be set to any value and remain constant, if appropriate.&amp;nbsp; Confidentiality of the remote key and the network traffic is not done by Groove, so for remote applications you probably want a dedicated LAN segment and IPSEC, or some other mechanism, to secure the SOAP access.&amp;nbsp; (Remote access is also disabled by default, and you need policy settings to switch it on.&amp;nbsp; WS-Security: not yet.)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The other missing piece from my first code was the GWS HTTP port (which defaults to 9080).&amp;nbsp; Again, there's a local registry key (HKCU\Software\Groove Networks, Inc.\Groove\GrooveLocalHTTPPort) updated by Groove when it starts listening.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;To write an application calling local Groove web services, then, we need a few helper routines to provide access to these values.&amp;nbsp; Each SOAP request sent to Groove must include the request key in the &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconUsingSOAPHeaders.asp"&gt;&lt;FONT face=Arial size=2&gt;SOAP header&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Arial size=2&gt;, and the call must be targeted at the appropriate TCP port.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Here's my (static) util class which implements this.&amp;nbsp; (Note: there's no dependency on the Groove WSDL web references):&lt;/FONT&gt;&lt;/P&gt;
&lt;DIV class=code&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT color=#0000ff size=1&gt;
&lt;P&gt;namespace&lt;/FONT&gt;&lt;FONT size=1&gt; GrooveContactsAddin&lt;/P&gt;
&lt;P&gt;{&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;static&lt;/FONT&gt;&lt;FONT size=1&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;class&lt;/FONT&gt;&lt;FONT size=1&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=1&gt;GWSUtil&lt;/P&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;P&gt;{&lt;/P&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;static&lt;/FONT&gt;&lt;FONT size=1&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;public&lt;/FONT&gt;&lt;FONT size=1&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;string&lt;/FONT&gt;&lt;FONT size=1&gt; GrooveURL&lt;/P&gt;
&lt;P&gt;{&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;get&lt;/P&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;P&gt;{&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;string&lt;/FONT&gt;&lt;FONT size=1&gt; url;&lt;/P&gt;
&lt;P&gt;Microsoft.Win32.&lt;/FONT&gt;&lt;FONT color=#008080 size=1&gt;RegistryKey&lt;/FONT&gt;&lt;FONT size=1&gt; HKCU_GrooveRegKey = Microsoft.Win32.&lt;/FONT&gt;&lt;FONT color=#008080 size=1&gt;Registry&lt;/FONT&gt;&lt;FONT size=1&gt;.CurrentUser.OpenSubKey(&lt;/FONT&gt;&lt;FONT color=#800000 size=1&gt;@"Software\Groove Networks, Inc.\Groove"&lt;/FONT&gt;&lt;FONT size=1&gt;);&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;object&lt;/FONT&gt;&lt;FONT size=1&gt; DesiredGroovePort = HKCU_GrooveRegKey.GetValue(&lt;/FONT&gt;&lt;FONT color=#800000 size=1&gt;"GrooveHTTPDesiredPort"&lt;/FONT&gt;&lt;FONT size=1&gt;, &lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;null&lt;/FONT&gt;&lt;FONT size=1&gt;);&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;if&lt;/FONT&gt;&lt;FONT size=1&gt; (DesiredGroovePort != &lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;null&lt;/FONT&gt;&lt;FONT size=1&gt;)&lt;/P&gt;
&lt;P&gt;{&lt;/P&gt;
&lt;P&gt;url = &lt;/FONT&gt;&lt;FONT color=#800000 size=1&gt;"http://localhost:"&lt;/FONT&gt;&lt;FONT size=1&gt; + DesiredGroovePort;&lt;/P&gt;
&lt;P&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;else&lt;/P&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;P&gt;{&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;object&lt;/FONT&gt;&lt;FONT size=1&gt; GroovePort = HKCU_GrooveRegKey.GetValue(&lt;/FONT&gt;&lt;FONT color=#800000 size=1&gt;"GrooveLocalHTTPPort"&lt;/FONT&gt;&lt;FONT size=1&gt;, &lt;/FONT&gt;&lt;FONT color=#800000 size=1&gt;"9080"&lt;/FONT&gt;&lt;FONT size=1&gt;);&lt;/P&gt;
&lt;P&gt;url = &lt;/FONT&gt;&lt;FONT color=#800000 size=1&gt;"http://localhost:"&lt;/FONT&gt;&lt;FONT size=1&gt; + GroovePort;&lt;/P&gt;
&lt;P&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;return&lt;/FONT&gt;&lt;FONT size=1&gt; url;&lt;/P&gt;
&lt;P&gt;}&lt;/P&gt;
&lt;P&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;static&lt;/FONT&gt;&lt;FONT size=1&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;public&lt;/FONT&gt;&lt;FONT size=1&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;string&lt;/FONT&gt;&lt;FONT size=1&gt; GrooveLocalRequestKey&lt;/P&gt;
&lt;P&gt;{&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;get&lt;/P&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;P&gt;{&lt;/P&gt;
&lt;P&gt;Microsoft.Win32.&lt;/FONT&gt;&lt;FONT color=#008080 size=1&gt;RegistryKey&lt;/FONT&gt;&lt;FONT size=1&gt; HKCU_GrooveWebServicesRegKey = Microsoft.Win32.&lt;/FONT&gt;&lt;FONT color=#008080 size=1&gt;Registry&lt;/FONT&gt;&lt;FONT size=1&gt;.CurrentUser.OpenSubKey(&lt;/FONT&gt;&lt;FONT color=#800000 size=1&gt;@"Software\Groove Networks, Inc.\Groove\WebServices"&lt;/FONT&gt;&lt;FONT size=1&gt;);&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;string&lt;/FONT&gt;&lt;FONT size=1&gt; key = (&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;string&lt;/FONT&gt;&lt;FONT size=1&gt;)HKCU_GrooveWebServicesRegKey.GetValue(&lt;/FONT&gt;&lt;FONT color=#800000 size=1&gt;"LocalRequestKey"&lt;/FONT&gt;&lt;FONT size=1&gt;);&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;return&lt;/FONT&gt;&lt;FONT size=1&gt; key;&lt;/P&gt;
&lt;P&gt;}&lt;/P&gt;
&lt;P&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;static&lt;/FONT&gt;&lt;FONT size=1&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;public&lt;/FONT&gt;&lt;FONT size=1&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;string&lt;/FONT&gt;&lt;FONT size=1&gt; GrooveLocalResponseKey&lt;/P&gt;
&lt;P&gt;{&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;get&lt;/P&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;P&gt;{&lt;/P&gt;
&lt;P&gt;Microsoft.Win32.&lt;/FONT&gt;&lt;FONT color=#008080 size=1&gt;RegistryKey&lt;/FONT&gt;&lt;FONT size=1&gt; HKCU_GrooveWebServicesRegKey = Microsoft.Win32.&lt;/FONT&gt;&lt;FONT color=#008080 size=1&gt;Registry&lt;/FONT&gt;&lt;FONT size=1&gt;.CurrentUser.OpenSubKey(&lt;/FONT&gt;&lt;FONT color=#800000 size=1&gt;@"Software\Groove Networks, Inc.\Groove\WebServices"&lt;/FONT&gt;&lt;FONT size=1&gt;);&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;string&lt;/FONT&gt;&lt;FONT size=1&gt; key = (&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;string&lt;/FONT&gt;&lt;FONT size=1&gt;)HKCU_GrooveWebServicesRegKey.GetValue(&lt;/FONT&gt;&lt;FONT color=#800000 size=1&gt;"LocalResponseKey"&lt;/FONT&gt;&lt;FONT size=1&gt;);&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=1&gt;return&lt;/FONT&gt;&lt;FONT size=1&gt; key;&lt;/P&gt;
&lt;P&gt;}&lt;/P&gt;
&lt;P&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;P&gt;}&lt;/P&gt;
&lt;P&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=443433" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/hughpyle/archive/tags/Web+Services+demo/default.aspx">Web Services demo</category><category domain="http://blogs.msdn.com/hughpyle/archive/tags/Internals/default.aspx">Internals</category></item><item><title>Deep dive: how Groove Forms synchronizes data</title><link>http://blogs.msdn.com/hughpyle/archive/2005/07/22/441847.aspx</link><pubDate>Fri, 22 Jul 2005 18:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:441847</guid><dc:creator>hpyle</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/hughpyle/comments/441847.aspx</comments><wfw:commentRss>http://blogs.msdn.com/hughpyle/commentrss.aspx?PostID=441847</wfw:commentRss><description>&lt;P&gt;&lt;FONT face=Arial size=2&gt;As I mentioned &lt;/FONT&gt;&lt;a href="http://blogs.msdn.com/hughpyle/archive/2005/07/21/441507.aspx"&gt;&lt;FONT face=Arial size=2&gt;earlier&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Arial size=2&gt;, Groove's essential magic is that all members of a workspace see the same information in the space.&amp;nbsp; That's maintained even though members can work offline (each member has a copy of each of their workspaces, so all the information is available when you're disconnected, and you can work in the space regardless of network connectivity), or be in separate companies behind firewalls.&amp;nbsp; And there's no central server; none of your workspace data is permanently stored anywhere else than on the machines of the workspace members.&amp;nbsp; The synchronization happens automatically, immediately, and is extremely resilient; it's designed to be "sufficiently advanced".&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;There's lots of depth in the mechanics, and I don't plan to dive into all of it.&amp;nbsp; (If you want reading material, try the &lt;/FONT&gt;&lt;A href="http://www.groove.net/index.cfm/pagename/SupportDocs/"&gt;&lt;FONT face=Arial size=2&gt;product docs&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Arial size=2&gt;, or even look up the patent numbers on Groove's About box: 6446113, 6640241, 6859821).&amp;nbsp; But it'll be helpful to understand the overall structure of Groove and how it works.&amp;nbsp; (Standard "how-internals-work" disclaimer goes here.&amp;nbsp; I'm just writing down what I believe to be the case about how things work; it may not all be correct, and of course might change in the future too, so don't rely on this the way you'd use official documentation.)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Physically, each workspace is a database file; they're files with .XSS extension (and corresponding transaction logs), usually to be found under &amp;lt;user&amp;gt;\Local Settings\Application Data\Groove Networks\Groove\accounts\&amp;lt;id&amp;gt;\telespaces.&amp;nbsp; These databases are encrypted (with your account key).&amp;nbsp; The file format is Groove-developed; essentially each XSS file is a collection of binary and/or XML documents.&amp;nbsp; There's a Groove subsystem called Storage Manager which is responsible for reading and writing the databases on disk, managing the transaction integrity, and so on.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Your Groove account is also stored in an XSS database file (id.xss).&amp;nbsp; Actually, the "account telespace" shares lots of characteristics with regular Groove workspaces; it's a distributed database in exactly the same way, so you can have your whole Groove account installed on multiple devices, which will all keep in sync.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Synchronization is performed by a subsystem called Dynamics Manager, reading and writing to the network via a subsystem called Communications Manager.&amp;nbsp; But to understand Dynamics, we should first take apart a workspace and peek inside.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The workspace is a container for Tools (there's a ToolContainer COM component which implements tool-containing-stuff).&amp;nbsp; We've already seen some of the user-visible tools; and there are several invisible tools too;&amp;nbsp; one to manage the member list, one for managing the tabs which display UI (the RootDisplay tool), and a few others.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Tools themselves are quite complex.&amp;nbsp; There's a tool template: an XML document which defines all the components and their connections (the components, at this level, are really COM components which implement parts of the tool's functionality).&amp;nbsp; Tools mostly all have the same sorts of components, in a Model-View-Controller structure:&amp;nbsp; there's a data-management piece (one or more Engines, and a DataDelegate providing programming interfaces to the outside world), a user interface (with its widgets usually being COM components arranged according to the spec in the tool template, and a ViewContainer managing the layout), and glue between them (UIDelegate code of some sort, usually written in C++, but historically also plenty of JavaScript).&amp;nbsp; A tool also has a ToolDescriptor, which is a small XML document describing the tool: its name, version, the location of the template, and so on.&amp;nbsp; (If you invite someone to a workspace, usually they're sent each tool descriptor and the engine data but not the tool template; the descriptor tells the client where to get the template).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Internally, every component -- &lt;STRONG&gt;every&lt;/STRONG&gt; component -- is addressable by URL.&amp;nbsp; In the case of an Engine, this URL is really important; it's used as the name of a message queue.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Engines are where work happens on a tool's data.&amp;nbsp; Let's take the example of a Forms tool; the tool has an engine called RDB (for "record database"), and RDB knows how to maintain reasonably large data sets with multiple schemas and indexes.&amp;nbsp; (RDB uses a btree-type structure; maybe Ed can expand on the details sometime, but honestly the details aren't very important.&amp;nbsp; One change in RDB over its predecessor RSE (recordset engine) is that RSE stored XML, where RDB is binary - &lt;/FONT&gt;&lt;A href="http://weblog.infoworld.com/udell/2004/05/04.html"&gt;&lt;FONT face=Arial size=2&gt;Jack Ozzie and Jon Udell discussed this&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Arial size=2&gt; a while back).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The outside world talks to an Engine by sending it transactions, or commands.&amp;nbsp; So in the Forms tool and the RDB underneath it, there are a few basic transaction commands: "CreateRecord", "DeleteRecord", "SetField".&amp;nbsp; When a user (at the Groove user interface) saves a Forms record, the View code tells the DataDelegate to create a record with certain field values, and the Engine receives a "CreateRecord" command with those field values inside.&amp;nbsp; Or, if the user edits an existing record to change a field value, the engine sees one or more "SetField" commands (possibly wrapped inside an outer transaction, so the field changes all apply atomically).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Synchronization between workspace members happens at this level:&amp;nbsp; the transaction (a distributed transaction in Groove is called a Delta).&amp;nbsp; Dynamics Manager sees the command to the local engine, and creates a copy of that command for each other member of the workspace, wraps them inside a routing packet (XML), and puts those commands into a queue.&amp;nbsp; The queue is "targeted" at the same engine URL, but for each other device in the workspace.&amp;nbsp; Communications Manager can then route data in the queues (encrypted) across the network to every other member;&amp;nbsp; depending on your communications state, the transactions can be sent directly to the receiving device (peer to peer), or be sent to the recipient's relay server (to sit in a queue -- if you have access to a relay server's management UI you can see the queues -- the &lt;/FONT&gt;&lt;A href="http://docs.groove.net/admin/ers/RelayServerAdministratorsGuide.pdf"&gt;&lt;FONT face=Arial size=2&gt;relay admin guide&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Arial size=2&gt; has lots more detail, but unfortunately no screenshots).&amp;nbsp; Or you might be completely offline, in which case the transactions sit in queue on your own machine until they can be offloaded.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Meanwhile, Communications Manager is also listening to connections from other devices, and dequeueing transactions from your own relay server, and sending those transactions to Dynamics Manager to tell your tools' Engines that their state must change.&amp;nbsp; Dynamics Manager is the middleman, and for good reason: it takes care of transaction sequencing.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Since you can work offline, there's no guarantee that your machine will&amp;nbsp;receive transactions in anything like the same order as other members of the workspace.&amp;nbsp; You might create some deltas yourself offline, which then need to be "later" than work done by other members while you were disconnected.&amp;nbsp; In an extreme (but common) case, for example, you could be working offline for a long period, then drive by a WiFi connection and manage to send a fraction of your outgoing queue data, then disconnect again, do some more work, and reconnect.&amp;nbsp; So it's entirely possible that other workspace members see a different set of deltas than you.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Each delta is assigned a sequence number, and Dynamics Manager maintains a table of which deltas are known to you, and which of those you know are also known to all other members of the space (so they can be purged from the log), and which might be fetchable from other online members, and so on.&amp;nbsp; If you have delta A and C, then receive delta B from another member, then Dynamics will decide (based on the dependency nesting of the transactions) whether it can just insert B right away, or whether it should tell the engine to undo transaction C, then apply B, then reapply C.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The magic of this is twofold.&amp;nbsp; First, the Dynamics Manager sequencing doesn't care about the actual data, or the implementation of the particular Engine; it's only concerned with the transaction sequencing and dependencies, and filling in any gaps in your transaction history.&amp;nbsp; Second, everything happens completely transparently to the user (even if there's a fairly large rollback and rollforward -- you might notice a performance glitch there, but big rollbacks are very rare), and the result is that all members of the workspace will always see a consistent transaction sequence, and they'll &lt;U&gt;all see the same sequence&lt;/U&gt; (eventually).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;So, back to the Forms tool.&amp;nbsp; The RDB engine underneath Forms manages distributed transactions (insert, update, delete) against records, and other things such as schema changes, within your tool.&amp;nbsp; If a record changes because another user changed it, the engine will assimilate that transaction, then notify the View to update the display -- immediately, if the user's working in that tool at the time.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Now, not all data in Groove is always disseminated.&amp;nbsp; Files in a Files tool are one example; the "stub" of the file is always disseminated, but the file contents can be fetched on demand if appropriate.&amp;nbsp; The Forms Designer Sandbox is another example: if you open the forms designer to make changes in the tool (adding or modifying fields, forms, views), those changes are only stored in your local device until you hit the "Save to Groove" button.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The end result is that users can work with your forms, creating, reading and updating rich documents, and Groove takes care of all the synchronization stuff to ensure that everyone has a consistent view of the world.&amp;nbsp;&amp;nbsp; (Should I talk about conflicts at this point?&amp;nbsp; Naah, never happens.&amp;nbsp; Or rather, with most Forms applications conflicts are rare enough that I can leave that for another day.&amp;nbsp; Remind me, later).&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=441847" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/hughpyle/archive/tags/Internals/default.aspx">Internals</category></item><item><title>Digression: the types of fields</title><link>http://blogs.msdn.com/hughpyle/archive/2005/07/22/441792.aspx</link><pubDate>Fri, 22 Jul 2005 15:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:441792</guid><dc:creator>hpyle</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/hughpyle/comments/441792.aspx</comments><wfw:commentRss>http://blogs.msdn.com/hughpyle/commentrss.aspx?PostID=441792</wfw:commentRss><description>&lt;P&gt;&lt;FONT face=Arial size=2&gt;Groove Forms forms are constructed by laying out fields on a page.&amp;nbsp; Actually, fields are just about the only things on the page (apart from field-groups and tab-groups, which we'll get to some time later).&amp;nbsp; So a "field", in the form designer, encompasses several things which you might not usually consider as data entry or data definition -- buttons, for example.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;That's why the list of field types in the "Create New Field" dialog is quite so long.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Let's break down that list and look at each type of field in turn.&amp;nbsp; First the usual suspects: fields for entering data in a form.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;STRONG&gt;Data entry fields&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.cabezal.com/msdnblog/04-field1-text.PNG" align=right&gt;&lt;STRONG&gt;Text&lt;/STRONG&gt;: a single-line text box.&amp;nbsp; There's no real limit on the size of text you can enter in one of these (but it's always entered on a single line); optionally, you can specify a maximum length, which restricts users from entering text beyond that limit, as well as other types of input validation.&amp;nbsp; When displayed on a form, the field actually has two parts: the input box, and a label beside it (to the left, or to the right, or above it).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.cabezal.com/msdnblog/04-field2-multiline.PNG" align=right&gt;&lt;STRONG&gt;Multi-line Text&lt;/STRONG&gt;: a multiple-line text box.&amp;nbsp; You can specify the width and height.&amp;nbsp; Like all text fields, the amount of text Groove can store in a multi-line field is effectively unlimited.&amp;nbsp; You can also specify validation in the same way as a text field:&amp;nbsp; to ensure that the text contains a particular string, or doesn't, or is a valid email address or ZIP, and so on -- quite a long list of options.&amp;nbsp; (It's also possible to write code for extra validation).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.cabezal.com/msdnblog/04-field3-number.PNG" align=right&gt;&lt;STRONG&gt;Number&lt;/STRONG&gt;: a single-line entry to hold a number.&amp;nbsp; It looks just like a text field, but doesn't allow non-numeric values.&amp;nbsp; Number fields can define a precision (the number of digits after the decimal point), and can restrict input to numbers in a particular range.&amp;nbsp; Now, numbers are stored differently from text in the Groove records' data; for example, you can build a view which adds up the total of a number field across several records -- can't do that with text.&amp;nbsp; Internally, numbers are double-precision floating point values.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Unformatted Number&lt;/STRONG&gt;: like a number field, but doesn't format the number with the user's locale's numeric formatting -- separating thousands with commas, or whatever.&amp;nbsp; (You can't change the type of a field after you create it, so it's unfortunate that display formatting isn't just a property on a regular numeric field.&amp;nbsp; Oh well.)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Currency&lt;/STRONG&gt;: like a number field, but displays using a currency format.&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;
&lt;P&gt;&lt;IMG src="http://www.cabezal.com/msdnblog/04-field8-password.PNG" align=right&gt;&lt;STRONG&gt;Password&lt;/STRONG&gt;: a text field where the input only displays as dots to hide your secret.&amp;nbsp; (The data you&amp;nbsp;enter in a password field is NOT encrypted in any special way.&amp;nbsp; Which is to say, it's encrypted multiple times with astounding confidentiality strength before being stored in Groove or transmitted to other members of the workspace, just like all data in a Groove workspace; and when the data arrives on another member's machine, after they handshake to verify that it wasn't spoofed or manipulated in transit and that the information originated from exactly who you claim to be, it's decrypted with a stunningly deep reverse of the original encryption algorithm, so that the other members&amp;nbsp;can look at it if they want to).&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.cabezal.com/msdnblog/04-field4-date.PNG" align=right&gt;&lt;STRONG&gt;Date&lt;/STRONG&gt;: a date (with no time portion; just the date).&amp;nbsp; In the form, date fields show a calendar button beside the date input box;&amp;nbsp; pressing this button &lt;A href="http://www.cabezal.com/msdnblog/04-popup-date.PNG"&gt;opens a calendar&lt;/A&gt; (defaulting to today's date if the field is empty).&amp;nbsp; You can design the field to have an initial value (a particular date, or "today", "tomorrow"), choose the date format, and validate that the date lies within a particular range.&amp;nbsp; (Again, it's possible to add code for more particular validation).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.cabezal.com/msdnblog/04-field5-datetime.PNG" align=right&gt;&lt;STRONG&gt;Date Time&lt;/STRONG&gt;: a date and time.&amp;nbsp; The calendar picker popup for a date/time field includes a &lt;A href="http://www.cabezal.com/msdnblog/04-popup-datetime.PNG"&gt;time picker&lt;/A&gt; too.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.cabezal.com/msdnblog/04-field6-optionbuttons.PNG" align=right&gt;&lt;STRONG&gt;Option &lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Buttons&lt;/STRONG&gt;, aka Radio Buttons.&amp;nbsp; The field includes a list of options;&amp;nbsp; for each option, you can specify the "display value" (which appears beside the selection button in the list) and also a "stored value" (which is saved into the record when that option is chosen).&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The options needn't be hard-coded; they can come from a lookup (ie. pulling data from a set of records in Groove).&amp;nbsp; Since we haven't yet created any records in the contacts-form example I'm building, we'll cover lookups&amp;nbsp;another time.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.cabezal.com/msdnblog/04-field7-checkbox.PNG" align=right&gt;&lt;STRONG&gt;Check Box&lt;/STRONG&gt;: just one checkbox.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.cabezal.com/msdnblog/04-field10-dropdown.PNG" align=right&gt;&lt;STRONG&gt;Drop-down List&lt;/STRONG&gt;: what it says.&amp;nbsp; Options are defined the same way as for Option Buttons fields and List Box fields.&amp;nbsp; Optionally, you can have the drop-down list include a blank value; otherwise, it'll default to the first option.&amp;nbsp; And that "+" button is another option, allowing users to add their own values to the list (pressing it opens a little &lt;A href="http://www.cabezal.com/msdnblog/04-popup-customlistentry.PNG"&gt;custom entry dialog&lt;/A&gt;).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.cabezal.com/msdnblog/04-field9-listbox.PNG" align=right&gt;&lt;STRONG&gt;List Box&lt;/STRONG&gt;: a list box.&amp;nbsp; Specify the options, and the size of the listbox, and whether to allow multiple selections.&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial size=2&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;STRONG&gt;Other types of data&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;All the standard field types above should be fairly familiar.&amp;nbsp; If you're looking closely, you might notice that they're implemented with HTML;&amp;nbsp; the form, it turns out, is actually a web page inside of the Groove forms tool (which is the basis for the custom scripting we'll get into later).&amp;nbsp; But there are some types of fields which go way beyond HTML's usual capabilities, allowing the form to become more dynamic.&amp;nbsp; These fields are:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.cabezal.com/msdnblog/04-extra1-richtext.PNG" align=right&gt;&lt;STRONG&gt;Rich Text&lt;/STRONG&gt;.&amp;nbsp; A proper rich-text entry field, with text and paragraph formatting.&amp;nbsp; In the example pictured here, I set some default contents for the richtext field, and also turned the background blue.&amp;nbsp; The toolbar is optional; right-clicking pops up a formatting menu.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The richtext field, like the other fields, has an optional field label beside it; and you can specify the width and height.&amp;nbsp; One thing you can't easily do is specify validation of the contents, though.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;It even has a built-in spell-checker; press F7.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.cabezal.com/msdnblog/04-extra2-attachments.PNG" align=right&gt;&lt;STRONG&gt;Attachments&lt;/STRONG&gt;: a place to attach one or more files of any type.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="http://www.cabezal.com/msdnblog/04-extra3-contact.PNG" align=right&gt;&lt;STRONG&gt;Contact&lt;/STRONG&gt;: a field which contains a real, "live", groovey contact.&amp;nbsp; This is very special, actually; maybe we'll use one of these in the contact-form example.&amp;nbsp; If there's a Groove contact in the field it will display online awareness, and you can right-click to send instant message, add to your personal contact list, invite to a workspace, and so on.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;STRONG&gt;Non-Data Fields&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Finally, the oddments and assortments.&amp;nbsp; These fields appear on a form, but there's no data stored in them.&amp;nbsp; (When I first started using Forms, I immediately wanted to add a button onto a form, and have some JavaScript run when&amp;nbsp;the button was clicked.&amp;nbsp; Turns out this is really easy, but it took me a while to realize how:&amp;nbsp; the secret is that buttons are fields.&amp;nbsp; And newlines are fields too.&amp;nbsp; Now isn't that cute?).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;I'm all out of screenshots for this lot.&amp;nbsp; Their look-and-feel is defined mostly by the stylesheet used on the form anyway;&amp;nbsp; stylesheets are another important thing on the "later" list.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Form Heading&lt;/STRONG&gt;: a heading for the form.&amp;nbsp; You usually never have more than one of these per form.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Section Heading&lt;/STRONG&gt;: another piece of heading text, usually big and bold.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Static Text&lt;/STRONG&gt;: just a random piece of text; for an extra label, for example.&amp;nbsp; The default formatting is different from a section heading or a form heading.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Horizontal Line&lt;/STRONG&gt;: a rule across the form (or across part of the form).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;New Line&lt;/STRONG&gt;: a line-break on the form.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Image&lt;/STRONG&gt;: a picture (not editable by the user).&amp;nbsp; Use an image field to put your logo on a form, for example.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Script Button&lt;/STRONG&gt;: a button, with some script attached; when you press the button it runs the script.&amp;nbsp;&amp;nbsp; The script has access to everything in the current state of the form, and the record underneath the form;&amp;nbsp; forms scripting is quite powerful (and really not difficult, but we'll get to the details soon),&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=441792" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/hughpyle/archive/tags/Internals/default.aspx">Internals</category></item></channel></rss>