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  }