SAS 9.1.3 Integration Technologies » Developer's Guide


Using the Workspace Manager
Launching IOM Servers
Administering the SAS Workspace Manager
SAS Workspace Manager Interfaces
Error Reporting
Using Workspace Pooling
Code Samples
Windows Clients

Using Workspace Pooling

Workspace pooling enables you to create a pool of connections to IOM servers that are shared and reused amongst multiple client applications. This feature can dramatically reduce connection times in environments where one or more client applications make frequent but brief requests for IOM services. This is typically the case, for example, in Active Server Pages (ASP) applications. Pooling reduces the wait that an application incurs when establishing a connection to SAS and is therefore most efficient when used in such applications. A pooled workspace does not offer any significant advantage in applications that use workspaces for an extended period of time.

The Workspace Manager supports two different pooling mechanisms: COM+ pooling and Integration Technologies pooling. The most noticeable difference between the two mechanisms is the way in which the pools are administered. They also differ in the way the programmer makes the call to get the pooled workspace.

In both the COM+ case and the Integration Technologies case, the WorkspaceManager represents a pooled workspace with the PooledWorkspace COM object. This object has a single property: workspace. Once a PooledWorkspace object is obtained, the calling application keeps a reference to the PooledWorkspace object for as long as it needs to use the workspace. Releasing the PooledWorkspace object returns the associated workspace to the pool. It also causes the workspace to be cleaned up, so it is impossible to make any more calls on the workspace once the associated PooledWorkspace is released.

COM+ Pooling

COM+ Workspace Pooling is only available on operating systems that support COM+, for example, Windows 2000. It cannot be used on Windows NT, Windows 95, or Windows 98. Another limitation of the COM+ mechanism is that it only allows a single pool on any given machine at a time (Microsoft may change this in future releases of Windows 2000).

COM+ pools can be configured in two different ways:

  • Library application

    With a library application, each process has it's own pool.

  • Server application

    With a server application, the pool is shared by all processes on the same machine.

Administration

Administration of a COM+ pool is done using the COM+ Component Services administrator, which is a standard Microsoft Management Console (MMC) snap-in that comes with Windows 2000.

To create a new COM+ server application:

  1. Start the Component Services administrator: select Start->Programs->Administrative Tools->Component Services
  2. Expand Component Services->Computer->COM+ Applications. Right click on COM+ Applications and select New->Application. This starts a wizard. Click next.
  3. Select to Create an Empty Application
  4. Enter a name of your choice, and select an Activation Type of Server application. Click next.
  5. Specify an identity, and click next.
  6. Click finish

To add the PooledWorkspace component to the application:

  1. Expand the application your created above in the tree view, so you see Components and Roles.
  2. Click on Components, then right click and select New->Component, which brings up a wizard.
  3. Click next, then Import components that are already registered.
  4. Select SASWorkspaceManager.PooledWorkspace.1, then click Next and Finish.

To administer the pooling properties:

  1. Click on SASWorkspaceManager.PooledWorkspace.1 under the Components node of the application you created.
  2. Right click on SASWorkspaceManager.PooledWorkspace.1, and select properties.
  3. Select the Activation tab.
  4. Click the "Enable object pooling" check box. Now enter the properties you want.
  5. You can also enter a constructor string here, which allows you to specify which machine SAS should run on. The constructor string is described below.

The Constructor String

The only SAS-specific attributes here are those that are necessary in the Constructor String. The constructor string is a single string that specifies the parameters that are used to initially create the pool. The Workspace Manager requires that the constructor string contain a set of name value pairs, with the names separated from the values by an equal (=), and the pairs separated by a semi colon (;). If no parameters are specified, then a pool consisting of SAS servers running on the local machine will be created. You should never use quotes in the constructor string.

logicalname
Specifies which sasServer objects to use when creating Workspaces in the pool. This can only be used when workspace definitions are persisted in a file or LDAP. The location of the file or LDAP server is found by the workspace manager in the system registry.
referencedn
Specifies the referenceDN to use for authentication. This is only necessary when a sasServer is found that requires the bridge.
machineDNSName
The name of the machine to connect to.
protocol
Either "com" or "bridge" (don't use the quotes).
port
The port number of a bridge server to connect to.
serviceName
Used to resolve a TCP/IP service to a port number. This should only be specified for a "bridge" protocol. Only one of port or serviceName should be specified.
loginName
The userid to use when connecting to a SAS server with the "bridge" protocol.
password
The password which authenticates the loginName.

Here is an example of a valid constructor string:

   logicalname=pooltest;referencedn=cn=Dan,cn=Users,dc=dtd-dom,dc=sas,dc=com

The WorkspaceManager will write entries to the Event Log if errors occur when creating a workspace. This log will include the constructor string being used.

Using COM+ Pooling

To obtain a PooledWorkspace object, the programmer simply creates a new PooledWorkspace object using COM, just as he would with any other COM component. The COM+ interceptors detect this and take care of pooling the PooledWorkspace objects. The PooledWorkspace object has been written to support the COM+ pooling mechanism.

Here is an example of using COM+ pooling.

Integration Technologies Pooling

There are several reasons why you might choose Integration Technologies pooling instead of COM+:

  1. You don't have COM+.
  2. You want multiple pools on the same machine.
  3. You want to use the security mechanism available in Integration Technologies pooling.
  4. You want to use the same administration model for Java applications and COM applications.
  5. You want to specify the pooling parameters in the source code.

Note that Java applications and COM applications cannot share the same pool, but they can share the administration model used for the pools.

An important concept to note is that a pool is defined by a logical name. When using WorkspacePools.CreatePoolByLogicalName, a single pool can contain Workspaces from multiple Servers and multiple logins. When using WorkspacePools.CreatePoolByServer, a pool will consist of Workspaces from a single Server and a single Login.

The authentication and authorization checking in Integration Technologies pooling allows you to create a pool that contains SAS Workspaces that have been authenticated using different user id's. This is useful for allowing the access to sensitive data to be controlled on the server machine instead of the middle tier. Checking is only performed in pools that were created with CreatePoolByLogicalName where the checkCredentialsOnEachGet parameter is set to TRUE.

Authentication is done by binding to the LDAP server using the referenceDN and referenceDNPassword provided to GetPooledWorkspace. If that bind fails, then GetPooledWorkspace will return INVALID_LDAP_CREDENTIALS. That connection will be released, and the main LDAP connection (as defined by calls to IWorkspaceManager.SetLDAPServer and IWorkspaceManager.SetLDAPUser) will then be used to lookup the allowedClientDN attribute on Logins that are appropriate for the requested pool. If a match is not found, then ERROR_ACCESS_DENIED is returned (0x80004005). Otherwise, a pooled workspace will be returned when one becomes available. Use of this feature allows user IDs and passwords to be used by people who are not allowed to know what those user ID and/or passwords are (assuming the security settings are specified properly in the LDAP server.) Only the userDN specified in SASWorkspaceManager.SetLDAPUser needs to have access to the login information.

Administration

Pool parameters can be specified in one of three places:

  1. In LDAP. This is done using the IT Administrator. This requires the WorkspaceManager.Scope property to be ScopeGlobal.
  2. In an LDIF-formatted file. Editing of the file is done by your favorite text editor. This requires the WorkspaceManager.Scope property to be either ScopeLocal or ScopeUser. The location of the file is determined by WorkspaceManager.FilePath.
  3. In source code. Create both a sasServer object and a sasLogin object, then fill out the relevant properties, then pass those to WorkspaceManager.WorkspacePools.CreatePoolByServer. In the above code, the line below could be added to specify the maximum number of workspaces that can be created in this pool:
    obServer.MaxPerWorkspacePool = 6

The following parameters are used to configure Integration Technologies pooling. The parameters are specified in either the serverDef or loginDef object.

ServerDef.MaxPerWorkspacePool
Specifies the maximum number of servers that should be created from the provided ServerDef object. A good starting place for this number is the number of CPUs that are available on the machine that's running SAS.
ServerDef.RecycleActivationLimit
Specifies the number of times that a Workspace is used before the process it is running in is replaced. This is useful for capping any memory leaks or non-scalable resource usage. A value of 0 means to never recycle the processes.
ServerDef.RunForever
The value for this property must be either true or false. If the value is false, then unallocated live connections will be disconnected after a period of time (specified by the value of ServerDef.ShutdownAfter). If the value is true (the default value), unallocated live connections will remain alive indefinitely. This property is optional.
ServerDef.ServerShutdownAfter
Specifies the number of minutes that an unallocated live connection will wait to be allocated to a user before shutting down. This property is optional and it is ignored if the value of ServerDef.ServerRunForever is true. The value must not be less than 0, and it must not be greater than 1440 (the number of minutes in a day). The default value is 3. If the value is 0, then a connection returned to a pool by a user will be disconnected immediately unless another user is waiting for a connection from the pool.
LoginDef.AllowedClientDN
This is a variant property that can contain a single string or an array of strings. The DN's can be specific UserDN's or Groups. This is used to specify who is allowed to access a Workspace that is created with the associated LoginName/Password.
LoginDef.MinSize
Specifies the minimum number of Workspaces using this LoginDef that are created when the pool is created.
LoginDef.MinAvail
Specifies the minimum number of Workspaces using this LoginDef that need to be available. Note that MaxPerWorkspacePool will never be exceeded.
LoginDef.LogicalName
This is only used when a pool is created using CreatePoolByLogicalName. It is used to determine which set of LoginDef's in LDAP to use in the Pool.

Using Integration Technologies Pooling

The Pooling takes advantage of the WorkspaceManager being a COM singleton object (which means only a single instance of the WorkspaceManager component will be created any given process.) In other words, every time a call to CoCreateInstance (which is what VB's CreateObject and dim x as New object use) is made in the same process, the same WorkspaceManager object will be returned. This makes the same pools available to all callers in the same process.

All applications that use pooling will follow these general steps:

  1. Create the Pool (use CreatePoolByServer or CreatePoolByLogicalName). This step needs to be only performed once, usually when the application is started. You will get an error if you try to create a pool using a logical name that has already been used in a pool.
  2. Get a PooledWorkspace object from the pool (use GetPooledWorkspace). The PooledWorkspace is really just a wrapper around the SAS.Workspace object that is being pooled. This wrapper is necessary to notify the pooling code when you are done using the pooled workspace. In pooling, you will want to keep a reference to the pooled workspace for as long as you keep a reference to the workspace.
  3. Use the workspace. Run a stored process; get the output from SAS, do whatever you need to do with SAS.
  4. Release the workspace and the PooledWorkspace. In VB, you can release these objects by either letting them go out of scope or by calling
    set obPooledWorkspace = Nothing
  5. The pool will continue to run until either your process exits or you call Shutdown() on each pool. Simply releasing your reference to the WorkspaceManager is not enough.

In an ASP application, there are two ways the pool can be created: in the Application_OnStart callback in the global.asa, or in the code that calls to get the PooledWorkspace. The following code is written in VB; some changes are needed to write it in VBScript.

Once a pool is running, methods and properties are available on the SASWorkspaceManager.WorkspacePool object to look at statistics (how many total workspaces are in the pool, and how many are in use) about the pool, and shutdown the pool.

Here is an example of using Integration Technologies pooling.

Example Scenario

Here's an example of a pool with a single server and two logins, using the Integration Technologies security mechanisms. For this example, assume that you have an application that presents payroll data. You want some users to see all data (those that work in the payroll department); but you want others to be restricted to only seeing the summary data (those that work in the HR department). This is a good example of where the security mechanisms in Integration Technologies pooling can help you out.

The first thing to do is create or determine two user IDs: one that the people in the payroll department will use and one that the people in the HR department will use. For this example, these will be payroll_ID and HR_ID.

The next step is to secure your data on your server. Use file permissions to restrict access of the detailed data to the payroll_ID, and grant access to both payroll_ID and HR_ID to the summary data.

In LDAP, you will need two groups: one for the payroll department (we'll call it payroll_GROUP), and one for the HR department (HR_GROUP). The users in the payroll department should be in the payroll_GROUP, and the users in the HR department should be in the HR_GROUP. Use the IT Administrator to create two sasLogin definitions: one for payroll_ID and one for HR_ID. These will both have a logical name of PayrollViewer. In the payroll_ID login, specify an allowedClientDN of payroll_GROUP. In the HR_ID login, specify an allowedClientDN of HR_GROUP. While IT Administrator is still up, you can specify some pooling parameters. Let's set minSize for both to 1, and MinAvail to 0.

Now, in IT Administrator, configure the Server. This needs to contain all the information needed by the client machine to establish a connection to the server machine. This includes specifying the Protocol (Bridge in this case), the machine(myUnixMachine.MyCompany.com), port(5678), and logicalname (PayrollViewer). We'll configure a MaxPerWorkspacePool of 4, and a RecycleActivationLimit of 100.

The administrative steps are now complete. Now we need some code that makes use of it. We'll assume that the application is an ASP application written to use VB Webclasses (also called IIS Applications). We'll also put the code to create the pool in with the code that uses it; this could also be written in VBScript and put in your Application_OnStart callback.

The following code is called after the web application has collected the LDAP user name and LDAP password of the caller:

   ' Get the pool. If it doesn't exist, create it
   Dim obWorkspaceManager As New SASWorkspaceManager.WorkspaceManager
   Dim obPool As SASWorkspaceManager.WorkspacePool

   On Error Resume Next
   ' Assume the pool already exists
   Set obPool = obWorkspaceManager.WorkspacePools("PayrollViewer")
   On Error GoTo 0
   If (obPool Is Nothing) Then
      ' The pool doesn't exist; create it
      ' Set checkCredentialsOnEachGet to true
      Set obPool = obWorkspaceManager.WorkspacePools.CreatePoolByLogicalName(
         "PayrollViewer", true)
   End If

   ' Now the pool is created, get a Workspace from it:
   Dim obPooledWorkspace As SASWorkspaceManager.PooledWorkspace
   'This assumes that the initial page collects the user's LDAPDN and 
   ' password, and some code has set those in variables.
   set obPooledWorkspace = obPool.GetPooledWorkspace(theGuysLDAPDN,
      theGuysLDAPPassword, 1000)

   Dim obSAS As SAS.Workspace
   Set obSAS = obPooledWorkspace.Workspace

   ' Now use obSAS.  Try to access some data
   Dim obConnection as new ADODB.Connection
   Dim rsSecret as new ADODB.Recordset
   Dim rsPublic as new ADODB.Recordset
   obConnection.Open "provider=SAS.IOMProvider.1; SAS Workspace ID=" &
      obSAS.UniqueIdentifier
   ' Everyone can access the public data
   rsPublic.Open "payroll.public", obConnection, adOpenDynamic,
      adCmdTableDirect

   On Error Resume Next
   obRecordset.Open "payroll.secret", obConnection, adOpenDynamic, 
      adCmdTableDirect
   If Err.Number <> 0 then
      'We couldn't open the sensitive data; we must be dealing with an HR guy
      Response.Write "<p>You must be an HR guy.</p>"
   Else
      Response.Write "<p>" & rsSecret!name & " makes " & rsSecret!salary
      & "</p>"
   End If

   ' Tell everyone the average salary:
   Response.Write "<p>The average salary here is: " & rsPublic!avg & "</p>"
   'When done, release the obPooledWorkspace to return it to the pool.
   Set obPooledWorkspace = Nothing