feat(job-array-one-based-index): apiserver backend ID helpers and array ID wrapper (task 5.1)
GenerateArrayJobID wraps libxce idgen_array (first element, index 1; one-element arrays included) with a non-cgo stub; pure helpers ParseHumanJobIDStrict (written identity with exact field-width checks, uint64 overflow reported as a width error), IsArrayCapableKey and MakeElementID (bit-identical to libxce jobsel_element_id). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
47b9938120
commit
b88e352616
7 changed files with 260 additions and 3 deletions
|
|
@ -3,10 +3,11 @@ package backend
|
|||
import (
|
||||
"apiserver/models"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// JobID bit layout constants — mirrors src/include/config.h.
|
||||
|
|
@ -132,6 +133,66 @@ func ParseHumanJobID(s string) (uint64, bool) {
|
|||
sequence, true
|
||||
}
|
||||
|
||||
// Errors returned by ParseHumanJobIDStrict. Callers map them to their own
|
||||
// messages: ErrJobIDSyntax is the written-form syntax rule, ErrJobIDWidth the
|
||||
// field-width rule (job-array-one-based-index 5.14).
|
||||
var (
|
||||
ErrJobIDSyntax = errors.New("job ID is not of the form cluster-apiserver-timestamp-sequence")
|
||||
ErrJobIDWidth = errors.New("job ID field out of range")
|
||||
)
|
||||
|
||||
// ParseHumanJobIDStrict parses a written job identity "c-a-ts-seq" (decimal
|
||||
// digits only, leading zeros allowed, no sign, no whitespace, no "[...]")
|
||||
// into its packed, untagged ID. Unlike ParseHumanJobID it checks every field
|
||||
// against its bit width -- cluster <= 63, apiserver <= 15, timestamp < 2^32,
|
||||
// sequence < 2^20 -- so an oversized field is rejected (ErrJobIDWidth)
|
||||
// instead of spilling into a neighbouring field. A field too large even for
|
||||
// uint64 is also ErrJobIDWidth. Anything not of that shape is ErrJobIDSyntax.
|
||||
func ParseHumanJobIDStrict(s string) (uint64, error) {
|
||||
m := humanJobIDPattern.FindStringSubmatch(s)
|
||||
if m == nil {
|
||||
return 0, ErrJobIDSyntax
|
||||
}
|
||||
widths := [4]int{nClusterIDBits, nApiserverIDBits, nTimestampBits, nSequenceBits}
|
||||
var f [4]uint64
|
||||
for i, w := range widths {
|
||||
v, err := strconv.ParseUint(m[i+1], 10, 64)
|
||||
if err != nil {
|
||||
if errors.Is(err, strconv.ErrRange) {
|
||||
return 0, ErrJobIDWidth
|
||||
}
|
||||
return 0, ErrJobIDSyntax
|
||||
}
|
||||
if v >= uint64(1)<<w {
|
||||
return 0, ErrJobIDWidth
|
||||
}
|
||||
f[i] = v
|
||||
}
|
||||
return (f[0] << clusterIDShift) |
|
||||
(f[1] << apiserverIDShift) |
|
||||
(f[2] << timestampShift) |
|
||||
f[3], nil
|
||||
}
|
||||
|
||||
// arrayIdxMask covers the 15-bit array index field (bits 0-14).
|
||||
const arrayIdxMask = uint64(1)<<nArrayIdxBits - 1
|
||||
|
||||
// IsArrayCapableKey reports whether key can name an array (an "<array-id>"
|
||||
// in "<array-id>[k]"): tag 0 and the low 15 (index) bits clear, i.e. the
|
||||
// sequence is a multiple of 32768 (job-array-one-based-index 5.8).
|
||||
func IsArrayCapableKey(key uint64) bool {
|
||||
return extractIDTag(key) == 0 && key&arrayIdxMask == 0
|
||||
}
|
||||
|
||||
// MakeElementID composes the ID of element k of the array identified by key:
|
||||
// key's cluster, apiserver, timestamp and sequence-high bits, tag
|
||||
// TAG_JOB_ARRAY and index k (masked to 15 bits). key's own tag and index bits
|
||||
// are ignored. Mirrors jobsel_element_id() in src/lib/utils.c.
|
||||
func MakeElementID(key uint64, k int) uint64 {
|
||||
base := key &^ (uint64(1<<nTagBits-1)<<tagShift | arrayIdxMask)
|
||||
return uint64(tagJobArray)<<tagShift | base | uint64(k)&arrayIdxMask
|
||||
}
|
||||
|
||||
// WorkerDefaultOutputPath returns the output file path the worker uses by default
|
||||
// for the given job ID and task index, matching uv_proc.c make_job_output_path().
|
||||
func WorkerDefaultOutputPath(uniqueJobID int64, taskIdx int) string {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue