1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef SYNC_STATE_MACHINE_H 17 #define SYNC_STATE_MACHINE_H 18 19 #include <mutex> 20 21 #include "isync_interface.h" 22 #include "isync_state_machine.h" 23 24 namespace DistributedDB { 25 // the 1st uint8_t is event, the 2nd uint8_t is out state 26 using EventToState = std::map<uint8_t, uint8_t>; 27 28 // The StateSwitchTable with the SyncProctolVersion 29 struct StateSwitchTable { 30 uint32_t version = 0; 31 std::map<uint8_t, EventToState> switchTable; // the 1st uint8_t is current state 32 }; 33 34 struct WatchDogController { 35 TimerId feedDogTimerId = 0; 36 uint8_t feedDogCnt = 0; 37 uint8_t feedDogUpperLimit = 0; 38 /* this variable will +1 when call StartFeedDogForSync, -1 when recv one ack, 39 when it become <= 0, we stop the watch dog. */ 40 int refCount = 0; 41 }; 42 43 class SyncStateMachine : public ISyncStateMachine { 44 public: 45 SyncStateMachine(); 46 ~SyncStateMachine() override; 47 48 // Init the SingleVerSyncStateMachine 49 int Initialize(ISyncTaskContext *context, ISyncInterface *syncInterface, std::shared_ptr<Metadata> &metadata, 50 ICommunicator *communicator) override; 51 52 // start a sync step 53 int StartSync() override; 54 55 // call when timeout 56 int TimeoutCallback(TimerId timerId) override; 57 58 // Force stop the state machine 59 void Abort() override; 60 61 // Force stop the state machine now 62 void AbortImmediately() override; 63 64 // Force stop current task with sessionId 65 void InnerErrorAbort(uint32_t sessionId) override; 66 67 // start a timer to ResetWatchDog when sync data one (key,value) size bigger than mtu 68 bool StartFeedDogForSync(uint32_t time, SyncDirectionFlag flag) override; 69 70 uint8_t GetFeedDogTimeout(int timeoutCount) const; 71 72 // stop timer to ResetWatchDog when sync data one (key,value) size bigger than mtu 73 void StopFeedDogForSync(SyncDirectionFlag flag) override; 74 75 // start a timer to ResetWatchDog when get data and send notify ack if need 76 void StartFeedDogForGetData(uint32_t sessionId) override; 77 78 // start a timer to ResetWatchDog when get data and stop send notify ack if need 79 void StopFeedDogForGetData() override; 80 81 // Notify machine is closing, should release some lock 82 void NotifyClosing() override; 83 protected: 84 85 // SyncOperation is timeout, step to timeout state 86 virtual void StepToTimeout(TimerId timerId) = 0; 87 88 // Step the SingleVerSyncStateMachine 89 virtual void SyncStep() = 0; 90 91 // Called by SyncStep, Sub class should realize this function to do machine step 92 virtual void SyncStepInnerLocked() = 0; 93 94 // Do state machine step with no lock, for inner use 95 virtual void SyncStepInner() = 0; 96 97 // Called by StartSync, Sub class should realize this function to start statemachine 98 virtual int StartSyncInner() = 0; 99 100 // Called by Abort, Sub class should realize this function to force abort statemachine 101 virtual void AbortInner() = 0; 102 103 // while currentstate could not be found, should called, Sub class should realize this function. 104 virtual void SetCurStateErrStatus(); 105 106 // Used to get instance class' stateSwitchTables 107 virtual const std::vector<StateSwitchTable> &GetStateSwitchTables() const = 0; 108 109 // Called by ExecNextTask, Sub class should realize this function to do some thing for run next sync task 110 virtual int PrepareNextSyncTask() = 0; 111 112 // Called by StartSaveDataNotifyTimer, Sub class should realize this function to send a heartbeet packet 113 virtual void SendNotifyPacket(uint32_t sessionId, uint32_t sequenceId, uint32_t inMsgId) = 0; 114 115 // Used to parse state table to switch machine state, this function must be called in stateMachineLock 116 int SwitchMachineState(uint8_t event); 117 118 // Do state switch with the event, and do syncstep 119 virtual void SwitchStateAndStep(uint8_t event); 120 121 // To Exec next sync task in context targetQueue 122 int ExecNextTask(); 123 124 // Start a watchdog used for manual sync, when begin a manual sync 125 int StartWatchDog(); 126 127 // Reset the watchdog used for manual sync 128 int ResetWatchDog(); 129 130 // stop a watchdog used for manual sync, call when sync finished, 131 void StopWatchDog(); 132 133 // Start a timer to send data notify packet to keep remote device not timeout 134 bool StartSaveDataNotify(uint32_t sessionId, uint32_t sequenceId, uint32_t inMsgId); 135 136 // Stop send save data notify 137 void StopSaveDataNotify(); 138 139 // Stop send save data notify without lock 140 void StopSaveDataNotifyNoLock(); 141 142 // stop a timer to ResetWatchDog when sync data bigger than mtu without lock 143 void StopFeedDogForSyncNoLock(SyncDirectionFlag flag); 144 145 void DecRefCountOfFeedDogTimer(SyncDirectionFlag flag); 146 147 virtual void DoSaveDataNotify(uint32_t sessionId, uint32_t sequenceId, uint32_t inMsgId); 148 149 void DoFeedDogForSync(SyncDirectionFlag flag); 150 151 void DoGetAndSendDataNotify(uint32_t sessionId); 152 153 void StopFeedDogForGetDataInner(TimerId timerId); 154 155 DISABLE_COPY_ASSIGN_MOVE(SyncStateMachine); 156 157 ISyncTaskContext *syncContext_; 158 ISyncInterface *storageInterface_; 159 ICommunicator *communicator_; 160 std::shared_ptr<Metadata> metadata_; 161 std::mutex stateMachineLock_; 162 uint8_t currentState_; 163 bool watchDogStarted_; 164 uint32_t currentSyncProctolVersion_; 165 166 // For save data notify 167 static const int DATA_NOTIFY_INTERVAL = 2000; // 2s for save/get data notify 168 static const int MAX_DATA_NOTIFY_COUNT = 15; // only notify 15 times 169 static const int SYNC_DIRECTION_NUM = 2; // send receive 170 std::mutex saveDataNotifyLock_; 171 TimerId saveDataNotifyTimerId_; 172 uint8_t saveDataNotifyCount_; 173 174 std::mutex getDataNotifyLock_; 175 TimerId getDataNotifyTimerId_; 176 uint8_t getDataNotifyCount_; 177 178 // used for one (key,value) bigger than mtu size, in this case, send packet need more longger time 179 std::mutex feedDogLock_[SYNC_DIRECTION_NUM]; 180 WatchDogController watchDogController_[SYNC_DIRECTION_NUM] = {{0}, {0}}; 181 }; 182 } // namespace DistributedDB 183 #endif // SYNC_STATE_MACHINE_H 184