/******************************************************************************* API: alarmClockFinalize Description : Stops the timer driving the clock and delete the timer Arguments In: none Arguments Out: none Return Value: none *******************************************************************************/ void alarmClockFinalize ( void ) { ClRcT rc = CL_OK; /* Stop the clock */ alarmClockStop(); rc = clTimerDelete(timerHandle); if (rc != CL_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockFinalize(pid=%d): Timer delete failed: 0x%x\n", getpid(), rc); } rc = clTimerFinalize(); if (rc != CL_OK) { alarmClockLogWrite(CL_LOG_SEV_CRITICAL, "alarmClockFinalize(pid=%d): Timer finalize failed:0x%x\n", getpid(), rc); return; } }
/******************************************************************************* API: alarmClockStop Description : Stops the clock (i.e the timer that drives the clock) Arguments In: None Arguments Out: none Return Value: none *******************************************************************************/ void alarmClockStop( void ) { ClRcT rc = CL_OK; if (alarmClock.clockRunning == CL_TRUE) { rc = clTimerStop(timerHandle); if (rc != CL_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockStop(pid=%d): Timer stop failed: 0x%x\n", getpid(), rc); } else { alarmClock.clockRunning = CL_FALSE; alarmClockLogWrite(CL_LOG_DEBUG, "alarmClockStop(pid=%d): Clock Stop successful\n", getpid()); } } else { alarmClockLogWrite(CL_LOG_DEBUG, "alarmClockStop(pid=%d): Clock already stopped\n", getpid()); } }
/* * Create the section if it doesn't exist. * Called on becoming active */ SaAisErrorT alarmClockCkptActivate(SaCkptCheckpointHandleT ckptHdl, ClUint32T section_num) { SaAisErrorT rc = SA_AIS_OK; SaCkptSectionIdT *id; if(section_num > NUM_SECTION_ID_MAPS) return SA_AIS_ERR_INVALID_PARAM; id = §ionIdMap[section_num-1].sectionId; rc = clCkptSectionCheck(ckptHdl, (ClCkptSectionIdT*)id); if(rc != CL_OK) { if(CL_GET_ERROR_CODE(rc) == CL_ERR_NOT_EXIST) { rc = alarmClockCkptSectionCreate(ckptHdl, 1); if(rc == SA_AIS_OK) { alarmClockLogWrite(CL_LOG_SEV_INFO, "alarmClockActivate: Section [%.*s] created successfully", id->idLen, (const char *)id->id); } } else rc = SA_AIS_ERR_UNAVAILABLE; /* internal error */ } else rc = SA_AIS_OK; if(rc != SA_AIS_OK) { alarmClockLogWrite(CL_LOG_SEV_INFO, "alarmClockActivate: Section operation on section [%d] " "failed with [%#x]", section_num, rc); } return rc; }
/******************************************************************************* API: alarmClockRaiseAlarm Description : Does the prescribed behavior on reaching an alarm state; i.e. raise an alarm or kill the process Arguments In: None Arguments Out: none Return Value: none *******************************************************************************/ void alarmClockRaiseAlarm ( void ) { if (alarmClock.alarm.reaction == ALARM_REACTION_KILL) { alarmClockLogWrite(CL_LOG_SEV_NOTICE, "alarmClockRaiseAlarm(pid=%d): killing the clock\n", getpid()); /* kill the process running the clock * to force a failover */ exit(alarmClock.clockId); } else if (alarmClock.alarm.reaction == ALARM_REACTION_TRAP) { alarmClockLogWrite(CL_LOG_SEV_NOTICE, "alarmClockRaiseAlarm(pid=%d): raising an alarm not supported yet\n", getpid()); } else { alarmClockLogWrite(CL_LOG_SEV_NOTICE, "alarmClockRaiseAlarm(pid=%d): reaction value not set; not raising alarm\n", getpid()); } }
/******************************************************************************* Feature API: alarmClockCkptRead Description : This API will not attempt to validate arguments, the thinking being that this is a volitional act by the invoker of this API to ensure that invalid parameters can be handled gracefully by the subsystem Arguments In: 1. ClCkptHdlT : ckpt handle 2. section number 3. data to read 4. size of data to read Return Value: ClInt32Teger 0 if success, non zero if failure *******************************************************************************/ ClRcT alarmClockCkptRead ( ClCkptHdlT ckpt_hdl, ClInt32T section_num, void* data, ClInt32T data_size ) { ClRcT ret_code = CL_OK; ClUint32T error_index; ClCharT section_id_name[ CL_MAX_NAME_LENGTH ]; ClCkptIOVectorElementT io_vector; /* * Check if its in sync through hot standby update before reading */ if((g_hot_standby & __HOT_STANDBY_ACTIVE)) return CL_ERR_NO_OP; sprintf(section_id_name, "s%05d", section_num); io_vector.sectionId.id = (ClUint8T*)section_id_name; io_vector.sectionId.idLen = strlen(section_id_name); /* assign other fields of the IoVector */ io_vector.dataBuffer = data; io_vector.dataSize = data_size; io_vector.dataOffset = 0; io_vector.readSize = 0; ret_code = clCkptCheckpointRead(ckpt_hdl, &io_vector, 1, &error_index ); if (ret_code != CL_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptRead(pid=%d): (error_index=%d) " "Failed to read section [%s]: 0x%x\n", getpid(), error_index, section_id_name, ret_code); return ret_code; } else { if ( io_vector.readSize != data_size ) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptRead(pid=%d): read %d bytes; expected %d bytes\n", getpid(), (ClInt32T)io_vector.readSize, data_size); } else { alarmClockLogWrite(CL_LOG_SEV_DEBUG, "alarmClockCkptRead(pid=%d): read %d bytes from %s\n", getpid(), data_size, section_id_name); } } 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); 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: alarmClockCkptRead Description : This API will not attempt to validate arguments, the thinking being that this is a volitional act by the invoker of this API to ensure that invalid parameters can be handled gracefully by the subsystem Arguments In: 1. ClCkptHdlT : ckpt handle 2. section number 3. data to read 4. size of data to read *******************************************************************************/ SaAisErrorT alarmClockCkptRead ( SaCkptCheckpointHandleT ckpt_hdl, SaUint32T section_num, void* data, SaUint32T data_size ) { SaAisErrorT ret_code = SA_AIS_OK; SaUint32T error_index; SaCkptIOVectorElementT io_vector; /* * If we are in sync via the hot-standby, no need to read */ if((g_hot_standby & HOT_STANDBY_ACTIVE)) return SA_AIS_ERR_NO_OP; io_vector.sectionId.id = (SaUint8T*)§ion_num; io_vector.sectionId.idLen = sizeof(section_num); /* assign other fields of the IoVector */ io_vector.dataBuffer = data; io_vector.dataSize = data_size; io_vector.dataOffset = 0; io_vector.readSize = 0; ret_code = saCkptCheckpointRead(ckpt_hdl, &io_vector, 1, &error_index ); if (ret_code != SA_AIS_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptRead: (error_index=%d) Failed to read: 0x%x\n", error_index, ret_code); goto finalizeRet; } else { if ( io_vector.readSize != data_size ) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptRead(pid=%d): read %d bytes; expected %d bytes\n", getpid(), (ClInt32T)io_vector.readSize, data_size); } else { alarmClockLogWrite(CL_LOG_SEV_DEBUG, "alarmClockCkptRead(pid=%d): read %d bytes from section:%d\n", getpid(), data_size, section_num); } } finalizeRet: return ret_code; }
/******************************************************************************* API: alarmClockInitialze Description : Set the alarm clock to all zeroes, and the boolean variable to indicate non-running clock Arguments In: none Arguments Out: none Return Value: none *******************************************************************************/ ClRcT alarmClockInitialize ( void ) { ClRcT rc = CL_OK; ClTimerTimeOutT timeOut; alarmClock.clockTime.hour = 0; alarmClock.clockTime.minute = 0; alarmClock.clockTime.second = 0; alarmClock.alarm.time.hour = 0; alarmClock.alarm.time.minute = 0; alarmClock.alarm.time.second = 0; alarmClock.alarm.reaction = ALARM_REACTION_NONE; alarmClock.clockId = 0;; alarmClock.clockRunning = CL_FALSE; alarmClock.alarmSet = CL_FALSE; /* one second in the clock is 50 millisecond of real time * as an enhancement this can be made provisionable as well */ timeOut.tsSec = 1; timeOut.tsMilliSec = 0; /* rc = clTimerInitialize(NULL); if (rc != CL_OK) { alarmClockLogWrite(CL_LOG_SEV_CRITICAL, "alarmClockInitialize(pid=%d): Timer initialize failed:0x%x\n", getpid(), rc); return rc; } */ rc = clTimerCreate(timeOut, CL_TIMER_REPETITIVE, CL_TIMER_SEPARATE_CONTEXT, (ClTimerCallBackT)&alarmClockAdvance, NULL, &timerHandle); if (rc != CL_OK) { alarmClockLogWrite(CL_LOG_SEV_CRITICAL, "alarmClockInitialize(pid=%d): Timer start failed: 0x%x\n", getpid(), rc); } alarmClockLogWrite(CL_LOG_DEBUG, "alarmClockInitialize(pid=%d): Clock Initialize successful\n", getpid()); return rc; }
/******************************************************************************* Feature API: alarmClockCkptWrite Description : This API will not attempt to validate arguments, the thinking being that this is a volitional act by the invoker of this API to ensure that invalid parameters can be handled gracefully by the subsystem Arguments In: 1. ClCkptHdlT : ckpt handle 2. section number 3. data to write 4. size of data to write *******************************************************************************/ SaAisErrorT alarmClockCkptWrite ( SaCkptCheckpointHandleT ckpt_hdl, SaUint32T section_num, void* data, SaUint32T data_size ) { SaAisErrorT ret_code = SA_AIS_OK; SaCkptSectionIdT *section_id = NULL; SaCkptSectionIdT *ctrl_section_id = NULL; SaCkptIOVectorElementT *ioVecIter = ioVecs; ClUint32T errVecIndex = 0; if(section_num > NUM_SECTION_ID_MAPS || (data_size != sizeof(acClockT))) return SA_AIS_ERR_INVALID_PARAM; data_size = sizeof(SessionT); section_id = §ionIdMap[section_num-1].sectionId; ctrl_section_id = §ionIdMap[section_num-1].ctrlSectionId; memset(ioVecs, 0, sizeof(*ioVecs) * MAX_NUM_IOVECS); SessionCtrlT *sessionCtrl = sessionAddCkpt((acClockT*)data, &ioVecIter, ctrl_section_id); CL_ASSERT(sessionCtrl != NULL); memcpy(&ioVecIter->sectionId, section_id, sizeof(ioVecIter->sectionId)); ioVecIter->dataOffset = sessionCtrl->offset * data_size; ioVecIter->dataBuffer = &sessionCtrl->session; ioVecIter->readSize = ioVecIter->dataSize = sizeof(sessionCtrl->session); ++ioVecIter; ret_code = saCkptCheckpointWrite(ckpt_hdl, ioVecs, (ClUint32T)(ioVecIter - ioVecs), &errVecIndex); if (ret_code != SA_AIS_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptWrite(hdl=%llx): Failed to write: 0x%x " "for session [%d] at offset [%d]. Error iovec index [%d]\n", ckpt_hdl, ret_code, sessionCtrl->session.id, sessionCtrl->offset, errVecIndex); } else { alarmClockLogWrite(CL_LOG_SEV_DEBUG, "alarmClockCkptWrite: wrote %d bytes to section: %.*s, " "iovecs [%d] for session [%d] at offset [%d]", data_size, section_id->idLen, (char*)section_id->id, (ClUint32T)(ioVecIter - ioVecs), sessionCtrl->session.id, sessionCtrl->offset); } return ret_code; }
SaAisErrorT alarmClockCkptSessionDelete(SaCkptCheckpointHandleT ckpt_hdl, ClUint32T section_num, ClUint32T id) { SaCkptIOVectorElementT *ioVecIter = ioVecs; SessionCtrlT ctrl; SaCkptSectionIdT *ctrl_section_id; SaCkptSectionIdT *section_id; SaUint32T errVecIndex = 0; SaAisErrorT rc = SA_AIS_OK; if(section_num > NUM_SECTION_ID_MAPS) return SA_AIS_ERR_INVALID_PARAM; ctrl_section_id = §ionIdMap[section_num-1].ctrlSectionId; section_id = §ionIdMap[section_num-1].sectionId; memset(ioVecs, 0, sizeof(*ioVecs) * MAX_NUM_IOVECS); rc = sessionDelCkpt(id, &ctrl, &ioVecIter, ctrl_section_id); if(rc != CL_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptSessionDelete: " "Session id [%d] delete failed with [%#x]", id, rc); rc = SA_AIS_ERR_NOT_EXIST; goto out; } /* * Write a delete entry by marking the session as deleted */ memcpy(&ioVecIter->sectionId, section_id, sizeof(ioVecIter->sectionId)); ioVecIter->dataOffset = ctrl.offset * sizeof(SessionT); ioVecIter->dataBuffer = &ctrl.session; ioVecIter->readSize = ioVecIter->dataSize = sizeof(ctrl.session); ++ioVecIter; rc = saCkptCheckpointWrite(ckpt_hdl, ioVecs, (ClUint32T)(ioVecIter - ioVecs), &errVecIndex); if(rc != SA_AIS_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptSessionDelete: " "Session delete for id [%d] at offset [%d] failed with ckpt error [%#x]", id, ctrl.offset, rc); goto out; } alarmClockLogWrite(CL_LOG_SEV_DEBUG, "alarmClockCkptSessionDelete: " "Session delete success for id [%d] at offset [%d]", id, ctrl.offset); out: return rc; }
/******************************************************************************* Feature API: alarmClockCkptRead Description : This API will not attempt to validate arguments, the thinking being that this is a volitional act by the invoker of this API to ensure that invalid parameters can be handled gracefully by the subsystem Arguments In: 1. ClCkptHdlT : ckpt handle 2. section number 3. data to read 4. size of data to read *******************************************************************************/ static void bitmapWalkCallback(BitmapT *bitmap, ClUint32T bit, void *arg) { SaCkptIOVectorElementT *ioVec = arg; alarmClockLogWrite(CL_LOG_SEV_DEBUG, "alarmClockCkptRead(%d): Bit set at offset [%u]", getpid(), bit); if(!ioVec) return; SessionT *session = (SessionT*)ioVec->dataBuffer + bit; ClUint32T readSize = (ClUint32T)ioVec->readSize; if( (bit * sizeof(SessionT)) >= readSize) { alarmClockLogWrite(CL_LOG_SEV_WARNING, "alarmClockCkptRead(%d): Bit [%d] " "exceeds session size [%d]", getpid(), bit, readSize); return; } sessionUpdate(session, bit); }
/******************************************************************************* API: alarmClockHotStandbyCopy Description : Copy the clock data structure; except for clock running status which on the standby should be "stopped" Arguments In: acClockT Arguments Out: none Return Value: ClRcT *******************************************************************************/ void alarmClockCopyHotStandby ( acClockT *backup ) { if(sessionBufferMode()) { memcpy(&alarmClock, backup, sizeof(acClockT)); return; } if (alarmClock.clockRunning == CL_TRUE) { alarmClockLogWrite(CL_LOG_SEV_CRITICAL, "alarmClockHotStandbyCopy(pid=%d): clock running; will be stopped\n", getpid()); /* stop the clock if it is running */ alarmClockStop(); } /* copy the clock struct */ memcpy( &alarmClock, backup, sizeof(acClockT)); /* set value of clockRunning to false as it has been stopped */ alarmClock.clockRunning = CL_FALSE; }
/******************************************************************************* Feature API: alarmClockCkptWrite Description : This API will not attempt to validate arguments, the thinking being that this is a volitional act by the invoker of this API to ensure that invalid parameters can be handled gracefully by the subsystem Arguments In: 1. ClCkptHdlT : ckpt handle 2. section number 3. data to write 4. size of data to write Return Value: ClInt32Teger 0 if success, non zero if failure *******************************************************************************/ ClRcT alarmClockCkptWrite ( ClCkptHdlT ckpt_hdl, ClInt32T section_num, void* data, ClInt32T data_size ) { ClRcT ret_code = CL_OK; ClInt32T pid = getpid(); ClCharT section_id_name[ CL_MAX_NAME_LENGTH ]; ClCkptSectionIdT section_id; sprintf(section_id_name, "s%05d", section_num); section_id.id = (ClUint8T*)section_id_name; section_id.idLen = strlen(section_id_name); ret_code = clCkptSectionOverwrite(ckpt_hdl, §ion_id, data, data_size); if (ret_code != CL_OK) { if(CL_GET_ERROR_CODE(ret_code) == 0xa || CL_GET_ERROR_CODE(ret_code) == CL_ERR_NOT_EXIST) { ClCkptSectionCreationAttributesT section_cr_attr; section_cr_attr.sectionId = §ion_id; section_cr_attr.expirationTime = (ClTimeT)CL_TIME_END; ret_code = clCkptSectionCreate(ckpt_hdl, §ion_cr_attr, data, data_size); } } if(ret_code != CL_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptWrite(pid=%d): Failed to write: 0x%x\n", pid, ret_code); } else { alarmClockLogWrite(CL_LOG_SEV_DEBUG, "alarmClockCkptWrite(pid=%d): wrote %d bytes to %s\n", pid, data_size, section_id_name); } return ret_code; }
/******************************************************************************* Feature API: alarmClockCkptWrite Description : This API will not attempt to validate arguments, the thinking being that this is a volitional act by the invoker of this API to ensure that invalid parameters can be handled gracefully by the subsystem Arguments In: 1. ClCkptHdlT : ckpt handle 2. section number 3. data to write 4. size of data to write *******************************************************************************/ SaAisErrorT alarmClockCkptWrite ( SaCkptCheckpointHandleT ckpt_hdl, SaUint32T section_num, void* data, SaUint32T data_size ) { SaAisErrorT ret_code = SA_AIS_OK; SaCkptSectionIdT section_id; section_id.id = (SaUint8T*)§ion_num; section_id.idLen = sizeof(section_num); ret_code = saCkptSectionOverwrite(ckpt_hdl, §ion_id, data, data_size); if (ret_code != SA_AIS_OK) { /* If the overwrite failed because the section did not exist then try to create the section */ if ((ret_code == 0x1000a) || (ret_code == SA_AIS_ERR_NOT_EXIST)) { SaCkptSectionCreationAttributesT section_cr_attr; /* Expiration time for section can also be varied * once parameters are read from a configuration file */ section_cr_attr.expirationTime = SA_TIME_END; section_cr_attr.sectionId = §ion_id; ret_code = saCkptSectionCreate(ckpt_hdl,§ion_cr_attr,data, data_size); } } if (ret_code != SA_AIS_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptWrite(hdl=%llx): Failed to write: 0x%x\n", ckpt_hdl, ret_code); } else { alarmClockLogWrite(CL_LOG_SEV_DEBUG, "alarmClockCkptWrite: wrote %d bytes to section: %d\n", data_size, section_num); } return ret_code; }
SaAisErrorT alarmClockCkptActivate(SaCkptCheckpointHandleT ckptHdl, ClUint32T section_num) { SaAisErrorT rc = SA_AIS_OK; SaCkptSectionIdT id; id.idLen = sizeof(section_num); id.id = (ClUint8T*)§ion_num; rc = saCkptActiveReplicaSet(ckptHdl); if(rc != SA_AIS_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockReplicaSet: returned [%#x]", rc); return rc; } rc = clCkptSectionCheck(ckptHdl, (ClCkptSectionIdT*)&id); if(rc != CL_OK) { if(CL_GET_ERROR_CODE(rc) == CL_ERR_NOT_EXIST) { SaCkptSectionCreationAttributesT attr; attr.sectionId = &id; attr.expirationTime = (ClTimeT)CL_TIME_END; rc = saCkptSectionCreate(ckptHdl, &attr, NULL, 0); if(rc == SA_AIS_OK) { alarmClockLogWrite(CL_LOG_SEV_INFO, "alarmClockActivate: Section [%d] created successfully", section_num); } } else rc = SA_AIS_ERR_UNAVAILABLE; /* internal error */ } else rc = SA_AIS_OK; if(rc != SA_AIS_OK) { alarmClockLogWrite(CL_LOG_SEV_INFO, "alarmClockActivate: Section operation on section [%d] " "failed with [%#x]", section_num, rc); } return rc; }
ClRcT alarmClockCkptActivate(ClCkptHdlT ckptHdl, ClUint32T numSections) { ClRcT rc = CL_OK; ClCkptSectionIdT id; ClCharT section_name[CL_MAX_NAME_LENGTH]; snprintf(section_name, sizeof(section_name), "s%05d", numSections); id.idLen = strlen(section_name); id.id = (ClUint8T*)section_name; rc = clCkptActiveReplicaSet(ckptHdl); if(rc != CL_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockReplicaSet: returned [%#x]", rc); return rc; } rc = clCkptSectionCheck(ckptHdl, &id); if(CL_GET_ERROR_CODE(rc) == CL_ERR_NOT_EXIST) { ClCkptSectionCreationAttributesT attr; attr.sectionId = &id; attr.expirationTime = (ClTimeT)CL_TIME_END; rc = clCkptSectionCreate(ckptHdl, &attr, NULL, 0); if(rc == CL_OK) { alarmClockLogWrite(CL_LOG_SEV_INFO, "alarmClockActivate: Section [%s] created successfully", section_name); } } if(rc != CL_OK) { alarmClockLogWrite(CL_LOG_SEV_INFO, "alarmClockActivate: Section operation on [%s] " "failed with [%#x]", section_name, rc); } return rc; }
/* * Register checkpoint for immediate consumption, all components that * register using this API for a checkpoint will be notified through * the callback function provided when a checkpoint update occurs * All components except the one that actually updates the checkpoint. */ SaAisErrorT alarmClockCkptHotStandbyRegister(SaCkptCheckpointHandleT ckpt_hdl) { ClRcT ret_code = CL_OK; /* When the standby becomes Active it checks this flag to see whether * it needs to perform a checkpoint read or not. If TRUE then the * assumption is that the checkpoint updates on standby have happened * via the callback */ g_hot_standby = HOT_STANDBY_IDLE; ret_code = clCkptImmediateConsumptionRegister(ckpt_hdl, alarmClockCkptCallback, NULL); if (ret_code != CL_OK) { alarmClockLogWrite( CL_LOG_SEV_ERROR, "alarmClockCkptCreate(pid=%d): Failed to register ckpt callback rc[0x%x]\n", getpid(), ret_code); alarmClockLogWrite(CL_LOG_SEV_WARNING, "alarmClockCkptCreate(pid=%d): Falling back to warm standby mode\n", getpid()); return SA_AIS_ERR_BAD_OPERATION; } alarmClockLogWrite(CL_LOG_SEV_DEBUG, "alarmClockCkptCreate: Successfully registered for callbacks"); return SA_AIS_OK; }
/******************************************************************************* Feature API: alarmClockCkptInitialize *******************************************************************************/ SaAisErrorT alarmClockCkptInitialize (void) { SaAisErrorT ret_code = SA_AIS_OK; if (ckpt_svc_hdl == 0) { ret_code = saCkptInitialize(&ckpt_svc_hdl, NULL, &ckpt_version); if (ret_code != SA_AIS_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptInitialize(pid=%d): Failed %x\n", getpid(), ret_code); } } return ret_code; }
/******************************************************************************* Feature API: alarmClockCkptInitialize *******************************************************************************/ ClRcT alarmClockCkptInitialize (void) { ClRcT ret_code = CL_OK; if (ckpt_svc_hdl == 0) { ret_code = clCkptInitialize(&ckpt_svc_hdl, NULL, &ckpt_version); if (ret_code != CL_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptInitialize(pid=%d): Failed %x\n", getpid(), ret_code); } } return ret_code; }
/******************************************************************************* Feature API: alarmClockCkptFinalize *******************************************************************************/ ClRcT alarmClockCkptFinalize (void) { ClRcT ret_code = CL_OK; if (ckpt_svc_hdl != 0) { ret_code = clCkptFinalize(ckpt_svc_hdl); if (ret_code != CL_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptFinalize(pid=%d): Failed %x\n", getpid(), ret_code); } else { ckpt_svc_hdl = 0; } } return ret_code; }
/******************************************************************************* Feature API: alarmClockCkptFinalize *******************************************************************************/ SaAisErrorT alarmClockCkptFinalize (void) { SaAisErrorT ret_code = SA_AIS_OK; if (ckpt_svc_hdl != 0) { ret_code = saCkptFinalize(ckpt_svc_hdl); if (ret_code != SA_AIS_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptFinalize(pid=%d): Failed %x\n", getpid(), ret_code); } else { ckpt_svc_hdl = 0; } } return ret_code; }
/******************************************************************************* Feature API: alarmClockCkptInitialize *******************************************************************************/ SaAisErrorT alarmClockCkptInitialize (void) { SaAisErrorT ret_code = SA_AIS_OK; if (ckpt_svc_hdl == 0) { ret_code = saCkptInitialize(&ckpt_svc_hdl, NULL, &ckpt_version); if (ret_code != SA_AIS_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptInitialize(pid=%d): Failed %x\n", getpid(), ret_code); } } sessionInit(); ClRcT rc = clOsalMutexInit(&alarmClockCkptMutex); CL_ASSERT(rc == CL_OK); ioVecs = clHeapCalloc(MAX_NUM_IOVECS, sizeof(*ioVecs)); CL_ASSERT(ioVecs != NULL); return ret_code; }
/******************************************************************************* Feature API: alarmClockCkptCreate Description : Create a checkpoint given a name and the number of sections. In addition the nature of the checkpoint needs to be specified, synchronous versus asynchronous. If asynchronous collocated versus non collocated. Arguments In: 1. Checkpoint Name 2. Number of Sections 3. Size of section *******************************************************************************/ SaAisErrorT alarmClockCkptCreate ( const SaStringT ckpt_name, SaUint32T num_sections, SaSizeT section_size, SaCkptCheckpointHandleT *ckpt_hdl ) { SaAisErrorT ret_code = SA_AIS_OK; SaNameT ckpt_name_t; SaCkptCheckpointCreationAttributesT ckpt_cr_attr; SaCkptCheckpointOpenFlagsT ckpt_open_flags; SaTimeT timeout; /* Initiailze name struct for ckpt */ ckpt_name_t.length = strlen(ckpt_name); strcpy( ( SaStringT )ckpt_name_t.value,ckpt_name); /* Initialize check point creation flags */ ckpt_cr_attr.creationFlags = CL_CKPT_DISTRIBUTED | CL_CKPT_PEER_TO_PEER_REPLICA; /* Maximum checkpoint size = size of all checkpoints combined */ ckpt_cr_attr.checkpointSize = 0; /* Retention time: forever */ ckpt_cr_attr.retentionDuration = (SaTimeT)-1; if ( num_sections == 1 ) { /* use a named section instead of the default section */ ckpt_cr_attr.maxSections = num_sections + 1; } else { ckpt_cr_attr.maxSections = num_sections; } ckpt_cr_attr.maxSectionSize = 0; ckpt_cr_attr.maxSectionIdSize = 256; /* forever */ timeout = (SaTimeT)-1; /* Initialize the checkpoint open flags */ ckpt_open_flags = (SA_CKPT_CHECKPOINT_READ | SA_CKPT_CHECKPOINT_WRITE | SA_CKPT_CHECKPOINT_CREATE); /* forever */ timeout = (SaTimeT)-1; ret_code = saCkptCheckpointOpen(ckpt_svc_hdl, &ckpt_name_t, &ckpt_cr_attr, ckpt_open_flags, timeout, ckpt_hdl); if ((ret_code != SA_AIS_OK)||(*ckpt_hdl == 0)) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptCreate: Failed to create ckpt:0x%x\n", ret_code); return ret_code; } alarmClockLogWrite(CL_LOG_SEV_DEBUG, "alarmClockCkptCreate: Successful creation ckpt [%llx]\n", *ckpt_hdl); return SA_AIS_OK; }
ClRcT alarmClockAdvance ( void ) { ClBoolT raiseAlarm = CL_FALSE; ClInt32T pid = getpid(); /* advance the clock by a second */ if (++alarmClock.clockTime.second >= 60) { alarmClock.clockTime.second = 0; if (++alarmClock.clockTime.minute >= 60) { alarmClock.clockTime.minute = 0; if (++alarmClock.clockTime.hour >= 24) { alarmClock.clockTime.hour = 0; } } } /* Turn the alarm off if it is due to go off; or else the standby * will also set the alarm off; */ if ((alarmClock.alarmSet == CL_TRUE) && (alarmClock.alarm.time.hour == alarmClock.clockTime.hour) && (alarmClock.alarm.time.minute == alarmClock.clockTime.minute)) { alarmClock.alarmSet = CL_FALSE; raiseAlarm = CL_TRUE; } /* * Checkpoint every 2 seconds */ if (! (alarmClock.clockTime.second & 1) ) { alarmClockCkptLock(); alarmClockCkptWrite(alarmClockCkptHdl, 1, &alarmClock, sizeof(acClockT)); alarmClockCkptUnlock(); } /* Log */ alarmClockLogWrite(CL_LOG_SEV_INFO, "alarm clock (pid=%d): time is %dh:%dm:%ds\n", pid, alarmClock.clockTime.hour, alarmClock.clockTime.minute, alarmClock.clockTime.second); if (raiseAlarm == CL_TRUE) { /* raising an alarm can have two consequences * calling the API to raise the alarm * or killing the process that has triggered * the alarm */ alarmClockRaiseAlarm(); } return CL_OK; }
/******************************************************************************* Feature API: alarmClockCkptCreate Description : Create a checkpoint given a name and the number of sections. In addition the nature of the checkpoint needs to be specified, synchronous versus asynchronous. If asynchronous collocated versus non collocated. Arguments In: 1. Checkpoint Name 2. Number of Sections 3. Size of section *******************************************************************************/ SaAisErrorT alarmClockCkptCreate ( const SaStringT ckpt_name, SaUint32T num_sections, SaSizeT section_size, SaCkptCheckpointHandleT *ckpt_hdl ) { SaAisErrorT ret_code = SA_AIS_OK; SaNameT ckpt_name_t; SaCkptCheckpointCreationAttributesT ckpt_cr_attr; SaCkptCheckpointOpenFlagsT ckpt_open_flags; SaTimeT timeout; /* Initiailze name struct for ckpt */ ckpt_name_t.length = strlen(ckpt_name); strcpy( ( SaStringT )ckpt_name_t.value,ckpt_name); /* Initialize check point creation flags */ ckpt_cr_attr.creationFlags = SA_CKPT_CHECKPOINT_COLLOCATED | CL_CKPT_DISTRIBUTED; /* Maximum checkpoint size = size of all checkpoints combined */ ckpt_cr_attr.checkpointSize = num_sections * section_size; /* Retention time: forever */ ckpt_cr_attr.retentionDuration = (SaTimeT)-1; if ( num_sections == 1 ) { /* use a named section instead of the default section */ ckpt_cr_attr.maxSections = num_sections + 1; } else { ckpt_cr_attr.maxSections = num_sections; } ckpt_cr_attr.maxSectionSize = section_size; ckpt_cr_attr.maxSectionIdSize = sizeof(SaUint32T); /* forever */ timeout = (SaTimeT)-1; /* Initialize the checkpoint open flags */ ckpt_open_flags = (SA_CKPT_CHECKPOINT_READ | SA_CKPT_CHECKPOINT_WRITE | SA_CKPT_CHECKPOINT_CREATE); /* forever */ timeout = (SaTimeT)-1; ret_code = saCkptCheckpointOpen(ckpt_svc_hdl, &ckpt_name_t, &ckpt_cr_attr, ckpt_open_flags, timeout, ckpt_hdl); if ((ret_code != SA_AIS_OK)||(*ckpt_hdl == 0)) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptCreate: Failed to create ckpt:0x%x\n", ret_code); return ret_code; } if (1) // *ckpt_hot_standby == CL_TRUE) { /* * Register checkpoint for immediate consumption, all components that * register using this API for a checkpoint will be notified through * the callback function provided when a checkpoint update occurs * All components except the one that actually updates the checkpoint. */ /* When the standby becomes Active it checks this flag to see whether * it needs to perform a checkpoint read or not. If TRUE then the * assumption is that the checkpoint updates on standby have happened * via the callback */ g_hot_standby = HOT_STANDBY_IDLE; ret_code = clCkptImmediateConsumptionRegister(*ckpt_hdl, alarmClockCkptCallback, NULL); if (ret_code != CL_OK) { alarmClockLogWrite( CL_LOG_SEV_ERROR, "alarmClockCkptCreate(pid=%d): Failed to register ckpt callback rc[0x%x]\n", getpid(), ret_code); alarmClockLogWrite(CL_LOG_SEV_WARNING, "alarmClockCkptCreate(pid=%d): Falling back to warm standby mode\n", getpid()); //*ckpt_hot_standby = CL_FALSE; return ret_code; } alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptCreate: Successfully registered for callbacks"); } alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptCreate: Successful creation ckpt [%llx]\n", *ckpt_hdl); return SA_AIS_OK; }
/******************************************************************************* 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; }
SaAisErrorT alarmClockCkptRead ( SaCkptCheckpointHandleT ckpt_hdl, SaUint32T section_num, void* data, SaUint32T data_size ) { SaAisErrorT ret_code = SA_AIS_OK; SaUint32T error_index = 0; SaCkptIOVectorElementT *ioVecIter = ioVecs; ClUint32T bitmapChunks = 0; ClUint32T chunkSize = 0; ClUint32T ctrlHeaderSize = sessionBitmapHeaderSize(&chunkSize); if(g_hot_standby & HOT_STANDBY_ACTIVE) { /* * Start session buffering if hotstandby mode is active */ sessionBufferStart(); return SA_AIS_ERR_EXIST; } if(section_num > NUM_SECTION_ID_MAPS) return SA_AIS_ERR_INVALID_PARAM; /* * If section doesn't exist, then skip the read */ if(!sectionCreated) { if(__alarmClockCkptSectionCheck(ckpt_hdl, section_num) != CL_OK) return SA_AIS_ERR_NOT_EXIST; sectionCreated = CL_TRUE; } memset(ioVecs, 0, sizeof(*ioVecs) * MAX_NUM_IOVECS); /* * We don't need to read in the ctrl section since we would * be syncing our session bitmaps while reading the session data */ memcpy(&ioVecIter->sectionId, §ionIdMap[section_num-1].ctrlSectionId, sizeof(ioVecIter->sectionId)); ++ioVecIter; memcpy(&ioVecIter->sectionId, §ionIdMap[section_num-1].sectionId, sizeof(ioVecIter->sectionId)); ++ioVecIter; ret_code = saCkptCheckpointRead(ckpt_hdl, ioVecs, 2, &error_index); if(ret_code == SA_AIS_OK) { if(!ioVecs[0].readSize) { alarmClockLogWrite(CL_LOG_SEV_NOTICE, "alarmClockCkptRead(pid=%d): " "Session empty", getpid()); goto out_free; } if(ioVecs[0].readSize < ctrlHeaderSize) { alarmClockLogWrite(CL_LOG_SEV_WARNING, "alarmClockCkptRead(pid=%d): " "read [%d] bytes, expected [%d] bytes", getpid(), (ClUint32T)ioVecs[0].readSize, ctrlHeaderSize); ret_code = SA_AIS_ERR_BAD_OPERATION; goto out_free; } bitmapChunks = *(ClUint32T*)ioVecs[0].dataBuffer; alarmClockLogWrite(CL_LOG_SEV_DEBUG, "alarmClockCkptRead(pid=%d): " "Bitmap chunks [%d], Bitmap size [%d]\n", getpid(), bitmapChunks, (ClUint32T)(ioVecs[0].readSize - sizeof(bitmapChunks))); BitmapT bitmap = {0}; bitmap.map = (ClUint8T*)ioVecs[0].dataBuffer + sizeof(bitmapChunks); bitmap.words = BYTES_TO_WORDS(bitmapChunks * chunkSize); /* * We can also walk the session itself (#else case) without using the bitmap segment * but could be slightly costly in the worst case with session holes in between * for deleted or empty sessions. */ #if 1 __find_next_bit_walk(&bitmap, &ioVecs[1], bitmapWalkCallback); alarmClockLogWrite(CL_LOG_SEV_DEBUG, "alarmClockCkptRead(pid=%d): " "Found [%d] active sessions", getpid(), bitmap.bits); #else __find_next_bit_walk(&bitmap, NULL, bitmapWalkCallback); /* * Read in session data */ ClUint32T numSessions = 0; ClUint8T *sessionBuffer = ioVecs[1].dataBuffer; SessionT *sessionIter = (SessionT*)sessionBuffer; ClUint32T sessionDataSize = ioVecs[1].readSize; numSessions = sessionDataSize/sizeof(SessionT); alarmClockLogWrite(CL_LOG_SEV_DEBUG, "alarmClockCkptRead(pid=%d): " "Found [%d] sessions with ckpt size of [%d] bytes", getpid(), numSessions, sessionDataSize); for(ClUint32T i = 0; i < numSessions; ++i, ++sessionIter) { /* * Real world, has to unmarshall or copy-in to avoid unaligned access */ sessionUpdate(sessionIter, i); } #endif } out_free: if(ioVecs[0].dataBuffer) { clHeapFree(ioVecs[0].dataBuffer); ioVecs[0].dataBuffer = NULL; } if(ioVecs[1].dataBuffer) { clHeapFree(ioVecs[1].dataBuffer); ioVecs[1].dataBuffer = NULL; } return ret_code; }
void clCompAppAMFCSISet(SaInvocationT invocation, const SaNameT *compName, SaAmfHAStateT haState, SaAmfCSIDescriptorT csiDescriptor) { /* * Print information about the CSI Set */ clprintf (CL_LOG_SEV_INFO, "Component [%.*s] : PID [%d]. CSI Set Received\n", compName->length, compName->value, mypid); clCompAppAMFPrintCSI(csiDescriptor, haState); SaAisErrorT rc = SA_AIS_OK; /* create a checkpoint based on the csi descriptor name to ensure uniqueness Both processes will attempt to open/create the checkpoint. The first one will create it. */ if (alarmClockCkptHdl == 0) { strcpy(alarmClockCkptName, (char *)csiDescriptor.csiName.value); rc = alarmClockCkptCreate(alarmClockCkptName, 1, sizeof(acClockT), &alarmClockCkptHdl); if (rc != SA_AIS_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptCreate failed code [%d]", rc); assert(0); alarmClockCkptHdl = 0; } } /* * Take appropriate action based on state */ switch ( haState ) { case SA_AMF_HA_ACTIVE: { /* * AMF has requested application to take the active HA state * for the CSI. */ rc = alarmClockCkptActivate(alarmClockCkptHdl, 1); if (rc != SA_AIS_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptCreate(pid=%d): Failed to activate ckpt :0x%x\n", getpid(), rc); } if (rc == SA_AIS_OK) /* try to read the checkpoint regardless of prior state if I become active prevHaState == SA_AMF_HA_STANDBY) */ { /* this way the ckpt will be read on process restart */ acClockT alarmClock = {{0}}; alarmClockLogWrite(CL_LOG_SEV_INFO, "Reading checkpoint to recover the time"); rc = alarmClockCkptRead ( alarmClockCkptHdl, 1, &alarmClock, sizeof(acClockT)); if (rc == SA_AIS_OK) { alarmClockCopyAndStart( &alarmClock); } else { alarmClockStart(); } } else { alarmClockStart(); } prevHaState = haState; saAmfResponse(amfHandle, invocation, SA_AIS_OK); break; } case SA_AMF_HA_STANDBY: { /* * AMF has requested application to take the standby HA state * for this CSI. */ alarmClockLogWrite(CL_LOG_SEV_INFO, "I am standby"); prevHaState = haState; saAmfResponse(amfHandle, invocation, SA_AIS_OK); break; } case SA_AMF_HA_QUIESCED: { /* * AMF has requested application to quiesce the CSI currently * assigned the active or quiescing HA state. The application * must stop work associated with the CSI immediately. */ alarmClockStop(); prevHaState = haState; saAmfResponse(amfHandle, invocation, SA_AIS_OK); break; } case SA_AMF_HA_QUIESCING: { /* * AMF has requested application to quiesce the CSI currently * assigned the active HA state. The application must stop work * associated with the CSI gracefully and not accept any new * workloads while the work is being terminated. */ saAmfCSIQuiescingComplete(amfHandle, invocation, SA_AIS_OK); break; } default: { assert(0); break; } } return; }
/******************************************************************************* Feature API: alarmClockCkptCreate Description : Create a checkpoint given a name and the number of sections. In addition the nature of the checkpoint needs to be specified, synchronous versus asynchronous. If asynchronous collocated versus non collocated. Arguments In: 1. Checkpoint Name 2. Number of Sections 3. Size of section 4. ckpt_hot_standby: If set to true then hot standby turned on Arguments Out: 1. : returns ckpt_handle 2. ckpt_hot_standby: If set to true then hot standby was successful Return Value: ClInt32Teger 0 if success, non zero if failure *******************************************************************************/ ClRcT alarmClockCkptCreate ( const ClCharT *ckpt_name, ClInt32T num_sections, ClInt32T section_size, ClCkptHdlT *ckpt_hdl, ClBoolT *ckpt_hot_standby ) { ClRcT ret_code = CL_OK; SaNameT ckpt_name_t; ClCkptCheckpointCreationAttributesT ckpt_cr_attr; ClCkptOpenFlagsT ckpt_open_flags; ClTimeT timeout; ClCharT section_id_name[ CL_MAX_NAME_LENGTH ]; /* First ensure that the Initialize function is called */ ret_code = alarmClockCkptInitialize(); if (ret_code != CL_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptCreate(pid=%d): failed initialze service\n", getpid()); return ret_code; } /* Initiailze name struct for ckpt */ ckpt_name_t.length = strlen(ckpt_name); strcpy(ckpt_name_t.value, ckpt_name); /* Get the max size for a name of sectionId */ sprintf(section_id_name, "s%05d", num_sections); if (*ckpt_hot_standby == CL_TRUE) { /* Initialize check point creation flags (includes hot standby flag) */ ckpt_cr_attr.creationFlags = CL_CKPT_CHECKPOINT_COLLOCATED | CL_CKPT_DISTRIBUTED; } else { /* Initialize check point creation flags */ ckpt_cr_attr.creationFlags = CL_CKPT_CHECKPOINT_COLLOCATED; } /* Maximum checkpoint size = size of all checkpoints combined */ ckpt_cr_attr.checkpointSize = num_sections * section_size; /* Retention time: forever */ ckpt_cr_attr.retentionDuration = (ClTimeT)-1; if ( num_sections == 1 ) { /* use a named section instead of the default section */ ckpt_cr_attr.maxSections = num_sections + 1; } else { ckpt_cr_attr.maxSections = num_sections; } ckpt_cr_attr.maxSectionSize = section_size; ckpt_cr_attr.maxSectionIdSize = (ClSizeT)(strlen(section_id_name)+1); /* forever */ timeout = (ClTimeT)-1; /* Initialize the checkpoint open flags */ ckpt_open_flags = (CL_CKPT_CHECKPOINT_READ | CL_CKPT_CHECKPOINT_WRITE | CL_CKPT_CHECKPOINT_CREATE); /* forever */ timeout = (ClTimeT)-1; ret_code = clCkptCheckpointOpen(ckpt_svc_hdl, &ckpt_name_t, &ckpt_cr_attr, ckpt_open_flags, timeout, (ClCkptHdlT *)ckpt_hdl); if (ret_code != CL_OK) { alarmClockLogWrite(CL_LOG_SEV_ERROR, "alarmClockCkptCreate(pid=%d): Failed to create ckpt:0x%x\n", getpid(), ret_code); return ret_code; } if (*ckpt_hot_standby == CL_TRUE) { /* * Register checkpoint for immediate consumption, all components that * register using this API for a checkpoint will be notified through * the callback function provided when a checkpoint update occurs * All components except the one that actually updates the checkpoint. */ /* When the standby becomes Active it checks this flag to see whether * it needs to perform a checkpoint read or not. If TRUE then the * assumption is that the checkpoint updates on standby have happened * via the callback */ g_hot_standby = __HOT_STANDBY_IDLE; ret_code = clCkptImmediateConsumptionRegister(*ckpt_hdl, alarmClockCkptCallback, NULL); if (ret_code != CL_OK) { alarmClockLogWrite( CL_LOG_SEV_ERROR, "alarmClockCkptCreate(pid=%d): Failed to register ckpt callback rc[0x%x]\n", getpid(), ret_code); alarmClockLogWrite(CL_LOG_SEV_WARNING, "alarmClockCkptCreate(pid=%d): Falling back to warm standby mode\n", getpid()); *ckpt_hot_standby = CL_FALSE; } } alarmClockLogWrite(CL_LOG_SEV_INFO, "alarmClockCkptCreate: Ckpt [%s] created successfully", ckpt_name); return ret_code; }