64 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			64 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|   | package lookup | ||
|  | 
 | ||
|  | import "context" | ||
|  | 
 | ||
|  | // FluzCapacitorAlgorithm works by narrowing the epoch search area if an update is found | ||
|  | // going back and forth in time | ||
|  | // First, it will attempt to find an update where it should be now if the hint was | ||
|  | // really the last update. If that lookup fails, then the last update must be either the hint itself | ||
|  | // or the epochs right below. If however, that lookup succeeds, then the update must be | ||
|  | // that one or within the epochs right below. | ||
|  | // see the guide for a more graphical representation | ||
|  | func FluzCapacitorAlgorithm(ctx context.Context, now uint64, hint Epoch, read ReadFunc) (value interface{}, err error) { | ||
|  | 	var lastFound interface{} | ||
|  | 	var epoch Epoch | ||
|  | 	if hint == NoClue { | ||
|  | 		hint = worstHint | ||
|  | 	} | ||
|  | 
 | ||
|  | 	t := now | ||
|  | 
 | ||
|  | 	for { | ||
|  | 		epoch = GetNextEpoch(hint, t) | ||
|  | 		value, err = read(ctx, epoch, now) | ||
|  | 		if err != nil { | ||
|  | 			return nil, err | ||
|  | 		} | ||
|  | 		if value != nil { | ||
|  | 			lastFound = value | ||
|  | 			if epoch.Level == LowestLevel || epoch.Equals(hint) { | ||
|  | 				return value, nil | ||
|  | 			} | ||
|  | 			hint = epoch | ||
|  | 			continue | ||
|  | 		} | ||
|  | 		if epoch.Base() == hint.Base() { | ||
|  | 			if lastFound != nil { | ||
|  | 				return lastFound, nil | ||
|  | 			} | ||
|  | 			// we have reached the hint itself | ||
|  | 			if hint == worstHint { | ||
|  | 				return nil, nil | ||
|  | 			} | ||
|  | 			// check it out | ||
|  | 			value, err = read(ctx, hint, now) | ||
|  | 			if err != nil { | ||
|  | 				return nil, err | ||
|  | 			} | ||
|  | 			if value != nil { | ||
|  | 				return value, nil | ||
|  | 			} | ||
|  | 			// bad hint. | ||
|  | 			t = hint.Base() | ||
|  | 			hint = worstHint | ||
|  | 			continue | ||
|  | 		} | ||
|  | 		base := epoch.Base() | ||
|  | 		if base == 0 { | ||
|  | 			return nil, nil | ||
|  | 		} | ||
|  | 		t = base - 1 | ||
|  | 	} | ||
|  | 
 | ||
|  | } |