github.com/swiftstack/proxyfs@v0.0.0-20201223034610-5434d919416e/liveness/api_internal.go (about) 1 package liveness 2 3 import ( 4 "reflect" 5 "sync" 6 ) 7 8 func fetchLivenessReport() (livenessReport *LivenessReportStruct) { 9 var ( 10 err error 11 fetchLivenessReportRequest *FetchLivenessReportRequestStruct 12 fetchLivenessReportResponse *FetchLivenessReportResponseStruct 13 leaderPeer *peerStruct 14 leaderResponseDone sync.WaitGroup 15 ) 16 17 globals.Lock() 18 if globals.active { 19 switch reflect.ValueOf(globals.nextState) { 20 case reflect.ValueOf(doCandidate): 21 // Return a local-only Liveness Report 22 livenessReport = &LivenessReportStruct{ 23 ObservingPeer: make([]*ObservingPeerStruct, 1), 24 } 25 livenessReport.ObservingPeer[0] = convertInternalToExternalObservingPeerReport(globals.myObservingPeerReport) 26 case reflect.ValueOf(doFollower): 27 leaderPeer = globals.currentLeader 28 if nil == leaderPeer { 29 // Special case where we just started in doFollower state but haven't yet received a HeartBeat 30 livenessReport = nil 31 } else { 32 // Need to go ask leaderPeer for Liveness Report 33 fetchLivenessReportRequest = &FetchLivenessReportRequestStruct{ 34 MsgType: MsgTypeFetchLivenessReportRequest, 35 MsgTag: fetchNonceWhileLocked(), 36 CurrentTerm: globals.currentTerm, 37 } 38 globals.Unlock() 39 leaderResponseDone.Add(1) 40 err = sendRequest( 41 leaderPeer, 42 fetchLivenessReportRequest.MsgTag, 43 nil, // Only one can be outstanding... so no need for non-nil requestContext 44 fetchLivenessReportRequest, 45 func(request *requestStruct) { 46 if request.expired { 47 fetchLivenessReportResponse = nil 48 } else { 49 fetchLivenessReportResponse = request.responseMsg.(*FetchLivenessReportResponseStruct) 50 } 51 leaderResponseDone.Done() 52 }, 53 ) 54 if nil != err { 55 panic(err) 56 } 57 leaderResponseDone.Wait() 58 livenessReport = fetchLivenessReportResponse.LivenessReport 59 globals.Lock() 60 } 61 case reflect.ValueOf(doLeader): 62 livenessReport = convertInternalToExternalLivenessReport(globals.livenessReport) 63 } 64 } else { 65 livenessReport = nil 66 } 67 globals.Unlock() 68 return 69 } 70 71 func convertInternalToExternalLivenessReport(internalLivenessReport *internalLivenessReportStruct) (externalLivenessReport *LivenessReportStruct) { 72 var ( 73 internalObservingPeerReport *internalObservingPeerReportStruct 74 observingPeer *ObservingPeerStruct 75 ) 76 77 if nil == internalLivenessReport { 78 externalLivenessReport = nil 79 return 80 } 81 82 externalLivenessReport = &LivenessReportStruct{ 83 ObservingPeer: make([]*ObservingPeerStruct, 0, len(internalLivenessReport.observingPeer)), 84 } 85 86 for _, internalObservingPeerReport = range internalLivenessReport.observingPeer { 87 observingPeer = convertInternalToExternalObservingPeerReport(internalObservingPeerReport) 88 externalLivenessReport.ObservingPeer = append(externalLivenessReport.ObservingPeer, observingPeer) 89 } 90 91 return 92 } 93 94 func convertExternalToInternalLivenessReport(externalLivenessReport *LivenessReportStruct) (internalLivenessReport *internalLivenessReportStruct) { 95 var ( 96 internalObservingPeerReport *internalObservingPeerReportStruct 97 observingPeer *ObservingPeerStruct 98 ) 99 100 if nil == externalLivenessReport { 101 internalLivenessReport = nil 102 return 103 } 104 105 internalLivenessReport = &internalLivenessReportStruct{ 106 observingPeer: make(map[string]*internalObservingPeerReportStruct), 107 } 108 109 for _, observingPeer = range externalLivenessReport.ObservingPeer { 110 internalObservingPeerReport = convertExternalToInternalObservingPeerReport(observingPeer) 111 internalLivenessReport.observingPeer[internalObservingPeerReport.name] = internalObservingPeerReport 112 } 113 114 return 115 } 116 117 func convertInternalToExternalObservingPeerReport(internalObservingPeerReport *internalObservingPeerReportStruct) (externalObservingPeer *ObservingPeerStruct) { 118 var ( 119 internalReconEndpointReport *internalReconEndpointReportStruct 120 internalServingPeerReport *internalServingPeerReportStruct 121 internalVolumeGroupReport *internalVolumeGroupReportStruct 122 internalVolumeReport *internalVolumeReportStruct 123 reconEndpoint *ReconEndpointStruct 124 servingPeer *ServingPeerStruct 125 volume *VolumeStruct 126 volumeGroup *VolumeGroupStruct 127 ) 128 129 if nil == internalObservingPeerReport { 130 externalObservingPeer = nil 131 return 132 } 133 134 externalObservingPeer = &ObservingPeerStruct{ 135 Name: internalObservingPeerReport.name, 136 ServingPeer: make([]*ServingPeerStruct, 0, len(internalObservingPeerReport.servingPeer)), 137 ReconEndpoint: make([]*ReconEndpointStruct, 0, len(internalObservingPeerReport.reconEndpoint)), 138 } 139 140 for _, internalServingPeerReport = range internalObservingPeerReport.servingPeer { 141 servingPeer = &ServingPeerStruct{ 142 Name: internalServingPeerReport.name, 143 State: internalServingPeerReport.state, 144 LastCheckTime: internalServingPeerReport.lastCheckTime, 145 VolumeGroup: make([]*VolumeGroupStruct, 0, len(internalServingPeerReport.volumeGroup)), 146 } 147 148 for _, internalVolumeGroupReport = range internalServingPeerReport.volumeGroup { 149 volumeGroup = &VolumeGroupStruct{ 150 Name: internalVolumeGroupReport.name, 151 State: internalVolumeGroupReport.state, 152 LastCheckTime: internalVolumeGroupReport.lastCheckTime, 153 Volume: make([]*VolumeStruct, 0, len(internalVolumeGroupReport.volume)), 154 } 155 156 for _, internalVolumeReport = range internalVolumeGroupReport.volume { 157 volume = &VolumeStruct{ 158 Name: internalVolumeReport.name, 159 State: internalVolumeReport.state, 160 LastCheckTime: internalVolumeReport.lastCheckTime, 161 } 162 163 volumeGroup.Volume = append(volumeGroup.Volume, volume) 164 } 165 166 servingPeer.VolumeGroup = append(servingPeer.VolumeGroup, volumeGroup) 167 } 168 169 externalObservingPeer.ServingPeer = append(externalObservingPeer.ServingPeer, servingPeer) 170 } 171 172 for _, internalReconEndpointReport = range internalObservingPeerReport.reconEndpoint { 173 reconEndpoint = &ReconEndpointStruct{ 174 IPAddrPort: internalReconEndpointReport.ipAddrPort, 175 MaxDiskUsagePercentage: internalReconEndpointReport.maxDiskUsagePercentage, 176 } 177 178 externalObservingPeer.ReconEndpoint = append(externalObservingPeer.ReconEndpoint, reconEndpoint) 179 } 180 181 return 182 } 183 184 func convertExternalToInternalObservingPeerReport(externalObservingPeer *ObservingPeerStruct) (internalObservingPeerReport *internalObservingPeerReportStruct) { 185 var ( 186 internalReconEndpointReport *internalReconEndpointReportStruct 187 internalServingPeerReport *internalServingPeerReportStruct 188 internalVolumeGroupReport *internalVolumeGroupReportStruct 189 internalVolumeReport *internalVolumeReportStruct 190 reconEndpoint *ReconEndpointStruct 191 servingPeer *ServingPeerStruct 192 volume *VolumeStruct 193 volumeGroup *VolumeGroupStruct 194 ) 195 196 if nil == externalObservingPeer { 197 internalObservingPeerReport = nil 198 return 199 } 200 201 internalObservingPeerReport = &internalObservingPeerReportStruct{ 202 name: externalObservingPeer.Name, 203 servingPeer: make(map[string]*internalServingPeerReportStruct), 204 reconEndpoint: make(map[string]*internalReconEndpointReportStruct), 205 } 206 207 for _, servingPeer = range externalObservingPeer.ServingPeer { 208 internalServingPeerReport = &internalServingPeerReportStruct{ 209 observingPeer: internalObservingPeerReport, 210 name: servingPeer.Name, 211 state: servingPeer.State, 212 lastCheckTime: servingPeer.LastCheckTime, 213 volumeGroup: make(map[string]*internalVolumeGroupReportStruct), 214 } 215 216 for _, volumeGroup = range servingPeer.VolumeGroup { 217 internalVolumeGroupReport = &internalVolumeGroupReportStruct{ 218 servingPeer: internalServingPeerReport, 219 name: volumeGroup.Name, 220 state: volumeGroup.State, 221 lastCheckTime: volumeGroup.LastCheckTime, 222 volume: make(map[string]*internalVolumeReportStruct), 223 } 224 225 for _, volume = range volumeGroup.Volume { 226 internalVolumeReport = &internalVolumeReportStruct{ 227 volumeGroup: internalVolumeGroupReport, 228 name: volume.Name, 229 state: volume.State, 230 lastCheckTime: volume.LastCheckTime, 231 } 232 233 internalVolumeGroupReport.volume[internalVolumeReport.name] = internalVolumeReport 234 } 235 236 internalServingPeerReport.volumeGroup[internalVolumeGroupReport.name] = internalVolumeGroupReport 237 } 238 239 internalObservingPeerReport.servingPeer[internalServingPeerReport.name] = internalServingPeerReport 240 } 241 242 for _, reconEndpoint = range externalObservingPeer.ReconEndpoint { 243 internalReconEndpointReport = &internalReconEndpointReportStruct{ 244 observingPeer: internalObservingPeerReport, 245 ipAddrPort: reconEndpoint.IPAddrPort, 246 maxDiskUsagePercentage: reconEndpoint.MaxDiskUsagePercentage, 247 } 248 249 internalObservingPeerReport.reconEndpoint[internalReconEndpointReport.ipAddrPort] = internalReconEndpointReport 250 } 251 252 return 253 }