/******************************************************************************* Feature API: alarmClockCkptCallback Description : Other API in this file are either completely generic or mostly so, the hot standby feature cannot be generic as the state needs to be conveyed to the application and made "hot" so to speak. Here we are going to have to know internals of the alarm clock structure Arguments In: 1. ClCkptHdlT : ckpt handle 2. SaNameT * ckpt_name being updated 3. ClCkptIOVectorElementT *io_vector containing updated checkpoint data (all sections) 4. ClInt32T number of sections within checkpoint 5. ClPtrT cookie; can be used to keep globals within the task Return Value: ClInt32Teger 0 if success, non zero if failure *******************************************************************************/ static ClRcT alarmClockCkptCallback( ClCkptHdlT ckpt_hdl, SaNameT *ckpt_name, ClCkptIOVectorElementT *io_vector, ClUint32T num_sections, ClPtrT cookie ) { ClRcT ret_code = CL_OK; ClInt32T count; ClInt32T pid = getpid(); ClInt32T data_size = sizeof(acClockT); ClUint32T section_index = 1; /*our section name apparently*/ ClCkptSectionIdT target_section_id; target_section_id.id = (ClUint8T*)§ion_index; target_section_id.idLen = sizeof(section_index); alarmClockLogWrite(CL_LOG_SEV_INFO, "alarmClockCkptCallback(pid=%d): ckpt[%.*s] update received\n", pid, ckpt_name->length, ckpt_name->value); for (count = 0; count < num_sections; count++) { /* * check if the received update is for the section of interest to us, * if it is update the section, */ if ((target_section_id.idLen == io_vector[count].sectionId.idLen) && (memcmp(target_section_id.id, (ClCharT *)io_vector[count].sectionId.id, target_section_id.idLen) == 0)) { if (io_vector[count].dataSize != data_size) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptCallback(pid=%d): received %d bytes; expected %d bytes\n", pid, (ClInt32T)io_vector[count].readSize, (ClInt32T)sizeof(acClockT)); } else { alarmClockLogWrite(CL_LOG_SEV_INFO, "alarmClockCkptCallback(pid=%d): received %d bytes from section %d\n", pid, (ClInt32T)io_vector[count].readSize, section_index); alarmClockCopyHotStandby((acClockT*)io_vector[count].dataBuffer); } break; } } /* * ckpt in sync through hot standby update */ if(!(g_hot_standby & HOT_STANDBY_ACTIVE)) g_hot_standby |= HOT_STANDBY_ACTIVE; return ret_code; }
/******************************************************************************* Feature API: alarmClockCkptCallback Description : Other API in this file are either completely generic or mostly so, the hot standby feature cannot be generic as the state needs to be conveyed to the application and made "hot" so to speak. Here we are going to have to know internals of the alarm clock structure Arguments In: 1. ClCkptHdlT : ckpt handle 2. SaNameT * ckpt_name being updated 3. ClCkptIOVectorElementT *io_vector containing updated checkpoint data (all sections) 4. ClInt32T number of sections within checkpoint 5. ClPtrT cookie; can be used to keep globals within the task Return Value: ClInt32Teger 0 if success, non zero if failure *******************************************************************************/ static ClRcT alarmClockCkptCallback( ClCkptHdlT ckpt_hdl, SaNameT *ckpt_name, ClCkptIOVectorElementT *io_vector, ClUint32T num_sections, ClPtrT cookie ) { ClRcT ret_code = CL_OK; ClInt32T count; ClInt32T pid = getpid(); ClInt32T data_size = sizeof(acClockT); ClInt32T section_id_len; ClCharT section_id_name[ CL_MAX_NAME_LENGTH ]; sprintf(section_id_name, "s00001"); section_id_len = strlen(section_id_name); alarmClockLogWrite(CL_LOG_SEV_INFO, "alarmClockCkptCallback(pid=%d): ckpt[%.*s] update received\n", pid, ckpt_name->length, ckpt_name->value); for (count = 0; count < num_sections; count++) { /* * check if the received update is for the section of interest to us, * if it is update the section, */ if ((section_id_len == io_vector[count].sectionId.idLen) && (strncmp(section_id_name, (ClCharT *)io_vector[count].sectionId.id, section_id_len) == 0)) { if (io_vector[count].dataSize != data_size) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptCallback(pid=%d): received %d bytes; expected %d bytes\n", pid, (ClInt32T)io_vector[count].readSize, (ClInt32T)sizeof(acClockT)); } else { alarmClockLogWrite(CL_LOG_SEV_INFO, "alarmClockCkptCallback(pid=%d): received %d bytes from %s\n", pid, (ClInt32T)io_vector[count].readSize, section_id_name); alarmClockCopyHotStandby((acClockT*)io_vector[count].dataBuffer); } break; } } /* * ckpt in sync through hot standby update */ if(!(g_hot_standby & __HOT_STANDBY_ACTIVE)) g_hot_standby |= __HOT_STANDBY_ACTIVE; return ret_code; }
/******************************************************************************* Feature API: alarmClockCkptCallback Description : Other API in this file are either completely generic or mostly so, the hot standby feature cannot be generic as the state needs to be conveyed to the application and made "hot" so to speak. Here we are going to have to know internals of the alarm clock structure Arguments In: 1. ClCkptHdlT : ckpt handle 2. ClNameT * ckpt_name being updated 3. ClCkptIOVectorElementT *io_vector containing updated checkpoint data (all sections) 4. ClInt32T number of sections within checkpoint 5. ClPtrT cookie; can be used to keep globals within the task Return Value: ClInt32Teger 0 if success, non zero if failure *******************************************************************************/ static ClRcT alarmClockCkptCallback( ClCkptHdlT ckpt_hdl, ClNameT *ckpt_name, ClCkptIOVectorElementT *io_vector, ClUint32T num_sections, ClPtrT cookie ) { ClRcT ret_code = CL_OK; ClInt32T count; ClInt32T pid = getpid(); ClInt32T data_size = sizeof(SessionT); ClCkptSectionIdT *target_section_id; target_section_id = (ClCkptSectionIdT*)§ionIdMap[0].sectionId; alarmClockLogWrite(CL_LOG_SEV_INFO, "alarmClockCkptCallback(pid=%d): ckpt[%.*s] update received\n", pid, ckpt_name->length, ckpt_name->value); /* * Normal case, would be zero-contention on the lock and futex with no contention * would incur no futex_wait or syscall overhead. */ alarmClockCkptLock(); for (count = 0; count < num_sections; count++) { /* * check if the received update is for the section of interest to us, * if it is update the section, */ if ((target_section_id->idLen == io_vector[count].sectionId.idLen) && (memcmp(target_section_id->id, (ClCharT *)io_vector[count].sectionId.id, target_section_id->idLen) == 0)) { if (io_vector[count].dataSize != data_size) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptCallback(pid=%d): received %d bytes; expected %d bytes\n", pid, (ClInt32T)io_vector[count].readSize, (ClInt32T)sizeof(acClockT)); } else { alarmClockLogWrite(CL_LOG_SEV_INFO, "alarmClockCkptCallback(pid=%d): received %d bytes from section %.*s " "for offset [%d]", pid, (ClInt32T)io_vector[count].readSize, target_section_id->idLen, (const char *)target_section_id->id, (ClUint32T)io_vector[count].dataOffset); SessionT *session = (SessionT*)io_vector[count].dataBuffer; ClUint32T offset = (ClUint32T)io_vector[count].dataOffset/data_size; sessionUpdate(session, offset); alarmClockCopyHotStandby(&session->clock); } break; } } /* * ckpt in sync through hot standby update */ if(!(g_hot_standby & HOT_STANDBY_ACTIVE)) g_hot_standby |= HOT_STANDBY_ACTIVE; alarmClockCkptUnlock(); return ret_code; }