VERSION 1.0 CLASS BEGIN MultiUse = 0 'False Persistable = 0 'NotPersistable DataBindingBehavior = 0 'vbNone DataSourceBehavior = 0 'vbNone MTSTransactionMode = 0 'NotAnMTSObject END Attribute VB_Name = "Worker" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = True Attribute VB_PredeclaredId = False Attribute VB_Exposed = True Attribute VB_Description = "APE Worker" Option Explicit '------------------------------------------------------------------------- 'The Class is the only public class in this project. See notes in 'modWorker for purpose. ' It implements the IWorker interface. '------------------------------------------------------------------------- Implements APEInterfaces.IWorker '*********************** 'Public Properties '*********************** Public Property Set IWorker_QueueMgrRef(ByVal oQueueMgr As APEInterfaces.IQueueDelegator) Attribute IWorker_QueueMgrRef.VB_Description = "Sets the QueueDelegator object that the Worker uses to receive Service Requests and to return Service Request results to the AEQueueMgr." '------------------------------------------------------------------------- 'Purpose: Called by the the QueueMgr to pass a reference of itself to ' the Worker. 'In: [oQueueMgr] ' A valid reference to a QueueMgr class object 'Effects: [goQueueDelegator] ' Sets the global object variable equal to the passed reference '------------------------------------------------------------------------- Set goQueueDelegator = oQueueMgr End Property Public Property Let IWorker_Log(ByVal bLog As Boolean) Attribute IWorker_Log.VB_Description = "Determines if the Worker logs its events and errors to the AELogger.Logger object." '------------------------------------------------------------------------- 'Purpose: If property is true, the Worker worker generates log records ' for events and passes the records to the logger. 'Effects: [goLogger] '------------------------------------------------------------------------- gbLog = bLog End Property Public Property Get IWorker_Log() As Boolean IWorker_Log = gbLog End Property Public Property Let IWorker_ID(ByVal lID As Long) Attribute IWorker_ID.VB_Description = "Returns or Sets the ID used by the AEQueueMgr or AEPoolMgr to manage this Worker." '------------------------------------------------------------------------- 'Purpose: Called by QueueMgr to give the Worker a unique ID. This ID ' can only be set once. The Worker must have this ID to poll ' the QueueMgr. 'Effects: ' [glWorkerID] ' Is set equal to the passed long, if it has not already happened '------------------------------------------------------------------------- Static stbAlreadySet As Boolean If Not stbAlreadySet Then glWorkerID = lID stbAlreadySet = True End If End Property Public Property Get IWorker_ID() As Long IWorker_ID = glWorkerID End Property Public Property Let IWorker_PersistentServices(ByVal bPersistent As Boolean) Attribute IWorker_PersistentServices.VB_Description = "Determines whether the Worker retains references to service objects that it instantiates or if it releases their references after each use." '------------------------------------------------------------------------- 'Purpose: If true, the worker keeps reference to ' every Service object it has used, else ' worker releases Service object after ' each use. 'Effects: ' [gcServices] ' If property is being changed to false ' then set collection of Service Object ' references to nothing, if it is change ' to true set equal to new collection '------------------------------------------------------------------------- If gbPersistent <> bPersistent Then gbPersistent = bPersistent If Not bPersistent Then Set gcServices = Nothing Else Set gcServices = New Collection End If End If End Property Public Property Get IWorker_PersistentServices() As Boolean IWorker_PersistentServices = gbPersistent End Property Public Property Let IWorker_EarlyBindServices(ByVal bEarlyBind As Boolean) Attribute IWorker_EarlyBindServices.VB_Description = "Specifies whether service objects should be instantiated as APEInterfaces.Service class objects or as Object class objects. If true, all service objects must implement the APEInterfaces.Service interface." '------------------------------------------------------------------------- 'Purpose: If true, the worker uses code that utilizes ' early binding. This option is only ' available for Service objects classes that ' were developed with the worker class, ' because early binding is only available ' if class names are hard coded. 'Effects: ' [gbEarlyBind] is made equal to passed Boolean '------------------------------------------------------------------------- gbEarlyBind = bEarlyBind End Property Public Property Get IWorker_EarlyBindServices() As Boolean IWorker_EarlyBindServices = gbEarlyBind End Property '************************ 'Public Methods '************************ Public Sub IWorker_SetProperties(Optional ByVal bLog As Variant, _ Optional ByVal bEarlyBindServices As Variant, _ Optional ByVal bPersistentServices As Variant, _ Optional ByVal lID As Variant) Attribute IWorker_SetProperties.VB_Description = "Sets Worker properties in one method call." '------------------------------------------------------------------------- 'Purpose: Called by QueueMgr or Client to set properties with one method ' call 'Effects: ' [Properties] ' Log, EarlyBindServices, ID, PersistentServices, UseQueueMgr '------------------------------------------------------------------------- With Me .IWorker_Log = bLog If Not IsMissing(bEarlyBindServices) Then gbEarlyBind = bEarlyBindServices If Not IsMissing(lID) Then .IWorker_ID = lID If Not IsMissing(bPersistentServices) Then .IWorker_PersistentServices = bPersistentServices End With ' If a Service object already exists, initialize it because a new test is starting If Not goLastServiceUsed Is Nothing Then goLastServiceUsed.Initialize gcServiceConfigurations(gsLastLibClassUsed) End If End Sub Public Function IWorker_DoService(ByVal sServiceID As String, ByVal sCommand As String, Optional ByVal vData As Variant) As Variant Attribute IWorker_DoService.VB_Description = "Receives a Service Request, loads the object needed to fulfill the Service Request, and returns the results." '------------------------------------------------------------------------- 'Purpose: This method allows a client to accomplish the same tasks ' accomplished by the return of a task request when the worker calls ' the QueueMgr in PollQueue or CheckService, but uses a synchronous ' process instead of asynchronous. ' This method is intended to be called directly by a client rather than ' the QueueMgr. It is provided for using a Pool Manager system or ' Direct instanciation system ' ' This loads a service object, and may or may not keep it in a collection ' for future use. The service object is called to accomplish the ' requested task and then the return results of the service object ' are returned directly to the calling client 'IN: ' [sServiceID] ' An ID for the requested Service request. It is only useful for ' tracing log records. ' [sCommand] ' ProgID and Method or Task name in the formate of "Library.Class.Method" ' The "Library.Class" is used to load the needed Service object. The ' "Method" string is passed to the Execute method of the service object ' [vData] ' (Optional) Data passed by the client that gets passed to the Service ' object. This data is not manipulated by the Worker at all. 'Return: ' Variant: this value is obtained by calling the service object. It is ' the results of the task accomplished by the service object. It is not ' manipulated by the Worker at all. 'Effects: ' [goEarlyBoundService] ' Set equal to AEService.Service class object if passed ProgID ' equals "AEService.Service" ' [gsLastCommandUsed] ' Set equal to sCommand parameter ' [gsLastLibClassUsed] ' Set equal to the Library.Class in the sCommand Parameter ' [gsLastMethodUsed] ' Set equal to the method portion of the passed sCommand parameter ' [goLastServiceUsed] ' Set equal to the object created using the passed ProgID '------------------------------------------------------------------------- Dim vReturn As Variant Dim bDataPresent As Boolean If Not IsMissing(vData) Then bDataPresent = True Else bDataPresent = False If Not gsLastCommandUsed = sCommand Or goLastServiceUsed Is Nothing Then 'Get the library.class from sCommand 'sCommand is in the format "library.class.method" GetLibClassMethod gsLastLibClassUsed, gsLastMethodUsed, sCommand ' Cache the service configuration options Debug.Assert bDataPresent ' Service configuration options must be specified If (VarType(vData) And vbArray) <> 0 Then CacheServiceConfiguration gsLastLibClassUsed, vData(giRECORD_SERVICE_CONFIGURATION) Else ' If the RPC call is rejected we report a special error message On Error Resume Next CacheServiceConfiguration gsLastLibClassUsed, vData(CStr(giRECORD_SERVICE_CONFIGURATION)) Dim lError As Long lError = IIf(Err.Number = RPC_E_CALL_REJECTED, giRPC_ERROR_ACCESSING_COLLECTION, Err.Number) On Error GoTo 0 If lError <> 0 Then Err.Raise lError End If End If 'Get the Service object Set goLastServiceUsed = GetServiceObject(gsLastLibClassUsed) If gbEarlyBind Then Set goEarlyBoundService = goLastServiceUsed End If gsLastCommandUsed = sCommand End If 'Call the execute method of the class object 'passing the method string and the send data as variant, 'and the return data as variant by reference LogEvent giEXECUTE_BEGIN, sServiceID If gbEarlyBind Then 'Use the Earlybound object reference If bDataPresent Then goEarlyBoundService.Execute sServiceID, gsLastMethodUsed, vData, vReturn Else goEarlyBoundService.Execute sServiceID, gsLastMethodUsed End If Else If bDataPresent Then goLastServiceUsed.Execute sServiceID, gsLastMethodUsed, vData, vReturn Else goLastServiceUsed.Execute sServiceID, gsLastMethodUsed End If End If LogEvent giEXECUTE_END, sServiceID 'Return the data Select Case VarType(vReturn) Case vbNull, vbEmpty IWorker_DoService = Null Case vbObject, vbError, vbDataObject Set IWorker_DoService = vReturn Case Else IWorker_DoService = vReturn End Select End Function Public Sub IWorker_LoadServiceObject(ByVal ServiceLibClass As String, ByVal vServiceConfiguration As Variant) Attribute IWorker_LoadServiceObject.VB_Description = "Loads an object whose ProgID matches ServiceLibClass, if PersistentServices is true." '------------------------------------------------------------------------- 'Purpose: Method is provided to instruct worker to Load an Service ' object without calling the execute method of the Service ' object. 'IN: ' [ServiceLibClass] ' String that contains a ProgID. ServiceLibClass may be in the ' format "library.class.method" or "library.class" 'Effects: ' [goEarlyBoundService] ' Set equal to AEService.Service class object if passed ProgID ' equals "AEService.Service" ' [gsLastCommandUsed] ' Set equal to ServiceLibClass parameter ' [gsLastLibClassUsed] ' Set equal to the Library.Class in the ServiceLibClass Parameter ' [gsLastMethodUsed] ' Set equal to the method portion of the passed ServiceLibClass parameter ' [goLastServiceUsed] ' Set equal to the object created using the passed ProgID '------------------------------------------------------------------------- 'Method is provided to instruct worker to Load an Service 'object without calling the execute method of the Service 'object Dim oService As Object Dim sMethod As String Dim iPos As Integer gsLastCommandUsed = ServiceLibClass 'Get the library.class from ServiceLibClass 'ServiceLibClass may be in the format "library.class.method" 'or "library.class" iPos = InStr(ServiceLibClass, gsCOMMAND_DELIMITER) If iPos = 0 Then Err.Raise giINVALID_COMMAND_PARAMETER, , LoadResString(giINVALID_COMMAND_PARAMETER) iPos = InStr((iPos + 1), ServiceLibClass, gsCOMMAND_DELIMITER) If iPos = 0 Then gsLastLibClassUsed = ServiceLibClass Else gsLastLibClassUsed = Left$(ServiceLibClass, (iPos - 1)) gsLastMethodUsed = Right$(ServiceLibClass, Len(ServiceLibClass) - iPos) End If 'Get the Service object CacheServiceConfiguration gsLastLibClassUsed, vServiceConfiguration Set goLastServiceUsed = GetServiceObject(gsLastLibClassUsed) If gbEarlyBind Then Set goEarlyBoundService = goLastServiceUsed End If End Sub Public Sub IWorker_ShutDown() Attribute IWorker_ShutDown.VB_Description = "Causes Worker to stop processing a Service Requests and destroy its QueueDelegator object." '------------------------------------------------------------------------- 'Purpose: Shut down the Worker. Timer is Killed. Reference to Queue ' Manager is destroyed. 'Effects: ' [gbShutDown] ' Is set to false. '------------------------------------------------------------------------- gbShutDown = True SetEnabled False End Sub Public Function IWorker_GetLogger() As APEInterfaces.ILogger Attribute IWorker_GetLogger.VB_Description = "Returns the AELogger.Logger object instantiated by this Worker." '------------------------------------------------------------------------- 'Purpose: Get the logger object local to this worker 'Return: A valid AELogger.Logger object on the same machine as ' this Worker class object '------------------------------------------------------------------------- Set IWorker_GetLogger = goLogger End Function Public Sub IWorker_StartPollingQueue() Attribute IWorker_StartPollingQueue.VB_Description = "Causes the Worker to start polling the GetServiceRequest method of the QueueDelegator object, if the QueueDelegator object is set." '------------------------------------------------------------------------- 'Purpose: Provided for the QueueMgr to cause the Worker to start ' polling the QueueMgr 'Effects: ' Starts timer so that Worker begins polling Queue '------------------------------------------------------------------------- 'Start timer to pole queuemgr if not processing a service already If (Not gbNewService) And (Not goQueueDelegator Is Nothing) Then SetEnabled True End Sub '********************* 'Private procedures '********************* Private Sub Class_Initialize() On Error GoTo Class_InitializeError '------------------------------------------------------------------------- 'Purpose: Puts Worker in its initial state setting many globals ' to their defaults, if mlInstances = 1 after adding one to it. '------------------------------------------------------------------------- App.OleServerBusyRaiseError = True App.OleServerBusyTimeout = 10000 'Set default property values Set goLogger = CreateObject("AELogger.Logger") gbLog = gbLOG_DEFAULT gbPersistent = gbPERSISTENCE_DEFAULT gbEarlyBind = gbEARLY_BIND_DEFAULT 'Create cServices collection if gbPersistent If gbPersistent Then Set gcServices = New Collection SetInterval giTIMER_INTERVAL Exit Sub Class_InitializeError: LogError Err, gsNULL_SERVICE_ID Resume Next End Sub Private Sub Class_Terminate() '------------------------------------------------------------------------- 'Purpose: Shuts down Worker and destroys objects that it has created, ' if mlInstances = 0 '------------------------------------------------------------------------- On Error GoTo Class_TerminateError SetEnabled False Set goLogger = Nothing Set goLastServiceUsed = Nothing Set goEarlyBoundService = Nothing If gbPersistent Then Set gcServices = Nothing Exit Sub Class_TerminateError: LogError Err, gsNULL_SERVICE_ID Resume Next End Sub