古詩詞大全網 - 藝術簽名 - Windows集群開發:6)寫資源DLL。

Windows集群開發:6)寫資源DLL。

編寫壹個資源DLL

開始

可以使用MS Visual C++開發系統或其他C/C++開發工具編寫自定義資源DLL。本文中的示例使用了

Microsoft Visual c++ b版包含Unicode MFC庫。

MIDL編譯器版本(MIDL編譯器可以在SDK中找到)

活動模板庫(ATL)版本(由代碼擴展示例和資源類型生成向導生成的代碼需要)

構建編譯環境時,請參考platform SDK,尤其是準備構建環境和開發人員註意事項章節。

完整的資源DLL參考實現也可以在platform SDK示例中找到(參見SMB *** p)。

創建新的資源類型

要創建新的資源類型,您必須編寫壹個資源DLL和壹個群集管理器擴展DLL。簡單的方法是運行資源類型生成向導來創建資源DLL。向導將聲明包含入口點的資源DLL框架和/或導出的群集管理器擴展DLL。

有關創建資源DLL的完整步驟,請參考SDK文檔中的使用資源類型AppWizard創建自定義資源類型和自定義資源DLL部分。

生成的資源DLL框架只包含最基本的故障轉移和恢復功能。要使用集群環境的所有功能並允許DLL提供特定的資源信息,您需要編寫自己的代碼。請註意,向導生成的框架代碼包含TODO和ADDPARAM: comments,以指示需要在何處添加資源的特定信息。如下所述,您需要使用資源API來完成大多數定制功能。

自定義資源DLL

如前所述,資源API包含幾個入口點函數,它們在資源DLL中實現。資源監視器使用這些入口點函數來管理DLL提供的資源,並且資源監視器實現壹些回調函數。資源DLL使用這些回調函數向群集服務報告狀態,或者為系統管理員記錄事件日誌。

大多數入口點函數是所有資源必需的兩個特殊API入口點函數——仲裁和釋放——只有在編寫仲裁資源時才需要。本文不討論這兩個函數。下面列出了其余的入口點函數。本文將討論它們的細節。

群集軟件支持的每個資源DLL都應該遵循以下原則。

在壹種例外情況下,資源DLL對於給定的資源實例是不可重入的,這就是說,終止入口點函數Terminate應該在任何時候被調用,即使資源DLL中的線程處於等待聯機或脫機調用完成的阻塞狀態。

資源DLL對於其他資源id是可重入的。如果資源DLL有多個資源id,它必須同步DLL中的所有全局數據。

入口點函數完成資源DLL中的操作所用的時間不應超過毫秒。如果壹個入口點函數——尤其是Online Offline LooksAlive或is alive——超過了這個限制,就應該產生壹個線程來處理這個耗時的操作(註意,當前向導將為Online的未來版本生成壹個線程,也應該為Offline生成壹個線程)。

在資源DLL的初始化過程中,用DLL_PROCESS_ATTACH標誌調用DLL的入口點函數(系統加載DLL後的標準DLL入口),然後資源監視器開始調用資源API的入口點函數。

啟動程序

當加載資源DLL時,資源監視器調用啟動例程。註意只導出啟動入口點函數,其他所有在資源DLL中實現的入口點函數都是通過啟動返回的函數表來訪問的。

下面是啟動例程dword winapi startup的定義(lpcwstr資源類型dword最小版本支持的dword最大版本支持的pset _ resource _ status _ routine set re)。source status PLOG _事件_例程日誌事件PCLRES _函數_表*函數表);

ResourceType參數標識啟動的資源的類型。

SetResourceStatus和LogEvent是由資源監視器實現的回調函數(這些回調函數將在本文後面的章節中討論)。在調用聯機或脫機入口點函數後,如果它們花費的時間超過毫秒,資源DLL應該調用SetResourceStatus來通知群集資源狀態,並且資源DLL還應該使用logevent。t報告事件和錯誤(SetResourceStatus應僅由Online或Offline調用,並僅在Online或Offline上返回ERROR_IO_PENDING)。

FunctionTable結構包含資源DLL的其余入口點的函數地址。

請註意啟動入口點函數資源DLL保存回調函數LogEvent和SetResourceStatus的唯壹位置。

啟動返回以下值

如果請求成功,則返回ERROR_SUCCESS。

如果資源不支持介於MinVersionSupported和MaxVersionSupported之間的版本,則返回ERROR_REVISION_MISMATCH。

操作不成功返回Win?編程接口的錯誤值

為了優化資源操作,需要確保啟動可以在毫秒內完成。

開放例程

壹旦啟動成功返回,資源監視器通常會為資源DLL管理的每個資源調用Open入口點函數。

Open例程的定義如下:Resid WinAPI Open(LPCWSTR ResourceName HKEY資源Key Resource _ Handle資源句柄);

ResourceName參數標識打開的資源(壹個資源DLL可以提供給定類型的多個資源)。ResourceKey參數是關於資源的特定信息,它是私有屬性,位於集群數據庫中。open返回時鍵值是關閉的,所以如果資源訪問其他入口點函數中的鍵值DLL,它應該調用ClusterRegOpenK。在SetResourceStatus和LogEvent回調函數中使用ey或clusterregcreatekey資源句柄參數。

Open使用集群API打開集群數據庫,並獲取資源參數和私有屬性。很重要的壹點是,資源DLL要在開放入口檢查資源當前是否脫機(壹個資源不能同時在多個節點上聯機)。如果資源當前聯機,DLL應該嘗試使其脫機(註意,在這種情況下,聯機和脫機表示應用程序或服務的狀態。不是給定的群集節點-資源必須真正脫機並且不屬於該節點)。此外,在Open例程中,資源DLL應該為資源創建專用的數據結構。

請註意,如果資源是仲裁資源,則集群API在Open例程中不可用。

Open返回以下值

如果操作成功,則返回資源標識(RESID)。

如果操作不成功並返回NULL,則應調用SetLastError來指示錯誤。

如果Open返回壹個錯誤(返回NULL),那麽資源將是不可管理的,所以Open應該只在非常罕見的情況下返回壹個錯誤(例如,它不能為資源分配內存)。

對於資源的優化,確保實現的打開將在毫秒內完成。

在線程序

當資源打開時,資源監視器調用Online入口點函數使資源聯機。

Online例程定義為dword winapi Online(resid resourceid p handle事件句柄);

ResourceId參數被傳遞給entry函數,它是資源的唯壹標識符(與Open entry函數返回的值相同)。資源DLL可以將EventHandle參數返回給資源監視器,以便異步地通知資源監視器它自己的狀態。如果EventHandle參數不是singal,那麽資源監視器將定期調用資源DLL的LooksAlive入口函數來檢查資源狀態。如果不希望該方法幹擾資源,DLL應該在EventHandle參數中返回壹個有效的句柄。通過返回有效的EventHandle資源DLL,可以通知資源監視器任何狀態更改。

每種資源類型都必須有自己的在線入口功能。需要實現這種不同的實現,因為不同類型的資源有不同的需求。比如聯機連接壹個磁盤和連接壹個普通的應用程序是完全不同的。連接壹個磁盤需要加載壹個磁盤來驗證磁盤簽名,聯機連接壹個應用程序只需要調用CreateProcess。

Online返回以下值

如果操作成功,並且資源現在返回ERROR_SUCCESS online。

如果資源被其他系統獨占,並且其中壹個系統擁有獨占權限,則返回ERROR_RESOURCE_NOT_AVAILABLE。

如果請求正在等待,並且已激活線程來處理請求,則返回ERROR_IO_PENDING。

如果操作不成功,Online返回Win錯誤值。

為了優化資源的運行,確保在線例程的執行能夠在毫秒級完成處理。如果不能,應該立即向資源監視器SetResourceStatus回調函數(該函數的地址保存在啟動入口函數中)返回ERROR_IO_PENDING指示資源狀態。壹旦資源聯機,工作線程應該被掛起或暫停以備將來使用。

如果資源由於任何原因無法聯機,資源DLL應使用LogEvent回調函數來記錄事件日誌,並應調用SetResourceStatus函數SetResourceStatus來指示資源的聯機或脫機狀態。群集資源可以處於下列狀態之壹。

在線-狀態代碼群集資源在線

離線-狀態代碼群集資源離線

失敗-狀態代碼ClusterResourceFailed

正在等待聯機-狀態代碼ClusterResourceOnlinePending

等待脫機-狀態代碼ClusterResourceOfflinePending

關於SetResourceStatus的更多信息,請參考平臺SDK。

如果幾分鐘後資源仍然不在線,資源監視器將調用Terminate entry函數來放棄操作。如果壹個資源需要分鐘以上使用集群API的集群管理器Cluster exe或者其他管理工具,可以通過控制代碼clus CTL _ resource _ SET _ M SET _ M . _ PROPERTIES使用ClusterResourceControl修改PendingTimeout的公共屬性(關於集群控制代碼的公共屬性和私有屬性的更多信息,請參考platform SDK文檔。

LooksAlive和IsAlive例程

壹旦資源聯機,資源監視器將定期檢查資源的狀態。資源監視器使用lookalive和isaive入口函數來完成這個操作。資源監視器使用lookalive進行臨時檢查,使用isaive進行徹底檢查。

Lookalive例程被定義為boolwinapi look alive(resid resourceid);

Isave例程被定義為boolwinapi isave(resid resourceid);

在這兩個例程中,ResourceId參數惟壹地標識所檢查的資源實例。通常,Lookalive用於簡單的檢查(例如,進程是否仍在運行,文件* * *是否仍然存在,等等。),而且資源管理器可以頻繁調用Lookalive。如果不希望資源DLL被它中斷,可以在Online例程中返回壹個有效的EventHandle(如上所述),然後用這個句柄通知資源監視器資源狀態。

IsAlive entry函數計算更詳細的資源狀態,並由資源監視器(無法停止)執行。資源DLL應該對資源進行徹底的檢查,看它是否正常工作。例如,數據庫資源應該檢查數據庫是否可以寫入磁盤,以便對磁盤執行查詢和更新。

LooksAlive返回以下值

如果資源可能在線且可用,則返回TRUE。

如果資源工作不正常,LooksAlive返回FALSE。

IsAlive返回以下值

如果資源聯機且工作正常,則返回TRUE。

如果資源工作不正常,則返回FALSE。

出於優化目的,IsAlive入口函數應該在毫秒內完成。如上所述,應該創建壹個單獨的工作線程來完成對資源的檢查。然後,工作線程將發布狀態,以便IsAlive可以獲取它並將其返回給資源管理器。

註意LooksAlive在任何情況下都不能超過毫秒。在大多數情況下,它不應該超過毫秒。IsAlive稍微長壹點,但即使是異步調用,同壹線程中資源監控器管理的其他資源入口函數也會等待直接IsAlive返回派生線程,無法改善這種情況,所以IsAlive也要在毫秒內完成。

離線程序

到目前為止,入口函數的討論都是關於從核心定制壹個行為良好的資源DLL。下面的入口函數提供了資源的結束和卸載機制。第壹個是離線功能。

離線函數定義為dword winapi Offline(resid resourceid);

ResourceId參數唯壹標識資源。當資源脫機時,資源監視器調用這個入口函數。壹旦脫機,群集客戶端就無法再使用該資源。

Offline返回以下值

如果資源脫機請求成功完成,則返回ERROR_SUCCESS。

如果請求仍在等待,並且已激活線程來處理脫機請求,則返回ERROR_IO_PENDING。

如果操作因其他原因無法完成,應返回Win錯誤代碼。

資源DLL應該優雅地關閉資源,並在毫秒內從門戶返回。如果離線例程的實現超出了這個限制,它應該返回ERROR_IO_PENDING,並產生壹個線程來完成離線請求。該線程應使用SetResourceStatus回調來持續更新資源監視器的資源狀態,直到資源狀態為ClusterResourceOffline。

如果資源沒有在PendingTimeout內正常關閉,或者Offline函數返回壹個Win錯誤代碼,資源監視器將調用Terminate entry函數來強制終止資源。

關閉例程

Close entry函數用於關閉資源,並且只能為壹個資源調用壹次。Close應該用於轉換由Open Offline ResourceControl或ResourceTypeControl入口函數分配的結構。如果要關閉的資源仍然沒有脫機,調用Terminate來強制它脫機。

關閉例程被定義為void winapi Close(resid resourceid);

resource id參數是已關閉資源的唯壹標識符。

Close沒有返回值。

資源DLL應該在毫秒內關閉資源,但是如果超過這個限制,群集服務將以適當的方式處理它。

例行的

Terminate entry函數會立即終止壹個在調用Offline時沒有正常關閉的進程。

終止例程被定義為void winapi termin ate(resid resourceid);

ResourceId是被強制脫機的資源的唯壹標識符。如果資源DLL的線程正在等待資源脫機或正常地使資源脫機,該線程的脫機操作將被放棄,資源將被強制脫機。

Terminate沒有返回值。

ResourceControl和ResourceTypeControl例程

ResourceControl和ResourceTypeControl的入口函數是可選的,但微軟建議實現這兩個函數,以支持群集資源控制代碼管理工具(如cluster manager和Cluster Exe)和支持群集的應用程序使用ClusterResourceControl和ClusterResourceTypeC。控制功能專門與資源通信,例如,這些功能可用於設置屬性(公共和私有)、請求操作等。當管理器或集群感知應用程序調用任何ClusterResourceXXXXControl函數時,資源管理器將分別調用ResourceControl或ResourceTypeControl,並獲得正確的控制代碼。實現這兩個例程的傳入資源DLL將根據控制代碼執行控制請求或設置資源屬性。對於未處理的控制代碼,資源DLL應該向資源監視器返回正確的狀態(ERROR_INVALID_FUNCTION state)。在這種情況下,如果有默認的處理動作,資源監視器將執行它。

ResourceControl例程定義為dword winapi資源控制(resid resourceid dword控制代碼lpvoid in buffer dword in buffer size lpvoid out buffer dword out buffer size lpd word返回的字節數);

ResourceId參數是受影響資源的標識,ControlCode表示要執行的操作的控制代碼。有關該參數的有效值列表,請參考platform SDK的“資源控制代碼”章節。

InBuffer是此操作中使用的傳入數據的緩沖區指針。InBufferSize是它的字節大小。OutBuffer是操作返回的數據的緩沖區指針。OutBufferSize是它的字節大小。註意,如果操作不需要數據或者不返回數據,InBuffer和OutBuffer可以為空。

BytesReturned是OutBuffer中實際數據的字節數。

ResourceControl返回以下值

如果ControlCode指定的操作成功完成,則返回ERROR_SUCCESS(盡管實際返回取決於控制代碼)。

如果資源DLL不支持ControlCode指示的操作,或者請求必須由資源監視器處理,則返回ERROR_INVALID_FUNCTION。

如果操作不成功,將返回Win錯誤代碼。

ResourceTypeControl例程定義為dword winapi資源類型控制(lpcwstr資源類型名稱dword控制代碼lpvoid in buffer dword in buffer size lpvoid)。out buffer DWORD out buffer size lpd word bytes returned);

ResourceTypeName是受操作影響的資源類型的標識,ControlCode是要執行的操作的控制代碼。關於控制代碼參數的有效值列表,請參考platform SDK的資源控制代碼。

InBuffer是此操作中使用的傳入數據的緩沖區指針。InBufferSize是它的字節大小。OutBuffer是操作返回的數據的緩沖區指針。OutBufferSize是它的字節大小。註意,如果操作不需要數據或者不返回數據,InBuffer和OutBuffer可以為空。

BytesReturned是OutBuffer緩沖區中返回的結果數據的實際大小。

ResourceTypeControl返回以下值

如果ControlCode指示的操作成功完成,ResourceTypeControl將返回ERROR_SUCCESS(盡管實際返回值取決於控制代碼)。

如果資源DLL不支持ControlCode指定的操作,或者請求必須由資源監視器處理,則返回ERROR_INVALID_FUNCTION。

Lishi Xinzhi/Article/program/net/201311/13753