feat: P1-1 handle resource value push via OPCode_notify
Add OPCode_notify handler in go_push_handler top-level switch (not inside handlePush) to receive resource value updates from the controller via xce_notify_data_t/schedUpdateResvals. - Add 8 CGO union accessors for xce_val_t (which, i32, i64, u32, u64, fval, str, bool) since CGO cannot access union fields - Add handleNotifyData() dispatching NotifyData_data_schedUpdateResvals events, iterating xce_resval_list_t and calling cResvalToDistribution - Add cResvalToDistribution in convert.go with 7 separate switch cases for Value_u_* union discriminants (no combining i32/i64) - Add rawResvalData + rawResvalToDistribution pure-Go version in convert_pure.go for testability without CGO - Add 10 TDD tests covering all 7 value types, nil val guard, unknown discriminant, and boolean false - All 42 backend tests passing
This commit is contained in:
parent
dc029a6d14
commit
bc3103a6d5
5 changed files with 365 additions and 23 deletions
|
|
@ -10,7 +10,10 @@ import "C"
|
|||
|
||||
import (
|
||||
"apiserver/models"
|
||||
logger "apiserver/utils"
|
||||
"unsafe"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// goString safely converts a C string to a Go string, handling nil.
|
||||
|
|
@ -250,3 +253,52 @@ func freeJobSubmit(js *C.xce_job_submit_t, sd *C.job_submit_data_t, si *C.job_st
|
|||
C.free(unsafe.Pointer(js))
|
||||
}
|
||||
}
|
||||
|
||||
// cResvalToDistribution converts a C xce_resval_t pointer to a Go ResourceDistributionInfo.
|
||||
// Returns nil if vp.val is NULL (nil guard prevents CGO panic).
|
||||
// vp.val is a *C.xce_val_t pointer field — pass directly, no &.
|
||||
func cResvalToDistribution(vp *C.xce_resval_t) *models.ResourceDistributionInfo {
|
||||
rd := &models.ResourceDistributionInfo{
|
||||
ResourceName: C.GoString(vp.name),
|
||||
Location: C.GoString(vp.host),
|
||||
IsDynamic: true, // resource values pushed from workers are always dynamic
|
||||
}
|
||||
// Guard: vp.val may be NULL if the controller sends a resval with no value set.
|
||||
// Dereferencing NULL in xce_val_which() would segfault in C.
|
||||
if vp.val == nil {
|
||||
logger.Warn("resval with nil value, skipping",
|
||||
zap.String("resource", rd.ResourceName),
|
||||
zap.String("host", rd.Location))
|
||||
return nil
|
||||
}
|
||||
switch C.xce_val_which(vp.val) {
|
||||
case C.Value_u_ivalue32:
|
||||
rd.ValueType = int(models.NUMERIC)
|
||||
rd.NumericValue = float64(C.xce_val_i32(vp.val))
|
||||
case C.Value_u_ivalue64:
|
||||
rd.ValueType = int(models.NUMERIC)
|
||||
rd.NumericValue = float64(C.xce_val_i64(vp.val))
|
||||
case C.Value_u_uvalue32:
|
||||
rd.ValueType = int(models.NUMERIC)
|
||||
rd.NumericValue = float64(C.xce_val_u32(vp.val))
|
||||
case C.Value_u_uvalue64:
|
||||
rd.ValueType = int(models.NUMERIC)
|
||||
rd.NumericValue = float64(C.xce_val_u64(vp.val))
|
||||
case C.Value_u_fvalue:
|
||||
rd.ValueType = int(models.NUMERIC)
|
||||
rd.NumericValue = C.xce_val_fval(vp.val) // C.double → float64, no explicit cast needed
|
||||
case C.Value_u_svalue:
|
||||
rd.ValueType = int(models.STRING)
|
||||
rd.StringValue = C.GoString(C.xce_val_str(vp.val))
|
||||
case C.Value_u_bvalue:
|
||||
rd.ValueType = int(models.BOOLEAN)
|
||||
rd.BooleanValue = C.xce_val_bool(vp.val) != 0
|
||||
default:
|
||||
logger.Warn("unknown xce_val_t discriminant, skipping",
|
||||
zap.Int("which", int(C.xce_val_which(vp.val))),
|
||||
zap.String("resource", rd.ResourceName),
|
||||
zap.String("host", rd.Location))
|
||||
return nil
|
||||
}
|
||||
return rd
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue