go-hep.org/x/hep@v0.38.1/groot/rtree/branch.go (about) 1 // Copyright ©2017 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package rtree 6 7 import ( 8 "fmt" 9 "reflect" 10 "strings" 11 12 "go-hep.org/x/hep/groot/rbase" 13 "go-hep.org/x/hep/groot/rbytes" 14 "go-hep.org/x/hep/groot/rcont" 15 "go-hep.org/x/hep/groot/rdict" 16 "go-hep.org/x/hep/groot/riofs" 17 "go-hep.org/x/hep/groot/root" 18 "go-hep.org/x/hep/groot/rtypes" 19 "go-hep.org/x/hep/groot/rvers" 20 ) 21 22 const ( 23 defaultBasketSize = 32 * 1024 // default basket size in bytes 24 defaultSplitLevel = 99 // default split-level for branches 25 defaultMaxBaskets = 10 // default number of baskets 26 ) 27 28 type tbranch struct { 29 named rbase.Named 30 attfill rbase.AttFill 31 compress int // compression level and algorithm 32 basketSize int // initial size of Basket buffer 33 entryOffsetLen int // initial length of entryOffset table in the basket buffers 34 writeBasket int // last basket number written 35 entryNumber int64 // current entry number (last one filled in this branch) 36 iobits tioFeatures // IO features for newly-created baskets 37 offset int // offset of this branch 38 maxBaskets int // maximum number of baskets so far 39 splitLevel int // branch split level 40 entries int64 // number of entries 41 firstEntry int64 // number of the first entry in this branch 42 totBytes int64 // total number of bytes in all leaves before compression 43 zipBytes int64 // total number of bytes in all leaves after compression 44 branches []Branch // list of branches of this branch 45 leaves []Leaf // list of leaves of this branch 46 baskets []Basket // list of baskets of this branch 47 48 basketBytes []int32 // length of baskets on file 49 basketEntry []int64 // table of first entry in each basket 50 basketSeek []int64 // addresses of baskets on file 51 52 fname string // named of file where buffers are stored (empty if in same file as Tree header) 53 54 ctx basketCtx // basket context for the current basket 55 56 tree *ttree // tree header 57 btop Branch // top-level parent branch in the tree 58 bup Branch // parent branch 59 dir riofs.Directory // directory where this branch's buffers are stored 60 } 61 62 func newBranchFromWVar(w *wtree, name string, wvar WriteVar, parent Branch, lvl int, cfg wopt) (Branch, error) { 63 base := &tbranch{ 64 named: *rbase.NewNamed(name, ""), 65 attfill: *rbase.NewAttFill(), 66 compress: int(cfg.compress), 67 68 iobits: w.ttree.iobits, 69 basketSize: int(cfg.bufsize), 70 maxBaskets: defaultMaxBaskets, 71 basketBytes: make([]int32, 0, defaultMaxBaskets), 72 basketEntry: make([]int64, 1, defaultMaxBaskets), 73 basketSeek: make([]int64, 0, defaultMaxBaskets), 74 75 tree: &w.ttree, 76 btop: btopOf(parent), 77 bup: parent, 78 dir: w.dir, 79 } 80 81 var ( 82 b Branch = base 83 84 title = new(strings.Builder) 85 rt = reflect.TypeOf(wvar.Value).Elem() 86 ) 87 88 title.WriteString(wvar.Name) 89 switch k := rt.Kind(); k { 90 case reflect.Array: 91 et, shape := flattenArrayType(rt) 92 for _, dim := range shape { 93 fmt.Fprintf(title, "[%d]", dim) 94 } 95 rt = et 96 97 case reflect.Slice: 98 switch wvar.Count { 99 case "": 100 // write as a std::vector<T> 101 return newBranchElementFromWVar(w, base, wvar, parent, lvl, cfg) 102 default: 103 fmt.Fprintf(title, "[%s]", wvar.Count) 104 rt = rt.Elem() 105 } 106 base.entryOffsetLen = 1000 // slice, so we need an offset array 107 108 case reflect.String: 109 base.entryOffsetLen = 1000 // string, so we need an offset array 110 111 case reflect.Struct: 112 return newBranchElementFromWVar(w, base, wvar, parent, lvl, cfg) 113 } 114 115 isBranchElem := false 116 if parent != nil { 117 if parent, ok := parent.(*tbranchElement); ok { 118 isBranchElem = true 119 be := &tbranchElement{ 120 tbranch: *base, 121 class: parent.class, 122 parent: parent.class, 123 } 124 b = be 125 base = &be.tbranch 126 } 127 } 128 129 if !isBranchElem && rt.Kind() != reflect.Struct { 130 code := gotypeToROOTTypeCode(rt) 131 fmt.Fprintf(title, "/%s", code) 132 } 133 134 _, err := newLeafFromWVar(w, b, wvar, lvl, cfg) 135 if err != nil { 136 return nil, err 137 } 138 139 base.named.SetTitle(title.String()) 140 base.createNewBasket() 141 142 return b, nil 143 } 144 145 func (b *tbranch) RVersion() int16 { 146 return rvers.Branch 147 } 148 149 func (b *tbranch) Name() string { 150 return b.named.Name() 151 } 152 153 func (b *tbranch) Title() string { 154 return b.named.Title() 155 } 156 157 func (b *tbranch) Class() string { 158 return "TBranch" 159 } 160 161 func (b *tbranch) getTree() *ttree { 162 return b.tree 163 } 164 165 func (b *tbranch) setTree(t *ttree) { 166 b.tree = t 167 for _, sub := range b.branches { 168 sub.setTree(t) 169 } 170 } 171 172 func (b *tbranch) Branches() []Branch { 173 return b.branches 174 } 175 176 func (b *tbranch) Leaves() []Leaf { 177 return b.leaves 178 } 179 180 func (b *tbranch) Branch(name string) Branch { 181 for _, bb := range b.Branches() { 182 if bb.Name() == name { 183 return bb 184 } 185 } 186 return nil 187 } 188 189 func (b *tbranch) Leaf(name string) Leaf { 190 for _, lf := range b.Leaves() { 191 if lf.Name() == name { 192 return lf 193 } 194 } 195 switch { 196 case b.bup != nil: 197 return b.bup.Leaf(name) 198 case b.btop != nil: 199 return b.btop.Leaf(name) 200 case b.tree != nil: 201 return b.tree.Leaf(name) 202 } 203 return nil 204 } 205 206 func (b *tbranch) GoType() reflect.Type { 207 if len(b.Leaves()) == 1 { 208 return b.leaves[0].Type() 209 } 210 fields := make([]reflect.StructField, len(b.leaves)) 211 for i, leaf := range b.leaves { 212 ft := &fields[i] 213 ft.Name = "ROOT_" + leaf.Name() 214 etype := leaf.Type() 215 switch { 216 case leaf.LeafCount() != nil: 217 etype = reflect.SliceOf(etype) 218 case leaf.Len() > 1 && leaf.Kind() != reflect.String: 219 etype = reflect.ArrayOf(leaf.Len(), etype) 220 } 221 ft.Type = etype 222 } 223 return reflect.StructOf(fields) 224 } 225 226 func (b *tbranch) getReadEntry() int64 { 227 return b.ctx.entry 228 } 229 230 func (b *tbranch) getEntry(i int64) { 231 if b.ctx.entry == i { 232 return 233 } 234 err := b.loadEntry(i) 235 if err != nil { 236 panic(fmt.Errorf("rtree: branch [%s] failed to load entry %d: %w", b.Name(), i, err)) 237 } 238 } 239 240 func (b *tbranch) MarshalROOT(w *rbytes.WBuffer) (int, error) { 241 if w.Err() != nil { 242 return 0, w.Err() 243 } 244 245 maxBaskets := b.maxBaskets 246 defer func() { b.maxBaskets = maxBaskets }() 247 b.maxBaskets = max(b.writeBasket+1, defaultMaxBaskets) 248 249 hdr := w.WriteHeader(b.Class(), b.RVersion()) 250 w.WriteObject(&b.named) 251 w.WriteObject(&b.attfill) 252 w.WriteI32(int32(b.compress)) 253 w.WriteI32(int32(b.basketSize)) 254 w.WriteI32(int32(b.entryOffsetLen)) 255 w.WriteI32(int32(b.writeBasket)) 256 w.WriteI64(b.entryNumber) 257 w.WriteObject(&b.iobits) 258 w.WriteI32(int32(b.offset)) 259 w.WriteI32(int32(b.maxBaskets)) 260 w.WriteI32(int32(b.splitLevel)) 261 w.WriteI64(b.entries) 262 w.WriteI64(b.firstEntry) 263 w.WriteI64(b.totBytes) 264 w.WriteI64(b.zipBytes) 265 266 { 267 branches := rcont.NewObjArray() 268 if len(b.branches) > 0 { 269 elems := make([]root.Object, len(b.branches)) 270 for i, v := range b.branches { 271 elems[i] = v 272 } 273 branches.SetElems(elems) 274 } 275 if n, err := branches.MarshalROOT(w); err != nil { 276 return n, err 277 } 278 } 279 { 280 leaves := rcont.NewObjArray() 281 if len(b.leaves) > 0 { 282 elems := make([]root.Object, len(b.leaves)) 283 for i, v := range b.leaves { 284 elems[i] = v 285 } 286 leaves.SetElems(elems) 287 } 288 if n, err := leaves.MarshalROOT(w); err != nil { 289 return n, err 290 } 291 } 292 { 293 baskets := rcont.NewObjArray() 294 if len(b.baskets) > 0 { 295 elems := make([]root.Object, len(b.baskets)) 296 for i := range b.baskets { 297 elems[i] = &b.baskets[i] 298 } 299 baskets.SetElems(elems) 300 } 301 if n, err := baskets.MarshalROOT(w); err != nil { 302 return n, err 303 } 304 baskets.SetElems(nil) 305 } 306 307 { 308 sli := b.basketBytes[:b.writeBasket] 309 w.WriteI8(1) 310 w.WriteArrayI32(sli) 311 if n := b.maxBaskets - len(sli); n > 0 { 312 // fill up with zeros. 313 w.WriteArrayI32(make([]int32, n)) 314 } 315 } 316 317 { 318 sli := b.basketEntry[:b.writeBasket+1] 319 w.WriteI8(1) 320 w.WriteArrayI64(sli) 321 if n := b.maxBaskets - len(sli); n > 0 { 322 // fill up with zeros. 323 w.WriteArrayI64(make([]int64, n)) 324 } 325 } 326 327 { 328 sli := b.basketSeek[:b.writeBasket] 329 w.WriteI8(1) 330 w.WriteArrayI64(sli) 331 if n := b.maxBaskets - len(sli); n > 0 { 332 // fill up with zeros. 333 w.WriteArrayI64(make([]int64, n)) 334 } 335 } 336 337 w.WriteString(b.fname) 338 339 return w.SetHeader(hdr) 340 } 341 342 // ROOTUnmarshaler is the interface implemented by an object that can 343 // unmarshal itself from a ROOT buffer 344 func (b *tbranch) UnmarshalROOT(r *rbytes.RBuffer) error { 345 if r.Err() != nil { 346 return r.Err() 347 } 348 349 hdr := r.ReadHeader(b.Class(), b.RVersion()) 350 351 b.tree = nil 352 b.ctx.bk = nil 353 b.ctx.entry = -1 354 b.ctx.first = -1 355 b.ctx.next = -1 356 357 const minVers = 6 358 switch { 359 case hdr.Vers >= 10: 360 361 r.ReadObject(&b.named) 362 r.ReadObject(&b.attfill) 363 364 b.compress = int(r.ReadI32()) 365 b.basketSize = int(r.ReadI32()) 366 b.entryOffsetLen = int(r.ReadI32()) 367 b.writeBasket = int(r.ReadI32()) 368 b.entryNumber = r.ReadI64() 369 if hdr.Vers >= 13 { 370 if err := b.iobits.UnmarshalROOT(r); err != nil { 371 return err 372 } 373 } 374 b.offset = int(r.ReadI32()) 375 b.maxBaskets = int(r.ReadI32()) 376 b.splitLevel = int(r.ReadI32()) 377 b.entries = r.ReadI64() 378 if hdr.Vers >= 11 { 379 b.firstEntry = r.ReadI64() 380 } 381 b.totBytes = r.ReadI64() 382 b.zipBytes = r.ReadI64() 383 384 { 385 var branches rcont.ObjArray 386 if err := branches.UnmarshalROOT(r); err != nil { 387 return err 388 } 389 b.branches = make([]Branch, branches.Last()+1) 390 for i := range b.branches { 391 br := branches.At(i).(Branch) 392 b.branches[i] = br 393 } 394 } 395 396 { 397 var leaves rcont.ObjArray 398 if err := leaves.UnmarshalROOT(r); err != nil { 399 return err 400 } 401 b.leaves = make([]Leaf, leaves.Last()+1) 402 for i := range b.leaves { 403 leaf := leaves.At(i).(Leaf) 404 leaf.setBranch(b) 405 b.leaves[i] = leaf 406 } 407 } 408 { 409 var baskets rcont.ObjArray 410 if err := baskets.UnmarshalROOT(r); err != nil { 411 return err 412 } 413 414 b.baskets = make([]Basket, baskets.Last()+1) 415 for i := range b.baskets { 416 bkt := baskets.At(i) 417 // FIXME(sbinet) check why some are nil 418 if bkt == nil { 419 continue 420 } 421 bk := bkt.(*Basket) 422 b.baskets[i] = *bk 423 } 424 } 425 426 b.basketBytes = nil 427 b.basketEntry = nil 428 b.basketSeek = nil 429 430 /*isArray*/ 431 _ = r.ReadI8() 432 b.basketBytes = make([]int32, b.maxBaskets) 433 r.ReadArrayI32(b.basketBytes) 434 b.basketBytes = b.basketBytes[:b.writeBasket:b.writeBasket] 435 436 /*isArray*/ 437 _ = r.ReadI8() 438 b.basketEntry = make([]int64, b.maxBaskets) 439 r.ReadArrayI64(b.basketEntry) 440 b.basketEntry = b.basketEntry[: b.writeBasket+1 : b.writeBasket+1] 441 442 /*isArray*/ 443 _ = r.ReadI8() 444 b.basketSeek = make([]int64, b.maxBaskets) 445 r.ReadArrayI64(b.basketSeek) 446 b.basketSeek = b.basketSeek[:b.writeBasket:b.writeBasket] 447 448 b.fname = r.ReadString() 449 450 case hdr.Vers >= 6: 451 r.ReadObject(&b.named) 452 453 if hdr.Vers > 7 { 454 r.ReadObject(&b.attfill) 455 } 456 457 b.compress = int(r.ReadI32()) 458 b.basketSize = int(r.ReadI32()) 459 b.entryOffsetLen = int(r.ReadI32()) 460 b.writeBasket = int(r.ReadI32()) 461 b.entryNumber = int64(r.ReadI32()) 462 b.offset = int(r.ReadI32()) 463 b.maxBaskets = int(r.ReadI32()) 464 if hdr.Vers > 6 { 465 b.splitLevel = int(r.ReadI32()) 466 } 467 b.entries = int64(r.ReadF64()) 468 b.totBytes = int64(r.ReadF64()) 469 b.zipBytes = int64(r.ReadF64()) 470 471 { 472 var branches rcont.ObjArray 473 if err := branches.UnmarshalROOT(r); err != nil { 474 return err 475 } 476 b.branches = make([]Branch, branches.Last()+1) 477 for i := range b.branches { 478 br := branches.At(i).(Branch) 479 b.branches[i] = br 480 } 481 } 482 483 { 484 var leaves rcont.ObjArray 485 if err := leaves.UnmarshalROOT(r); err != nil { 486 return err 487 } 488 b.leaves = make([]Leaf, leaves.Last()+1) 489 for i := range b.leaves { 490 leaf := leaves.At(i).(Leaf) 491 leaf.setBranch(b) 492 b.leaves[i] = leaf 493 } 494 } 495 { 496 var baskets rcont.ObjArray 497 if err := baskets.UnmarshalROOT(r); err != nil { 498 return err 499 } 500 b.baskets = make([]Basket, baskets.Last()+1) 501 for i := range b.baskets { 502 bkt := baskets.At(i) 503 // FIXME(sbinet) check why some are nil 504 if bkt == nil { 505 continue 506 } 507 bk := bkt.(*Basket) 508 b.baskets[i] = *bk 509 } 510 } 511 512 b.basketBytes = nil 513 b.basketEntry = nil 514 b.basketSeek = nil 515 516 /*isArray*/ 517 _ = r.ReadI8() 518 b.basketBytes = make([]int32, b.maxBaskets) 519 r.ReadArrayI32(b.basketBytes) 520 521 /*isArray*/ 522 _ = r.ReadI8() 523 { 524 slice := make([]int32, b.maxBaskets) 525 r.ReadArrayI32(slice) 526 b.basketEntry = make([]int64, len(slice)) 527 for i, v := range slice { 528 b.basketEntry[i] = int64(v) 529 } 530 } 531 532 switch r.ReadI8() { 533 case 2: 534 b.basketSeek = make([]int64, b.maxBaskets) 535 r.ReadArrayI64(b.basketSeek) 536 default: 537 slice := make([]int32, b.maxBaskets) 538 r.ReadArrayI32(slice) 539 b.basketSeek = make([]int64, len(slice)) 540 for i, v := range slice { 541 b.basketSeek[i] = int64(v) 542 } 543 } 544 545 b.fname = r.ReadString() 546 547 default: 548 panic(fmt.Errorf("rtree: too old TBranch version (%d<%d)", hdr.Vers, minVers)) 549 } 550 551 if b.splitLevel == 0 && len(b.branches) > 0 { 552 b.splitLevel = 1 553 } 554 555 r.CheckHeader(hdr) 556 return r.Err() 557 } 558 559 func (b *tbranch) loadEntry(ientry int64) error { 560 var err error 561 562 if len(b.basketBytes) == 0 { 563 return nil 564 } 565 566 err = b.loadBasket(ientry) 567 if err != nil { 568 return err 569 } 570 b.firstEntry = b.ctx.first 571 572 jentry := ientry - b.ctx.first 573 switch len(b.leaves) { 574 case 1: 575 err = b.ctx.bk.loadLeaf(jentry, b.leaves[0]) 576 if err != nil { 577 return err 578 } 579 default: 580 for _, leaf := range b.leaves { 581 err = b.ctx.bk.loadLeaf(jentry, leaf) 582 if err != nil { 583 return err 584 } 585 } 586 } 587 588 return nil 589 } 590 591 func (b *tbranch) loadBasket(entry int64) error { 592 ib := b.findBasketIndex(entry) 593 if ib < 0 { 594 return fmt.Errorf("rtree: no basket for entry %d", entry) 595 } 596 var ( 597 err error 598 bufsz = int(b.basketBytes[ib]) 599 seek = b.basketSeek[ib] 600 f = b.tree.getFile() 601 ) 602 b.ctx.id = ib 603 b.ctx.entry = entry 604 b.ctx.next = b.basketEntry[ib+1] 605 b.ctx.first = b.basketEntry[ib] 606 if ib < len(b.baskets) { 607 b.ctx.bk = &b.baskets[ib] 608 if b.ctx.bk.rbuf == nil { 609 err = b.ctx.inflate(bufsz, seek, f) 610 if err != nil { 611 return fmt.Errorf("rtree: could not inflate basket: %w", err) 612 } 613 614 return b.setupBasket(&b.ctx, entry) 615 } 616 return nil 617 } 618 619 b.baskets = append(b.baskets, Basket{}) 620 b.ctx.bk = &b.baskets[len(b.baskets)-1] 621 err = b.ctx.inflate(bufsz, seek, f) 622 if err != nil { 623 return fmt.Errorf("rtree: could not inflate basket: %w", err) 624 } 625 return b.setupBasket(&b.ctx, entry) 626 } 627 628 func (b *tbranch) findBasketIndex(entry int64) int { 629 switch { 630 case entry == 0: 631 return 0 632 case b.ctx.first <= entry && entry < b.ctx.next: 633 return b.ctx.id 634 } 635 /* 636 // binary search is not efficient for small slices (like basketEntry) 637 // TODO(sbinet): test at which length of basketEntry it starts to be efficient. 638 entries := b.basketEntry[1:] 639 i := sort.Search(len(entries), func(i int) bool { return entries[i] >= entry }) 640 if b.basketEntry[i+1] == entry { 641 return i + 1 642 } 643 return i 644 */ 645 646 for i := b.ctx.id; i < len(b.basketEntry); i++ { 647 v := b.basketEntry[i] 648 if v > entry && v > 0 { 649 return i - 1 650 } 651 } 652 if entry == b.basketEntry[len(b.basketEntry)-1] { 653 return -2 // len(b.basketEntry) - 1 654 } 655 return -1 656 } 657 658 func (b *tbranch) setupBasket(ctx *basketCtx, entry int64) error { 659 ib := ctx.id 660 switch ctx.keylen { 661 case 0: // FIXME(sbinet): from trial and error. check this is ok for all cases 662 b.basketEntry[ib] = 0 663 b.basketEntry[ib+1] = int64(ctx.bk.nevbuf) 664 665 default: 666 if b.entryOffsetLen <= 0 { 667 return nil 668 } 669 670 last := int64(ctx.bk.last) 671 ctx.bk.rbuf.SetPos(last) 672 n := int(ctx.bk.rbuf.ReadI32()) 673 ctx.bk.offsets = rbytes.ResizeI32(ctx.bk.offsets, n) 674 ctx.bk.rbuf.ReadArrayI32(ctx.bk.offsets) 675 if err := ctx.bk.rbuf.Err(); err != nil { 676 return err 677 } 678 } 679 680 return nil 681 } 682 683 func (b *tbranch) setStreamer(s rbytes.StreamerInfo, ctx rbytes.StreamerInfoContext) { 684 // no op 685 } 686 687 func (b *tbranch) setStreamerElement(s rbytes.StreamerElement, ctx rbytes.StreamerInfoContext) { 688 // no op 689 } 690 691 func (b *tbranch) createNewBasket() { 692 cycle := int16(b.writeBasket) + 1 693 bk := newBasketFrom(b.tree, b, cycle, b.basketSize, b.entryOffsetLen) 694 b.ctx.bk = &bk 695 if n := b.writeBasket; n > b.maxBaskets { 696 b.maxBaskets = n 697 } 698 } 699 700 func (b *tbranch) write() (int, error) { 701 b.entries++ 702 b.entryNumber++ 703 704 szOld := b.ctx.bk.wbuf.Len() 705 b.ctx.bk.update(szOld) 706 _, err := b.writeToBuffer(b.ctx.bk.wbuf) 707 szNew := b.ctx.bk.wbuf.Len() 708 n := int(szNew - szOld) 709 if err != nil { 710 return n, fmt.Errorf("could not write to buffer (branch=%q): %w", b.Name(), err) 711 } 712 if n > b.ctx.bk.nevsize { 713 b.ctx.bk.nevsize = n 714 } 715 716 // FIXME(sbinet): harmonize or drive via "auto-flush" ? 717 if szNew+int64(n) >= int64(b.basketSize) { 718 err = b.flush() 719 if err != nil { 720 return n, fmt.Errorf("could not flush branch (auto-flush): %w", err) 721 } 722 723 b.createNewBasket() 724 } 725 return n, nil 726 } 727 728 func (b *tbranch) writeToBuffer(w *rbytes.WBuffer) (int, error) { 729 var tot int 730 for i, leaf := range b.leaves { 731 n, err := leaf.writeToBuffer(w) 732 if err != nil { 733 return tot, fmt.Errorf("could not write leaf[%d] name=%q of branch %q: %w", i, leaf.Name(), b.Name(), err) 734 } 735 tot += n 736 } 737 return tot, nil 738 } 739 740 func (b *tbranch) flush() error { 741 for i, sub := range b.branches { 742 err := sub.flush() 743 if err != nil { 744 return fmt.Errorf("could not flush subbranch[%d]=%q of branch %q: %w", i, sub.Name(), b.Name(), err) 745 } 746 } 747 748 f := b.tree.getFile() 749 totBytes, zipBytes, err := b.ctx.bk.writeFile(f, int32(b.compress)) 750 if err != nil { 751 return fmt.Errorf("could not marshal basket[%d] (branch=%q): %w", b.writeBasket, b.Name(), err) 752 } 753 b.totBytes += totBytes 754 b.zipBytes += zipBytes 755 756 b.basketBytes = append(b.basketBytes, b.ctx.bk.key.Nbytes()) 757 b.basketEntry = append(b.basketEntry, b.entryNumber) 758 b.basketSeek = append(b.basketSeek, b.ctx.bk.key.SeekKey()) 759 b.writeBasket++ 760 b.ctx.bk = nil 761 762 return nil 763 } 764 765 // tbranchObject is a Branch for objects. 766 type tbranchObject struct { 767 tbranch 768 class string // class name of referenced object 769 } 770 771 func (b *tbranchObject) RVersion() int16 { 772 return rvers.BranchObject 773 } 774 775 func (b *tbranchObject) Class() string { 776 return "TBranchObject" 777 } 778 779 func (b *tbranchObject) MarshalROOT(w *rbytes.WBuffer) (int, error) { 780 if w.Err() != nil { 781 return 0, w.Err() 782 } 783 784 hdr := w.WriteHeader(b.Class(), b.RVersion()) 785 w.WriteObject(&b.tbranch) 786 w.WriteString(b.class) 787 788 return w.SetHeader(hdr) 789 } 790 791 // ROOTUnmarshaler is the interface implemented by an object that can 792 // unmarshal itself from a ROOT buffer 793 func (b *tbranchObject) UnmarshalROOT(r *rbytes.RBuffer) error { 794 if r.Err() != nil { 795 return r.Err() 796 } 797 798 hdr := r.ReadHeader(b.Class(), b.RVersion()) 799 800 if hdr.Vers < 1 { 801 r.SetErr(fmt.Errorf("rtree: TBranchObject version too old (%d < 8)", hdr.Vers)) 802 return r.Err() 803 } 804 805 r.ReadObject(&b.tbranch) 806 807 for _, leaf := range b.leaves { 808 switch leaf := leaf.(type) { 809 case *tleaf: 810 leaf.branch = b 811 case *tleafObject: 812 leaf.branch = b 813 case *tleafElement: 814 leaf.branch = b 815 } 816 } 817 818 b.class = r.ReadString() 819 820 r.CheckHeader(hdr) 821 return r.Err() 822 } 823 824 // tbranchElement is a Branch for objects. 825 type tbranchElement struct { 826 tbranch 827 class string // class name of referenced object 828 parent string // name of parent class 829 clones string // named of class in TClonesArray (if any) 830 chksum uint32 // checksum of class 831 clsver uint16 // version number of class 832 id int32 // element serial number in fInfo 833 btype int32 // branch type 834 stype int32 // branch streamer type 835 max int32 // maximum entries for a TClonesArray or variable array 836 stltyp int32 // STL container type 837 bcount1 *tbranchElement // pointer to primary branchcount branch 838 bcount2 *tbranchElement // pointer to secondary branchcount branch 839 840 streamer rbytes.StreamerInfo 841 estreamer rbytes.StreamerElement 842 } 843 844 func newBranchElementFromWVar(w *wtree, base *tbranch, wvar WriteVar, parent Branch, lvl int, cfg wopt) (Branch, error) { 845 var ( 846 rv = reflect.ValueOf(wvar.Value) 847 streamer = rdict.StreamerOf(w.ttree.f, reflect.Indirect(rv).Type()) 848 pclass = "" 849 ) 850 851 if parent, ok := parent.(*tbranchElement); ok { 852 pclass = parent.class 853 } 854 855 b := &tbranchElement{ 856 tbranch: *base, 857 class: streamer.Name(), 858 parent: pclass, 859 chksum: uint32(streamer.CheckSum()), 860 clsver: uint16(streamer.ClassVersion()), 861 id: -1, 862 btype: 0, 863 stype: -1, 864 streamer: streamer, 865 } 866 switch reflect.TypeOf(wvar.Value).Elem().Kind() { 867 case reflect.Struct: 868 b.tbranch.entryOffsetLen = 20 869 case reflect.Slice: 870 b.tbranch.entryOffsetLen = 400 871 } 872 873 w.ttree.f.RegisterStreamer(b.streamer) 874 875 _, err := newLeafFromWVar(w, b, wvar, lvl, cfg) 876 if err != nil { 877 return nil, err 878 } 879 b.named.SetTitle(wvar.Name) 880 b.createNewBasket() 881 return b, nil 882 } 883 884 func (b *tbranchElement) RVersion() int16 { 885 return rvers.BranchElement 886 } 887 888 func (b *tbranchElement) Class() string { 889 return "TBranchElement" 890 } 891 892 func (b *tbranchElement) MarshalROOT(w *rbytes.WBuffer) (int, error) { 893 if w.Err() != nil { 894 return 0, w.Err() 895 } 896 897 hdr := w.WriteHeader(b.Class(), b.RVersion()) 898 w.WriteObject(&b.tbranch) 899 w.WriteString(b.class) 900 w.WriteString(b.parent) 901 w.WriteString(b.clones) 902 w.WriteU32(b.chksum) 903 w.WriteU16(b.clsver) 904 w.WriteI32(b.id) 905 w.WriteI32(b.btype) 906 w.WriteI32(b.stype) 907 w.WriteI32(b.max) 908 909 { 910 var obj root.Object 911 if b.bcount1 != nil { 912 obj = b.bcount1 913 } 914 w.WriteObjectAny(obj) 915 } 916 { 917 var obj root.Object 918 if b.bcount2 != nil { 919 obj = b.bcount2 920 } 921 w.WriteObjectAny(obj) 922 } 923 924 return w.SetHeader(hdr) 925 } 926 927 // ROOTUnmarshaler is the interface implemented by an object that can 928 // unmarshal itself from a ROOT buffer 929 func (b *tbranchElement) UnmarshalROOT(r *rbytes.RBuffer) error { 930 if r.Err() != nil { 931 return r.Err() 932 } 933 934 hdr := r.ReadHeader(b.Class(), b.RVersion()) 935 936 if hdr.Vers < 1 { 937 r.SetErr(fmt.Errorf("rtree: TBranchElement version too old (%d < 8)", hdr.Vers)) 938 return r.Err() 939 } 940 941 r.ReadObject(&b.tbranch) 942 943 for _, leaf := range b.leaves { 944 switch leaf := leaf.(type) { 945 case *tleaf: 946 leaf.branch = b 947 case *tleafObject: 948 leaf.branch = b 949 case *tleafElement: 950 leaf.branch = b 951 } 952 } 953 954 b.class = r.ReadString() 955 if hdr.Vers > 1 { 956 b.parent = r.ReadString() 957 b.clones = r.ReadString() 958 b.chksum = r.ReadU32() 959 } 960 if hdr.Vers >= 10 { 961 b.clsver = r.ReadU16() 962 } else { 963 b.clsver = uint16(r.ReadU32()) 964 } 965 b.id = r.ReadI32() 966 b.btype = r.ReadI32() 967 b.stype = r.ReadI32() 968 if hdr.Vers > 1 { 969 b.max = r.ReadI32() 970 971 bcount1 := r.ReadObjectAny() 972 if bcount1 != nil { 973 b.bcount1 = bcount1.(*tbranchElement) 974 } 975 976 bcount2 := r.ReadObjectAny() 977 if bcount2 != nil { 978 b.bcount2 = bcount2.(*tbranchElement) 979 } 980 } 981 982 r.CheckHeader(hdr) 983 return r.Err() 984 } 985 986 func (b *tbranchElement) loadEntry(ientry int64) error { 987 if len(b.branches) > 0 { 988 for _, sub := range b.branches { 989 err := sub.loadEntry(ientry) 990 if err != nil { 991 return err 992 } 993 } 994 } 995 return b.tbranch.loadEntry(ientry) 996 } 997 998 func (b *tbranchElement) setupReadStreamer(sictx rbytes.StreamerInfoContext) error { 999 streamer, err := sictx.StreamerInfo(b.class, int(b.clsver)) 1000 if err != nil { 1001 streamer, err = sictx.StreamerInfo(b.class, -1) 1002 if err != nil { 1003 return fmt.Errorf("rtree: no StreamerInfo for class=%q version=%d checksum=%d", b.class, b.clsver, b.chksum) 1004 } 1005 } 1006 b.streamer = streamer 1007 1008 for _, leaf := range b.tbranch.leaves { 1009 leaf, ok := leaf.(*tleafElement) 1010 if !ok { 1011 continue 1012 } 1013 leaf.streamers = b.streamer.Elements() 1014 } 1015 1016 for _, sub := range b.branches { 1017 sub, ok := sub.(*tbranchElement) 1018 if !ok { 1019 continue 1020 } 1021 err := sub.setupReadStreamer(sictx) 1022 if err != nil { 1023 return err 1024 } 1025 } 1026 1027 return nil 1028 } 1029 1030 func (b *tbranchElement) GoType() reflect.Type { 1031 typ, err := rdict.TypeFromSI(b.tree.getFile(), b.streamer) 1032 if err != nil { 1033 panic(err) 1034 } 1035 return typ 1036 } 1037 1038 func (b *tbranchElement) setStreamer(s rbytes.StreamerInfo, ctx rbytes.StreamerInfoContext) { 1039 b.streamer = s 1040 if len(b.tbranch.leaves) == 1 { 1041 typ, err := rdict.TypeFromSI(ctx, s) 1042 if err != nil { 1043 panic(err) 1044 } 1045 tle := b.tbranch.leaves[0].(*tleafElement) 1046 tle.streamers = s.Elements() 1047 tle.src = reflect.New(typ).Elem() 1048 } 1049 err := b.setupReadStreamer(ctx) 1050 if err != nil { 1051 panic(err) 1052 } 1053 } 1054 1055 func (b *tbranchElement) setStreamerElement(se rbytes.StreamerElement, ctx rbytes.StreamerInfoContext) { 1056 b.estreamer = se 1057 if len(b.Leaves()) == 1 { 1058 tle := b.Leaves()[0].(*tleafElement) 1059 tle.streamers = []rbytes.StreamerElement{se} 1060 typ, err := rdict.TypeFromSE(ctx, se) 1061 if err != nil { 1062 panic(err) 1063 } 1064 tle.src = reflect.New(typ).Elem() 1065 } 1066 err := b.setupReadStreamer(ctx) 1067 if err != nil { 1068 panic(err) 1069 } 1070 } 1071 1072 func (b *tbranchElement) write() (int, error) { 1073 b.entries++ 1074 b.entryNumber++ 1075 1076 szOld := b.ctx.bk.wbuf.Len() 1077 b.ctx.bk.update(szOld) 1078 _, err := b.writeToBuffer(b.ctx.bk.wbuf) 1079 szNew := b.ctx.bk.wbuf.Len() 1080 n := int(szNew - szOld) 1081 if err != nil { 1082 return n, fmt.Errorf("could not write to buffer (branch=%q): %w", b.Name(), err) 1083 } 1084 if n > b.ctx.bk.nevsize { 1085 b.ctx.bk.grow(n) 1086 } 1087 1088 // FIXME(sbinet): harmonize or drive via "auto-flush" ? 1089 if szNew+int64(n) >= int64(b.basketSize) { 1090 err = b.flush() 1091 if err != nil { 1092 return n, fmt.Errorf("could not flush branch (auto-flush): %w", err) 1093 } 1094 1095 b.createNewBasket() 1096 } 1097 return n, nil 1098 } 1099 1100 func (b *tbranchElement) writeToBuffer(w *rbytes.WBuffer) (int, error) { 1101 var tot int 1102 for i, leaf := range b.leaves { 1103 n, err := leaf.writeToBuffer(w) 1104 if err != nil { 1105 return tot, fmt.Errorf("could not write leaf[%d] name=%q of branch %q: %w", i, leaf.Name(), b.Name(), err) 1106 } 1107 tot += n 1108 } 1109 return tot, nil 1110 } 1111 1112 func btopOf(b Branch) Branch { 1113 if b == nil { 1114 return nil 1115 } 1116 const max = 1<<31 - 1 1117 for range max { 1118 switch bb := b.(type) { 1119 case *tbranch: 1120 if bb.bup == nil { 1121 return bb 1122 } 1123 b = bb.bup 1124 case *tbranchElement: 1125 if bb.bup == nil { 1126 return bb 1127 } 1128 b = bb.bup 1129 default: 1130 panic(fmt.Errorf("rtree: unknown branch type %T", b)) 1131 } 1132 } 1133 panic("impossible") 1134 } 1135 1136 func init() { 1137 { 1138 f := func() reflect.Value { 1139 o := &tbranch{} 1140 return reflect.ValueOf(o) 1141 } 1142 rtypes.Factory.Add("TBranch", f) 1143 } 1144 { 1145 f := func() reflect.Value { 1146 o := &tbranchObject{} 1147 return reflect.ValueOf(o) 1148 } 1149 rtypes.Factory.Add("TBranchObject", f) 1150 } 1151 { 1152 f := func() reflect.Value { 1153 o := &tbranchElement{} 1154 return reflect.ValueOf(o) 1155 } 1156 rtypes.Factory.Add("TBranchElement", f) 1157 } 1158 } 1159 1160 type basketCtx struct { 1161 id int // current basket number when reading 1162 entry int64 // current entry number when reading 1163 first int64 // first entry in the current basket 1164 next int64 // next entry that will require us to go to TBranchElement next basket 1165 bk *Basket // pointer to the current basket 1166 buf []byte // scratch space for the current basket 1167 1168 keylen uint32 1169 } 1170 1171 func (ctx *basketCtx) inflate(bufsz int, seek int64, f *riofs.File) error { 1172 ctx.buf = rbytes.ResizeU8(ctx.buf, bufsz) 1173 ctx.bk.key.SetFile(f) 1174 ctx.keylen = 0 1175 1176 var ( 1177 bk = ctx.bk 1178 buf = ctx.buf[:bufsz] 1179 sictx = f 1180 err error 1181 ) 1182 1183 switch { 1184 case len(buf) == 0 && ctx.bk != nil: // FIXME(sbinet): from trial and error. check this is ok for all cases 1185 1186 default: 1187 _, err = f.ReadAt(buf, seek) 1188 if err != nil { 1189 return fmt.Errorf("rtree: could not read basket buffer from file: %w", err) 1190 } 1191 1192 err = bk.UnmarshalROOT(rbytes.NewRBuffer(buf, nil, 0, sictx)) 1193 if err != nil { 1194 return fmt.Errorf("rtree: could not unmarshal basket buffer from file: %w", err) 1195 } 1196 1197 ctx.keylen = uint32(bk.key.KeyLen()) 1198 } 1199 1200 buf = rbytes.ResizeU8(buf, int(bk.key.ObjLen())) 1201 _, err = bk.key.Load(buf) 1202 if err != nil { 1203 return err 1204 } 1205 1206 bk.rbuf = rbytes.NewRBuffer(buf, nil, ctx.keylen, sictx) 1207 return nil 1208 } 1209 1210 var ( 1211 _ root.Object = (*tbranch)(nil) 1212 _ root.Named = (*tbranch)(nil) 1213 _ Branch = (*tbranch)(nil) 1214 _ rbytes.Marshaler = (*tbranch)(nil) 1215 _ rbytes.Unmarshaler = (*tbranch)(nil) 1216 1217 _ root.Object = (*tbranchObject)(nil) 1218 _ root.Named = (*tbranchObject)(nil) 1219 _ Branch = (*tbranchObject)(nil) 1220 _ rbytes.Marshaler = (*tbranchObject)(nil) 1221 _ rbytes.Unmarshaler = (*tbranchObject)(nil) 1222 1223 _ root.Object = (*tbranchElement)(nil) 1224 _ root.Named = (*tbranchElement)(nil) 1225 _ Branch = (*tbranchElement)(nil) 1226 _ rbytes.Marshaler = (*tbranchElement)(nil) 1227 _ rbytes.Unmarshaler = (*tbranchElement)(nil) 1228 )