An Integrated Web Application Domain Object Model


Most custom SDK script developers are familiar with the core SDK, a stateless, single user, single server connection, thread agnostic object model. Only one user can create a connection and login at a time, using the SDK api Server.logon(“username”, “password”). Additionally, each com.starteam.Server instance represents a single Tcp/IP connection to the physical StarTeam server. To acquire multiple connections, the application developer needs to create separate Server object instances to the underlying StarTeam server, constrained however, by the fact that the second (or third, …) server instance can still only be acquired using the same user credentials which were already in play for the previous connection. The core SDK is an extremely chatty client server communication protocol. Every request to the server elicits an immediate response. Application developers need to take care to ensure that they carefully ‘bulk up’ the requests to ensure equivalent bulk responses, thereby minimizing network traffic. In this single user model, all access rights are controlled by the StarTeam server. When a user requests data, he is only sent that which he is allowed to see. When a user sends data, the server validates her right to send the change.

In the core SDK object model, each StarTeam object instance (say File, Folder, ChangeRequest etc) has an in-memory cache that contains the data stored for that revision in the server database. The core object caches are thread safe for reading & writing.

Each StarTeam Server object instance in memory manages a Tcp/Ip connection to the physical StarTeam server. Multi threaded data reads or writes to the StarTeam server via the same server object are serialized, i.e. a command cannot be preempted or interrupted by another one. In that sense, the transport protocol itself is thread safe.

Most SDK objects running in the same runtime are generally thread agnostic. For instance, 1 thread using Checkin Manager and another thread using Checkout Manager (using the same connection) can coexist. However, since server commands are serialized, multi-threading does not buy either performance or throughput. Two threads each running a Checkout Manager instance are no faster than 1 thread making 2 separate calls to CheckoutManager.commit in sequence.

Some operations are inherently thread unsafe and can lead to deadlocks. For instance, 2 threads each attempting to use its own instance of Checkin Manager (on the same connection) to commit a set of files could lead to a deadlock. Assume that the first thread starts a server transaction, and the second thread asks to start a transaction, the server blocks the second thread. which will block the first thread from reacquiring the connection. The deadlock will be broken only after the server throws a transaction timeout exception (typically 90 seconds)

The key to performance is bulkification. The more the operations performed with the fewest set of server commands, the better the performance of a StarTeam client, and the better the overall responsiveness of the server to all clients.

The core object model works well for thick client desktop applications or even custom back office scripts, but provides no opportunity to develop scalable multi user web applications.

Current releases of the SDK (14.0 ) address this deficiency by introducing a multi user, multi server, thread safe, connection pool based ‘web’ object model. From an application developer point of view, the web model is disjoint from the core model, even though it is internally based upon the core model. The RESTful StarTeam Web Clients Zuma, Agile and Atlas are Tomcat servlet based web servers, developed on top of the 'webcache' object model. In contrast to the core model, the web model is stateful, requires MPX to be enabled on the server, supports multiple users logging in and out through the SDK instance, and minimizes network traffic by maximizing the data cached in the client. At the heart of this multi-reader, multi-writer model is the basic assumption that reads are ubiquitous, while writes are few and far between. All reads are performed in local memory, with the expectation that little has or will change between reads, while writes are performed on pooled server connections allocated to a requesting thread on demand. If/when external changes occur, they are streamed back to the SDK over MPX using the built in publish/subscribe mechanism, so that subsequent in memory updates result in no additional server commands. Each write on a pooled connection (thread) forces the cache to refresh itself, thereby keeping the memory model in sync with underlying changes.

The ArtifactCacheManager (ACM) manages a set of Artifact Caches (AC) for a given server. The primary cache is the 'tip' or writable cache, and all others (if any) are rolled back (historical, read only) caches.

The Artifact Cache houses the data and provides api's to query & filter the data based on a combination of requesting user access rights and specified query criteria.
The application developer decides what projects/views/types get cached in the tip cache, and for that matter, whether or not to support rolled back caches. The tip cache is loaded at web server startup with the minimum required data from the StarTeam server, in the context of an administrator with full user rights & privileges. Once the tip cache is loaded, users can login through their web browsers, authenticate themselves, and then start browsing or editing items. User browsing is limited to the access rights that they have been granted on the data.

With MPX enabled (the default), server command (read) traffic itself is minimized. Even deploying multiple web servers (using this new web sdk technology) truly reaps the benefits of mpx. Changes issued via one web server are propagated (pushed) out to all the other web servers via mpx.

To access the model, the application developer begins by creating an instance of an ArtifactCache object, through the ArtifactCacheManager.register(ServerInfo) api. The ServerInfo is used to provide credentials such as physical server address and port, user name and password. The specified user name and password must be that of the StarTeam system administrator, with full access (i.e. read and write privilege) to all data in the repository. From this point on, all further calls to prime the cache result in all server instance data being loaded up into the ArtifactCache using the administrative privilege. Additionally, all the access rights for a given data set are loaded into the cache, so that subsequent queries made by users with lesser privileges will result in appropriate data being surfaced accordingly. This method returns a User context (in this case, the Administrative Context), which is characterized by server GUID and {WebCache}User. The User Context object also provides access to the underlying ArtifactCache, and to a WebCacheServer instance. Most application developers will be satisfied with the ‘only’ Tip Cache, which houses all projects, views and types the user is interested in. However, application developers can also create historical caches rolled back to a specific configuration by time, to provide shared, read only views or snapshots of the repository. (Rolled back caches are view specific). Note that each WebCacheXXX type is essentially a wrapper around an equivalent immutable read-only XXXX object from the core SDK. The object graph of WebCacheXXX objects faithfully mirrors the core SDK object graph, as a matter of fact, each WebCache object is defined as a public static object on its core peer. for instance,

WebCacheFolder is a public static member of Folder,

WebCacheView is a public static member of View,

WebCacheServer is a public static member of Server,


Attempting to modify a WebCache object creates a new writable instance in place inside the wrapper. The writable instance is a private copy available only in the context of the current thread, invisible to the shared cache or to any other users on reading or writing threads. Finally, attempting to save the changes made to a ‘dirty’ web cache object allocates a server connection from the pool which is used to stream the change while impersonating the user requesting the change. Unlike the core SDK, the web SDK handles read access rights (visibility) in SDK memory, while allowing the server to handle write access rights. After the changes go through successfully, the writing thread forces the shared cache to refresh itself and returns to the caller with an updated read only object reflective of the new, updated state of the cache.

Writes are managed through a private SDK class called the JobRunner. The JobRunner manages a connection pool of connected StarTeam server instances. Each connection in the pool is instantiated in the context of the administrator with full rights and privileges. However, when a user submits an update, a connection is pulled out of the pool, the connection context is switched to impersonate the user invoking the write operation, the relevant server command(s) are executed, at the end the connection context is switched back to the Administrator, and the connection is returned to the pool ready for reuse. The pool grows as new requests come in, (and no existing connection is available) until at steady state it (the pool) neither grows nor shrinks. Since each connection has it's own Tcp/Ip 'pipe', the commands issued by each thread on each connection execute in parallel. The bottleneck (if any) is now the network!

Registration of the ArtifactCache in the Administrative Context is only done once. Users who are required to log in at lesser privilege do so using the WebCacheServer.logon(“username”, “password”) api, and are logged off using the WebCacheServer.logoff(WebCacheUser) api. Application developers manipulate the cache in individual user context. To do so, the developer may create a Context object using the guid of the server and the userid of a logged in user. Specifying the user context through the model allows the read access rights to be applied; the data returned in any user context is the data that user has the right to see, no more, no less.

The application developer can pick and choose the views and/or types she intends to cache or uncache using the ArtifactCache.cacheViewMembers(WebCacheView, WebCacheViewMemberType) and ArtifactCache.remove(WebCacheView) api’s. Again note that the data for a type within a view must be cached using the administrative user who registered the cache and no other, while all queries against cached view data must be executed in the context of the logged in user (at typically lesser privileges). A request to cache view members fetches all the data for that type for that view from the server, and caches it in memory along with assigned or denied access rights. Note also that this model is not just view centric. It fully supports most StarTeam development objectives including file check in and checkout, user and group maintenance. Additionally, the model also surfaces transactional patterns, such as multi-object locking, creation, update and removal of multiple view members at a time, in a true server transaction, where the expectation is that all operations succeed or fail together. Transactional support is provided through the class WebCacheViewMemberCollection. File checkin and checkout pose an interesting problem. While the api’s are surfaced via WebCacheCheckinManager and WebCacheCheckoutManager, the challenge in the model is that the operations are executed on a web server shared across multiple user context, while file status needs to be maintained on the client desktop, often behind a firewall. Solving this problem required developing  a rich internet application with access to the user desktop, then manipulating the sdk’s status database on disk using a local copy of the SDK on the client (via the FileBasedStatusManager class).

While the WebCache model is inherently memory intensive, it is also highly scalable and provides full multi user support. Stress testing has benchmarked typical reads of 400 users to writes of 40 users per second in Tomcat, making this the model of choice for native 64 bit web application development on Java or .NET (IIS) platforms.

Application developers interested in leveraging the web cache object model will find plenty of examples of use in the junit test suite distributed through the forum, in the namespace com.starteam.test.mpx. The subset of relevant tests is While the syntax of the test suite is Java, the model is fully supported in .NET as well via equivalent C# classes and api’s in the StarTeam.dll assembly.


How To-Best Practice
Comment List