windows-nt/Source/XPSP1/NT/base/cluster/service/cp/receive.c

596 lines
14 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
receive.c
Abstract:
APIs for the server-side RPC support for the Checkpoint Manager
Author:
John Vert (jvert) 1/14/1997
Revision History:
--*/
#include "cpp.h"
error_status_t
CppDepositCheckpoint(
handle_t IDL_handle,
LPCWSTR ResourceId,
DWORD dwCheckpointId,
BYTE_PIPE CheckpointData,
BOOLEAN fCryptoCheckpoint
)
/*++
Routine Description:
Server side RPC to allow other nodes to checkpoint data to the
quorum disk.
Arguments:
IDL_handle - RPC binding handle, not used.
ResourceId - Name of the resource whose data is being checkpointed
dwCheckpointId - Unique identifier of the checkpoint
CheckpointData - pipe through which checkpoint data can be retrieved.
fCryptoCheckpoint - Indicates if the checkpoint is a crypto checkpoint
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{
DWORD Status = ERROR_SUCCESS;
LPWSTR FileName = NULL;
LPWSTR DirectoryName = NULL;
BOOL Success;
PFM_RESOURCE Resource;
HANDLE hDirectory = INVALID_HANDLE_VALUE;
ACQUIRE_SHARED_LOCK(gQuoLock);
Resource = OmReferenceObjectById(ObjectTypeResource, ResourceId);
if (Resource == NULL)
{
Status = ERROR_FILE_NOT_FOUND;
goto FnExit;
}
Status = CppGetCheckpointFile(Resource,
dwCheckpointId,
&DirectoryName,
&FileName,
NULL,
fCryptoCheckpoint);
OmDereferenceObject(Resource);
if (Status != ERROR_SUCCESS)
{
ClRtlLogPrint(LOG_CRITICAL,
"[CP] CppDepositCheckpoint - CppGetCheckpointFile failed %1!d!\n",
Status);
goto FnExit;
}
ClRtlLogPrint(LOG_NOISE,
"[CP] CppDepositCheckpoint checkpointing data to file %1!ws!\n",
FileName);
//
// Create the directory.
//
if (!CreateDirectory(DirectoryName, NULL))
{
Status = GetLastError();
if (Status != ERROR_ALREADY_EXISTS)
{
ClRtlLogPrint(LOG_CRITICAL,
"[CP] CppDepositCheckpoint unable to create directory %1!ws!, error %2!d!\n",
DirectoryName,
Status);
goto FnExit;
}
else
{
//the directory exists, set Status to ERROR_SUCCESS
Status = ERROR_SUCCESS;
}
}
else
{
//
// The directory was newly created. Put the appropriate ACL on it
// so that only ADMINs can read it.
//
hDirectory = CreateFile(DirectoryName,
GENERIC_READ | WRITE_DAC | READ_CONTROL,
0,
NULL,
OPEN_ALWAYS,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (hDirectory == INVALID_HANDLE_VALUE)
{
Status = GetLastError();
ClRtlLogPrint(LOG_CRITICAL,
"[CP] CppDepositCheckpoint unable to open directory %1!ws!, error %2!d!\n",
DirectoryName,
Status);
goto FnExit;
}
Status = ClRtlSetObjSecurityInfo(hDirectory,
SE_FILE_OBJECT,
GENERIC_ALL,
GENERIC_ALL,
0);
if (Status != ERROR_SUCCESS)
{
ClRtlLogPrint(LOG_CRITICAL,
"[CP] CppDepositCheckpoint- unable to set ACL on directory %1!ws!, error %2!d!\n",
DirectoryName,
Status);
goto FnExit;
}
}
//
// Pull the checkpoint data file across RPC
//
Status = DmPullFile(FileName, CheckpointData);
if (Status != ERROR_SUCCESS) {
ClRtlLogPrint(LOG_CRITICAL,
"[CP] CppDepositCheckpoint - DmPullFile %1!ws! failed %2!d!\n",
FileName,
Status);
}
FnExit:
RELEASE_LOCK(gQuoLock);
//clean up
if (DirectoryName) LocalFree(DirectoryName);
if (FileName) LocalFree(FileName);
if (hDirectory != INVALID_HANDLE_VALUE)
CloseHandle(hDirectory);
//
// Adjust the return status if the quorum volume is truly offline and that is why this
// call failed.
//
if ( ( Status != ERROR_SUCCESS ) && ( CppIsQuorumVolumeOffline() == TRUE ) ) Status = ERROR_NOT_READY;
//At this point, CppDepositCheckpoint should either
//a) throw the error code as an exception, or
//b) drain the [in] pipe and then return the error code normally
//but if it returns without draining the pipe, and the RPC runtime throws
//the pipe-discipline exception.
if (Status != ERROR_SUCCESS)
RpcRaiseException(Status);
return(Status);
}
error_status_t
s_CpDepositCheckpoint(
handle_t IDL_handle,
LPCWSTR ResourceId,
DWORD dwCheckpointId,
BYTE_PIPE CheckpointData
)
/*++
Routine Description:
Server side RPC to allow other nodes to checkpoint data to the
quorum disk.
Arguments:
IDL_handle - RPC binding handle, not used.
ResourceId - Name of the resource whose data is being checkpointed
dwCheckpointId - Unique identifier of the checkpoint
CheckpointData - pipe through which checkpoint data can be retrieved.
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{
return CppDepositCheckpoint(IDL_handle,
ResourceId,
dwCheckpointId,
CheckpointData,
FALSE
);
}
error_status_t
s_CpDepositCryptoCheckpoint(
handle_t IDL_handle,
LPCWSTR ResourceId,
DWORD dwCheckpointId,
BYTE_PIPE CheckpointData
)
/*++
Routine Description:
Server side RPC to allow other nodes to checkpoint data to the
quorum disk.
Arguments:
IDL_handle - RPC binding handle, not used.
ResourceId - Name of the resource whose data is being checkpointed
dwCheckpointId - Unique identifier of the checkpoint
CheckpointData - pipe through which checkpoint data can be retrieved.
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{
return CppDepositCheckpoint(IDL_handle,
ResourceId,
dwCheckpointId,
CheckpointData,
TRUE
);
}
error_status_t
CppRetrieveCheckpoint(
handle_t IDL_handle,
LPCWSTR ResourceId,
DWORD dwCheckpointId,
BOOLEAN fCryptoCheckpoint,
BYTE_PIPE CheckpointData
)
/*++
Routine Description:
Server side RPC through which data checkpointed to the quorum disk
can be retrieved by other nodes.
Arguments:
IDL_handle - RPC binding handle, not used.
ResourceId - Name of the resource whose checkpoint data is to be retrieved
dwCheckpointId - Unique identifier of the checkpoint
fCryptoCheckpoint - Indicates if the checkpoint is a crypto checkpoint
CheckpointData - pipe through which checkpoint data should be sent
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{
DWORD Status;
LPWSTR FileName=NULL;
HANDLE hFile;
BOOL Success;
PFM_RESOURCE Resource;
ACQUIRE_SHARED_LOCK(gQuoLock);
Resource = OmReferenceObjectById(ObjectTypeResource, ResourceId);
if (Resource == NULL) {
Status = ERROR_FILE_NOT_FOUND;
goto FnExit;
}
Status = CppGetCheckpointFile(Resource,
dwCheckpointId,
NULL,
&FileName,
NULL,
fCryptoCheckpoint);
OmDereferenceObject(Resource);
if (Status != ERROR_SUCCESS) {
ClRtlLogPrint(LOG_CRITICAL,
"[CP] CppRetrieveCheckpoint - CppGetCheckpointFile failed %1!d!\n",
Status);
goto FnExit;
}
ClRtlLogPrint(LOG_NOISE,
"[CP] CppRetrieveCheckpoint retrieving data from file %1!ws!\n",
FileName);
//
// Push the checkpoint data file across RPC
//
Status = DmPushFile(FileName, CheckpointData);
if (Status != ERROR_SUCCESS) {
ClRtlLogPrint(LOG_CRITICAL,
"[CP] CppRetrieveCheckpoint - DmPushFile %1!ws! failed %2!d!\n",
FileName,
Status);
}
FnExit:
RELEASE_LOCK(gQuoLock);
//cleanup
if (FileName) LocalFree(FileName);
//
// Adjust the return status if the quorum volume is truly offline and that is why this
// call failed.
//
if ( ( Status != ERROR_SUCCESS ) && ( CppIsQuorumVolumeOffline() == TRUE ) ) Status = ERROR_NOT_READY;
return(Status);
}
error_status_t
s_CpRetrieveCheckpoint(
handle_t IDL_handle,
LPCWSTR ResourceId,
DWORD dwCheckpointId,
BYTE_PIPE CheckpointData
)
/*++
Routine Description:
Server side RPC through which data checkpointed to the quorum disk
can be retrieved by other nodes.
Arguments:
IDL_handle - RPC binding handle, not used.
ResourceId - Name of the resource whose checkpoint data is to be retrieved
dwCheckpointId - Unique identifier of the checkpoint
CheckpointData - pipe through which checkpoint data should be sent
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{
return CppRetrieveCheckpoint(IDL_handle,
ResourceId,
dwCheckpointId,
FALSE,
CheckpointData
);
}
error_status_t
s_CpRetrieveCryptoCheckpoint(
handle_t IDL_handle,
LPCWSTR ResourceId,
DWORD dwCheckpointId,
BYTE_PIPE CheckpointData
)
/*++
Routine Description:
Server side RPC through which data checkpointed to the quorum disk
can be retrieved by other nodes.
Arguments:
IDL_handle - RPC binding handle, not used.
ResourceId - Name of the resource whose checkpoint data is to be retrieved
dwCheckpointId - Unique identifier of the checkpoint
CheckpointData - pipe through which checkpoint data should be sent
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{
return CppRetrieveCheckpoint(IDL_handle,
ResourceId,
dwCheckpointId,
TRUE,
CheckpointData
);
}
error_status_t
CppDeleteCheckpoint(
handle_t IDL_handle,
LPCWSTR ResourceId,
DWORD dwCheckpointId,
LPCWSTR lpszQuorumPath,
BOOL fCryptoCheckpoint
)
/*++
Routine Description:
Server side RPC through which the checkpoint file corresponding to a
given checkpointid for a resource is deleted.
Arguments:
IDL_handle - RPC binding handle, not used.
ResourceId - Name of the resource whose checkpoint file is to be deleted.
dwCheckpointId - Unique identifier of the checkpoint. If 0, all checkpoints
must be deleted.
lpszQuorumPath - The path to the cluster files from where these files must
be deleted.
fCryptoCheckpoint - Indicates if the checkpoint is a crypto checkpoint
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{
DWORD Status;
PFM_RESOURCE Resource = NULL;
Resource = OmReferenceObjectById(ObjectTypeResource, ResourceId);
if (Resource == NULL) {
Status = ERROR_FILE_NOT_FOUND;
goto FnExit;
}
if (fCryptoCheckpoint) {
Status = CpckDeleteCheckpointFile(Resource, dwCheckpointId, lpszQuorumPath);
} else {
Status = CppDeleteCheckpointFile(Resource, dwCheckpointId, lpszQuorumPath);
}
if (Status != ERROR_SUCCESS)
{
goto FnExit;
}
FnExit:
if (Resource) OmDereferenceObject(Resource);
return(Status);
}
error_status_t
s_CpDeleteCheckpoint(
handle_t IDL_handle,
LPCWSTR ResourceId,
DWORD dwCheckpointId,
LPCWSTR lpszQuorumPath
)
/*++
Routine Description:
Server side RPC through which the checkpoint file corresponding to a
given checkpointid for a resource is deleted.
Arguments:
IDL_handle - RPC binding handle, not used.
ResourceId - Name of the resource whose checkpoint file is to be deleted.
dwCheckpointId - Unique identifier of the checkpoint. If 0, all checkpoints
must be deleted.
lpszQuorumPath - The path to the cluster files from where these files must
be deleted.
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{
return CppDeleteCheckpoint(IDL_handle,
ResourceId,
dwCheckpointId,
lpszQuorumPath,
FALSE);
}
error_status_t
s_CpDeleteCryptoCheckpoint(
handle_t IDL_handle,
LPCWSTR ResourceId,
DWORD dwCheckpointId,
LPCWSTR lpszQuorumPath
)
/*++
Routine Description:
Server side RPC through which the crypto checkpoint file corresponding to a
given checkpointid for a resource is deleted.
Arguments:
IDL_handle - RPC binding handle, not used.
ResourceId - Name of the resource whose checkpoint file is to be deleted.
dwCheckpointId - Unique identifier of the checkpoint. If 0, all checkpoints
must be deleted.
lpszQuorumPath - The path to the cluster files from where these files must
be deleted.
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{
return CppDeleteCheckpoint(IDL_handle,
ResourceId,
dwCheckpointId,
lpszQuorumPath,
TRUE);
}