@@ -474,15 +474,37 @@ func doStructuralNormalization(conf *normalizedSpanConfig) error {
474474 allIndex int
475475 voterAndAllRel conjunctionRelationship
476476 }
477+ // emptyConstraintIndex corresponds to the index of the empty constraint in
478+ // conf.constraints. We expect only one empty constraint.
479+ // Example:
480+ // constraints: []: 2, [+region=a]: 2 => emptyConstraintIndex = 0
481+ //
482+ // TODO(wenyihu6): we should not allow user to specify empty constraints;
483+ // there should only be one created by us during normalizeConstraints.
484+ // Instead, we can also combine empty constraints into a single one in
485+ // normalizeConstraints.
477486 emptyConstraintIndex := - 1
487+ // emptyVoterConstraintIndex corresponds to the index of the empty voter
488+ // constraint in conf.voterConstraints. We expect only one empty voter
489+ // constraint.
490+ // Example:
491+ // voterConstraints: [+region=a]: 2, []: 2 => emptyVoterConstraintIndex = 1
478492 emptyVoterConstraintIndex := - 1
479493 var rels []relationshipVoterAndAll
480494 for i := range conf .voterConstraints {
481495 if len (conf .voterConstraints [i ].constraints ) == 0 {
496+ if emptyVoterConstraintIndex != - 1 {
497+ return errors .Errorf ("multiple empty voter constraints: %v and %v" ,
498+ conf .voterConstraints [emptyVoterConstraintIndex ], conf .voterConstraints [i ])
499+ }
482500 emptyVoterConstraintIndex = i
483501 }
484502 for j := range conf .constraints {
485503 if len (conf .constraints [j ].constraints ) == 0 {
504+ if emptyConstraintIndex != - 1 && emptyConstraintIndex != j {
505+ return errors .Errorf ("multiple empty constraints: %v and %v" ,
506+ conf .constraints [emptyConstraintIndex ], conf .constraints [j ])
507+ }
486508 emptyConstraintIndex = j
487509 }
488510 rels = append (rels , relationshipVoterAndAll {
@@ -577,10 +599,7 @@ func doStructuralNormalization(conf *normalizedSpanConfig) error {
577599 voterConstraints [rel .voterIndex ].numReplicas
578600 if neededVoterReplicas > 0 && remainingAll > 0 {
579601 // We can satisfy some voter replicas.
580- toAdd := remainingAll
581- if toAdd > neededVoterReplicas {
582- toAdd = neededVoterReplicas
583- }
602+ toAdd := min (remainingAll , neededVoterReplicas )
584603 voterConstraints [rel .voterIndex ].numReplicas += toAdd
585604 allReplicaConstraints [rel .allIndex ].remainingReplicas -= toAdd
586605 }
@@ -602,20 +621,20 @@ func doStructuralNormalization(conf *normalizedSpanConfig) error {
602621 // has some remainingReplicas, we take them here to satisfy the empty voter
603622 // constraint as much as possible. Only what is remaining in the empty voter
604623 // constraint will then be available for subsequent narrowing.
605- if emptyVoterConstraintIndex > 0 && emptyConstraintIndex > 0 {
624+ if emptyVoterConstraintIndex >= 0 && emptyConstraintIndex >= 0 {
606625 neededReplicas := conf .voterConstraints [emptyVoterConstraintIndex ].numReplicas
607- actualReplicas := voterConstraints [ emptyVoterConstraintIndex ]. numReplicas
608- remaining := neededReplicas - actualReplicas
609- if remaining > 0 {
610- remainingSatisfiable := allReplicaConstraints [ emptyConstraintIndex ]. remainingReplicas
611- if remainingSatisfiable > 0 {
612- count := remainingSatisfiable
613- if count > remaining {
614- count = remaining
615- }
616- voterConstraints [ emptyVoterConstraintIndex ]. numReplicas += count
617- allReplicaConstraints [ emptyConstraintIndex ]. remainingReplicas - = count
618- }
626+ // While iterating over the previous relationships, we skipped over
627+ // emptyVoterConstraintIndex, so its corresponding
628+ // voterConstraints.numReplicas must be 0.
629+ if voterConstraints [ emptyVoterConstraintIndex ]. numReplicas != 0 {
630+ panic ( errors . AssertionFailedf ( "programming error: voterConstraints[%d].numReplicas should be 0, but is %d" ,
631+ emptyVoterConstraintIndex , voterConstraints [ emptyVoterConstraintIndex ]))
632+ }
633+ remainingSatisfiable := allReplicaConstraints [ emptyConstraintIndex ]. remainingReplicas
634+ if neededReplicas > 0 && remainingSatisfiable > 0 {
635+ count := min ( remainingSatisfiable , neededReplicas )
636+ voterConstraints [ emptyVoterConstraintIndex ]. numReplicas + = count
637+ allReplicaConstraints [ emptyConstraintIndex ]. remainingReplicas -= count
619638 }
620639 }
621640
@@ -761,19 +780,17 @@ func doStructuralNormalization(conf *normalizedSpanConfig) error {
761780 // rel.voterIndex must be emptyVoterConstraintIndex.
762781 continue
763782 }
764- if conf .constraints [rel .allIndex ].numReplicas < conf .voterConstraints [rel .voterIndex ].numReplicas {
765- toAddCount := conf .voterConstraints [rel .voterIndex ].numReplicas -
766- conf .constraints [rel .allIndex ].numReplicas
767- availableCount := conf .constraints [emptyConstraintIndex ].numReplicas
768- if availableCount < toAddCount {
769- // TODO(wenyihu6): this should also create an error, since we will
770- // end up with two identical constraint conjunctions in replica
771- // constraints and voter constraints, with the former having a lower
772- // count than the latter.
773- toAddCount = availableCount
774- }
775- conf .constraints [emptyConstraintIndex ].numReplicas -= toAddCount
776- conf .constraints [rel .allIndex ].numReplicas += toAddCount
783+ toAddCount := conf .voterConstraints [rel .voterIndex ].numReplicas -
784+ conf .constraints [rel .allIndex ].numReplicas
785+ availableCount := conf .constraints [emptyConstraintIndex ].numReplicas
786+ if toAddCount > 0 && availableCount > 0 {
787+ // TODO(wenyihu6): this should also create an error, since we will
788+ // end up with two identical constraint conjunctions in replica
789+ // constraints and voter constraints, with the former having a lower
790+ // count than the latter.
791+ add := min (toAddCount , availableCount )
792+ conf .constraints [emptyConstraintIndex ].numReplicas -= add
793+ conf .constraints [rel .allIndex ].numReplicas += add
777794 }
778795 }
779796 // For conjStrictSubset, if the subset relationship is with
@@ -790,14 +807,12 @@ func doStructuralNormalization(conf *normalizedSpanConfig) error {
790807 continue
791808 }
792809 availableCount := conf .constraints [emptyConstraintIndex ].numReplicas
793- if availableCount > 0 {
794- toAddCount := conf .voterConstraints [rel .voterIndex ].numReplicas
795- if toAddCount > availableCount {
796- toAddCount = availableCount
797- }
798- conf .constraints [emptyConstraintIndex ].numReplicas -= toAddCount
810+ toAddCount := conf .voterConstraints [rel .voterIndex ].numReplicas
811+ if availableCount > 0 && toAddCount > 0 {
812+ add := min (availableCount , toAddCount )
813+ conf .constraints [emptyConstraintIndex ].numReplicas -= add
799814 conf .constraints = append (conf .constraints , internedConstraintsConjunction {
800- numReplicas : toAddCount ,
815+ numReplicas : add ,
801816 constraints : conf .voterConstraints [rel .voterIndex ].constraints ,
802817 })
803818 }
0 commit comments