github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/test_framework/mockDirectoryWrapper.go (about) 1 package test_framework 2 3 import ( 4 "errors" 5 "fmt" 6 "github.com/balzaczyy/golucene/core/index" 7 "github.com/balzaczyy/golucene/core/store" 8 "github.com/balzaczyy/golucene/core/util" 9 . "github.com/balzaczyy/golucene/test_framework/util" 10 "io" 11 "log" 12 "math/rand" 13 "os" 14 "reflect" 15 "runtime" 16 "runtime/debug" 17 "sort" 18 // "strings" 19 "sync" 20 ) 21 22 // store/MockDirectoryWrapper.java 23 24 /* 25 This is a Directory wrapper that adds methods intended to be used 26 only by unit tests. It also adds a number of fatures useful for 27 testing: 28 29 1. Instances created by newDirectory() are tracked to ensure they are 30 closed by the test. 31 2. When a MockDirectoryWrapper is closed, it returns an error if it 32 has any open files against it (with a stacktrace indicating where 33 they were opened from) 34 3. When a MockDirectoryWrapper is closed, it runs CheckIndex to test 35 if the index was corrupted. 36 4. MockDirectoryWrapper simulates some "features" of Windows, such as 37 refusing to write/delete to open files. 38 */ 39 type MockDirectoryWrapper struct { 40 *BaseDirectoryWrapperImpl 41 sync.Locker // simulate Java's synchronized keyword 42 myLockFactory store.LockFactory // overrides LockFactory 43 44 isLocked bool // workaround re-entrant lock 45 46 maxSize int64 47 48 // Max actual bytes used. This is set by MockRAMOutputStream 49 maxUsedSize int64 50 randomErrorRate float64 51 randomErrorRateOnOpen float64 52 randomState *rand.Rand 53 noDeleteOpenFile bool 54 preventDoubleWrite bool 55 trackDiskUsage bool 56 wrapLockFactory bool 57 unSyncedFiles map[string]bool 58 createdFiles map[string]bool 59 openFilesForWrite map[string]bool 60 openLocks map[string]bool // synchronized 61 openLocksLock sync.Locker 62 crashed bool // volatile 63 throttledOutput *ThrottledIndexOutput 64 throttling Throttling 65 66 inputCloneCount int32 // atomic 67 68 // use this for tracking files for crash. 69 // additionally: provides debugging information in case you leave one open 70 openFileHandles map[io.Closer]error // synchronized 71 72 // NOTE: we cannot intialize the map here due to the order in which our 73 // constructor actually does this member initialization vs when it calls 74 // super. It seems like super is called, then our members are initialzed. 75 // 76 // Ian: it's not the case for golucene BUT I have no idea why it stays... 77 openFiles map[string]int 78 79 // Only tracked if noDeleteOpenFile is true: if an attempt is made to delete 80 // an open file, we entroll it here. 81 openFilesDeleted map[string]bool 82 83 failOnCreateOutput bool 84 failOnOpenInput bool 85 assertNoUnreferencedFilesOnClose bool 86 87 failures []*Failure 88 } 89 90 func (mdw *MockDirectoryWrapper) init() { 91 if mdw.openFiles == nil { 92 mdw.openFiles = make(map[string]int) 93 mdw.openFilesDeleted = make(map[string]bool) 94 } 95 96 if mdw.createdFiles == nil { 97 mdw.createdFiles = make(map[string]bool) 98 } 99 if mdw.unSyncedFiles == nil { 100 mdw.unSyncedFiles = make(map[string]bool) 101 } 102 } 103 104 func NewMockDirectoryWrapper(random *rand.Rand, delegate store.Directory) *MockDirectoryWrapper { 105 ans := &MockDirectoryWrapper{ 106 noDeleteOpenFile: true, 107 preventDoubleWrite: true, 108 trackDiskUsage: false, 109 wrapLockFactory: true, 110 openFilesForWrite: make(map[string]bool), 111 openLocks: make(map[string]bool), 112 openLocksLock: &sync.Mutex{}, 113 throttling: THROTTLING_SOMETIMES, 114 inputCloneCount: 0, 115 openFileHandles: make(map[io.Closer]error), 116 failOnCreateOutput: true, 117 failOnOpenInput: true, 118 assertNoUnreferencedFilesOnClose: true, 119 } 120 ans.BaseDirectoryWrapperImpl = NewBaseDirectoryWrapper(delegate) 121 ans.Locker = &sync.Mutex{} 122 // must make a private random since our methods are called from different 123 // methods; else test failures may not be reproducible from the original 124 // seed 125 ans.randomState = rand.New(rand.NewSource(random.Int63())) 126 ans.throttledOutput = NewThrottledIndexOutput( 127 MBitsToBytes(40+ans.randomState.Intn(10)), 5+ans.randomState.Int63n(5), nil) 128 // force wrapping of LockFactory 129 ans.myLockFactory = newMockLockFactoryWrapper(ans, delegate.LockFactory()) 130 ans.init() 131 return ans 132 } 133 134 // Controlling hard disk throttling 135 // Set via setThrottling() 136 // WARNING: can make tests very slow. 137 type Throttling int 138 139 const ( 140 // always emulate a slow hard disk. Cold be very slow! 141 THROTTLING_ALWAYS = Throttling(1) 142 // sometimes (2% of the time) emulate a slow hard disk. 143 THROTTLING_SOMETIMES = Throttling(2) 144 // never throttle output 145 THROTTLING_NEVER = Throttling(3) 146 ) 147 148 func (mdw *MockDirectoryWrapper) SetThrottling(throttling Throttling) { 149 mdw.throttling = throttling 150 } 151 152 /* 153 Returns true if delegate must sync its files. Currently, only 154 NRTCachingDirectory requires sync'ing its files because otherwise 155 they are cached in an internal RAMDirectory. If other directories 156 requires that too, they should be added to this method. 157 */ 158 func (mdw *MockDirectoryWrapper) mustSync() bool { 159 var delegate = mdw.Directory 160 for { 161 if v, ok := delegate.(*store.RateLimitedDirectoryWrapper); ok { 162 delegate = v.Directory 163 } else if v, ok := delegate.(*store.TrackingDirectoryWrapper); ok { 164 delegate = v.Directory 165 } else { 166 break 167 } 168 } 169 _, ok := delegate.(*store.NRTCachingDirectory) 170 return ok 171 } 172 173 func (w *MockDirectoryWrapper) Sync(names []string) error { 174 w.Lock() // synchronized 175 defer w.Unlock() 176 w.maybeYield() 177 err := w.maybeThrowDeterministicException() 178 if err != nil { 179 return err 180 } 181 if w.crashed { 182 return errors.New("cannot sync after crash") 183 } 184 // don't wear out out hardware so much intests. 185 if Rarely(w.randomState) || w.mustSync() { 186 for _, name := range names { 187 // randomly fail with IOE on any file 188 err = w.maybeThrowIOException(name) 189 if err != nil { 190 return err 191 } 192 err = w.Directory.Sync([]string{name}) 193 if err != nil { 194 return err 195 } 196 delete(w.unSyncedFiles, name) 197 } 198 } else { 199 for _, name := range names { 200 delete(w.unSyncedFiles, name) 201 } 202 } 203 return nil 204 } 205 206 func (w *MockDirectoryWrapper) String() string { 207 // NOTE: do not maybeYield here, since it consumes randomness and 208 // can thus (unexpectedly during debugging) change the behavior of 209 // a seed maybeYield() 210 return fmt.Sprintf("MockDirWrapper(%v)", w.Directory) 211 } 212 213 func (w *MockDirectoryWrapper) sizeInBytes() (int64, error) { 214 w.Lock() 215 defer w.Unlock() 216 217 // v, ok := w.Directory.(*store.RAMDirectory) 218 // if ok { 219 // return v.RamBytesUsed(), nil 220 // } 221 // hack 222 panic("not implemented yet") 223 } 224 225 // Simulates a crash of OS or machine by overwriting unsynced files. 226 func (w *MockDirectoryWrapper) Crash() error { 227 w.Lock() // synchronized 228 defer w.Unlock() 229 return w._crash() 230 } 231 232 func (w *MockDirectoryWrapper) _crash() error { 233 panic("not implemented yet") 234 // w.crashed = true 235 // w.openFiles = make(map[string]int) 236 // w.openFilesForWrite = make(map[string]bool) 237 // w.openFilesDeleted = make(map[string]bool) 238 // files := w.unSyncedFiles 239 // w.unSyncedFiles = make(map[string]bool) 240 // // first force-close all files, so we can corrupt on windows etc. 241 // // clone the file map, as these guys want to remove themselves on close. 242 // m := make(map[io.Closer]error) 243 // for k, v := range w.openFileHandles { 244 // m[k] = v 245 // } 246 // for f, _ := range m { 247 // f.Close() // ignore error 248 // } 249 250 // for name, _ := range files { 251 // var action string 252 // var err error 253 // switch w.randomState.Intn(5) { 254 // case 0: 255 // action = "deleted" 256 // err = w.deleteFile(name, true) 257 // case 1: 258 // action = "zeroes" 259 // // Zero out file entirely 260 // var length int64 261 // length, err = w._fileLength(name) 262 // if err == nil { 263 // zeroes := make([]byte, 256) 264 // var upto int64 = 0 265 // var out store.IndexOutput 266 // out, err = w.BaseDirectoryWrapperImpl.CreateOutput(name, NewDefaultIOContext(w.randomState)) 267 // if err == nil { 268 // for upto < length && err == nil { 269 // limit := length - upto 270 // if int64(len(zeroes)) < limit { 271 // limit = int64(len(zeroes)) 272 // } 273 // err = out.WriteBytes(zeroes[:limit]) 274 // upto += limit 275 // } 276 // if err == nil { 277 // err = out.Close() 278 // } 279 // } 280 // } 281 // case 2: 282 // action = "partially truncated" 283 // // Partially Truncate the file: 284 285 // // First, make temp file and copy only half this file over: 286 // var tempFilename string 287 // for { 288 // tempFilename = fmt.Sprintf("%v", w.randomState.Int()) 289 // if !w.BaseDirectoryWrapperImpl.FileExists(tempFilename) { 290 // break 291 // } 292 // } 293 // var tempOut store.IndexOutput 294 // if tempOut, err = w.BaseDirectoryWrapperImpl.CreateOutput(tempFilename, NewDefaultIOContext(w.randomState)); err == nil { 295 // var ii store.IndexInput 296 // if ii, err = w.BaseDirectoryWrapperImpl.OpenInput(name, NewDefaultIOContext(w.randomState)); err == nil { 297 // if err = tempOut.CopyBytes(ii, ii.Length()/2); err == nil { 298 // if err = tempOut.Close(); err == nil { 299 // if err = ii.Close(); err == nil { 300 // // Delete original and copy bytes back: 301 // if err = w.deleteFile(name, true); err == nil { 302 // var out store.IndexOutput 303 // if out, err = w.BaseDirectoryWrapperImpl.CreateOutput(name, NewDefaultIOContext(w.randomState)); err == nil { 304 // if ii, err = w.BaseDirectoryWrapperImpl.OpenInput(tempFilename, NewDefaultIOContext(w.randomState)); err == nil { 305 // if err = out.CopyBytes(ii, ii.Length()); err == nil { 306 // if err = out.Close(); err == nil { 307 // if err = ii.Close(); err == nil { 308 // err = w.deleteFile(tempFilename, true) 309 // } 310 // } 311 // } 312 // } 313 // } 314 // } 315 // } 316 // } 317 // } 318 // } 319 // } 320 // case 3: 321 // // the file survived intact: 322 // action = "didn't change" 323 // default: 324 // action = "fully truncated" 325 // // totally truncate the file to zero bytes 326 // if err = w.deleteFile(name, true); err == nil { 327 // var out store.IndexOutput 328 // if out, err = w.BaseDirectoryWrapperImpl.CreateOutput(name, NewDefaultIOContext(w.randomState)); err == nil { 329 // if err = out.SetLength(0); err == nil { 330 // err = out.Close() 331 // } 332 // } 333 // } 334 // } 335 // if err != nil { 336 // return err 337 // } 338 // if VERBOSE { 339 // log.Printf("MockDirectoryWrapper: %v unsynced file: %v", action, name) 340 // } 341 // } 342 // return nil 343 } 344 345 func (w *MockDirectoryWrapper) maybeThrowIOException(message string) error { 346 if w.randomState.Float64() < w.randomErrorRate { 347 if message != "" { 348 message = fmt.Sprintf(" (%v)", message) 349 } 350 if VERBOSE { 351 log.Printf("MockDirectoryWrapper: now return random error%v", message) 352 debug.PrintStack() 353 } 354 return errors.New(fmt.Sprintf("a random IO error%v", message)) 355 } 356 return nil 357 } 358 359 func (w *MockDirectoryWrapper) maybeThrowIOExceptionOnOpen(name string) error { 360 if w.randomState.Float64() < w.randomErrorRateOnOpen { 361 if VERBOSE { 362 log.Printf("MockDirectoryWrapper: now return random error during open file=%v", name) 363 debug.PrintStack() 364 } 365 if w.randomState.Intn(2) == 0 { 366 return errors.New(fmt.Sprintf("a random IO error (%v)", name)) 367 } 368 return os.ErrNotExist 369 } 370 return nil 371 } 372 373 func (w *MockDirectoryWrapper) DeleteFile(name string) error { 374 w.maybeYield() 375 return w.deleteFile(name, false) 376 } 377 378 /* 379 sets the cause of the incoming ioe to be the stack trace when the 380 offending file name was opened 381 */ 382 func (w *MockDirectoryWrapper) fillOpenTrace(err error, name string, input bool) error { 383 w.Lock() 384 defer w.Unlock() 385 return w._fillOpenTrace(err, name, input) 386 } 387 388 func (w *MockDirectoryWrapper) _fillOpenTrace(err error, name string, input bool) error { 389 for closer, cause := range w.openFileHandles { 390 v, ok := closer.(*MockIndexInputWrapper) 391 if input && ok && v.name == name { 392 err = mergeError(err, cause) 393 break 394 } else { 395 v2, ok := closer.(*MockIndexOutputWrapper) 396 if !input && ok && v2.name == name { 397 err = mergeError(err, cause) 398 break 399 } 400 } 401 } 402 return err 403 } 404 405 func mergeError(err, err2 error) error { 406 if err == nil { 407 return err2 408 } else { 409 return errors.New(fmt.Sprintf("%v\n %v", err, err2)) 410 } 411 } 412 413 func (w *MockDirectoryWrapper) maybeYield() { 414 if w.randomState.Intn(2) == 0 { 415 runtime.Gosched() 416 } 417 } 418 419 func (w *MockDirectoryWrapper) deleteFile(name string, forced bool) error { 420 if !w.isLocked { 421 w.Lock() // synchronized 422 defer w.Unlock() 423 } 424 425 w.maybeYield() 426 427 err := w.maybeThrowDeterministicException() 428 if err != nil { 429 return err 430 } 431 432 if w.crashed && !forced { 433 return errors.New("cannot delete after crash") 434 } 435 436 if _, ok := w.unSyncedFiles[name]; ok { 437 delete(w.unSyncedFiles, name) 438 } 439 if !forced && w.noDeleteOpenFile { 440 if _, ok := w.openFiles[name]; ok { 441 w.openFilesDeleted[name] = true 442 return w._fillOpenTrace(errors.New(fmt.Sprintf( 443 "MockDirectoryWrapper: file '%v' is still open: cannot delete", 444 name)), name, true) 445 } 446 delete(w.openFilesDeleted, name) 447 } 448 return w.Directory.DeleteFile(name) 449 } 450 451 func (w *MockDirectoryWrapper) CreateOutput(name string, context store.IOContext) (store.IndexOutput, error) { 452 panic("not implemented yet") 453 // if !w.isLocked { 454 // w.Lock() // synchronized 455 // defer w.Unlock() 456 // } 457 458 // err := w.maybeThrowDeterministicException() 459 // if err != nil { 460 // return nil, err 461 // } 462 // err = w.maybeThrowIOExceptionOnOpen(name) 463 // if err != nil { 464 // return nil, err 465 // } 466 // w.maybeYield() 467 // if w.failOnCreateOutput { 468 // if err = w.maybeThrowDeterministicException(); err != nil { 469 // return nil, err 470 // } 471 // } 472 // if w.crashed { 473 // return nil, errors.New("cannot createOutput after crash") 474 // } 475 // w.init() 476 // if _, ok := w.createdFiles[name]; w.preventDoubleWrite && ok && name != "segments.gen" { 477 // return nil, errors.New(fmt.Sprintf("file %v was already written to", name)) 478 // } 479 // if _, ok := w.openFiles[name]; w.noDeleteOpenFile && ok { 480 // return nil, errors.New(fmt.Sprintf("MockDirectoryWraper: file %v is still open: cannot overwrite", name)) 481 // } 482 483 // if w.crashed { 484 // return nil, errors.New("cannot createOutput after crash") 485 // } 486 // w.unSyncedFiles[name] = true 487 // w.createdFiles[name] = true 488 489 // if ramdir, ok := w.Directory.(*store.RAMDirectory); ok { 490 // file := store.NewRAMFile(ramdir) 491 // existing := ramdir.GetRAMFile(name) 492 493 // // Enforce write once: 494 // if existing != nil && name != "segments.gen" && w.preventDoubleWrite { 495 // return nil, errors.New(fmt.Sprintf("file %v already exists", name)) 496 // } else { 497 // if existing != nil { 498 // ramdir.ChangeSize(-existing.SizeInBytes()) 499 // // existing.directory = nil 500 // } 501 // ramdir.PutRAMFile(name, file) 502 // } 503 // } 504 // log.Printf("MDW: create %v", name) 505 // delegateOutput, err := w.Directory.CreateOutput(name, NewIOContext(w.randomState, context)) 506 // if err != nil { 507 // return nil, err 508 // } 509 // assert(delegateOutput != nil) 510 // if w.randomState.Intn(10) == 0 { 511 // // once ina while wrap the IO in a buffered IO with random buffer sizes 512 // delegateOutput = newBufferedIndexOutputWrapper( 513 // 1+w.randomState.Intn(store.DEFAULT_BUFFER_SIZE), delegateOutput) 514 // assert(delegateOutput != nil) 515 // } 516 // io := newMockIndexOutputWrapper(w, name, delegateOutput) 517 // w._addFileHandle(io, name, HANDLE_OUTPUT) 518 // w.openFilesForWrite[name] = true 519 520 // // throttling REALLY slows down tests, so don't do it very often for SOMETIMES 521 // if _, ok := w.Directory.(*store.RateLimitedDirectoryWrapper); w.throttling == THROTTLING_ALWAYS || 522 // (w.throttling == THROTTLING_SOMETIMES && w.randomState.Intn(50) == 0) && !ok { 523 // if VERBOSE { 524 // log.Println(fmt.Sprintf("MockDirectoryWrapper: throttling indexOutpu (%v)", name)) 525 // } 526 // return w.throttledOutput.NewFromDelegate(io), nil 527 // } 528 // return io, nil 529 } 530 531 type Handle int 532 533 const ( 534 HANDLE_INPUT = Handle(1) 535 HANDLE_OUTPUT = Handle(2) 536 HANDLE_SLICE = Handle(3) 537 ) 538 539 func handleName(handle Handle) string { 540 switch handle { 541 case HANDLE_INPUT: 542 return "Input" 543 case HANDLE_OUTPUT: 544 return "Output" 545 case HANDLE_SLICE: 546 return "Slice" 547 } 548 panic("should not be here") 549 } 550 551 func (w *MockDirectoryWrapper) addFileHandle(c io.Closer, name string, handle Handle) { 552 if !w.isLocked { 553 w.Lock() // synchronized 554 defer w.Unlock() 555 } 556 w._addFileHandle(c, name, handle) 557 } 558 559 func (w *MockDirectoryWrapper) _addFileHandle(c io.Closer, name string, handle Handle) { 560 if v, ok := w.openFiles[name]; ok { 561 w.openFiles[name] = v + 1 562 } else { 563 w.openFiles[name] = 1 564 } 565 w.openFileHandles[c] = errors.New(fmt.Sprintf("unclosed Index %v: %v", handleName(handle), name)) 566 } 567 568 func (w *MockDirectoryWrapper) OpenInput(name string, context store.IOContext) (ii store.IndexInput, err error) { 569 panic("not implemented yet") 570 // if !w.isLocked { 571 // w.Lock() // synchronized 572 // defer w.Unlock() 573 // } 574 575 // if err = w.maybeThrowDeterministicException(); err != nil { 576 // return 577 // } 578 // if err = w.maybeThrowIOExceptionOnOpen(name); err != nil { 579 // return 580 // } 581 // w.maybeYield() 582 // if w.failOnOpenInput { 583 // if err = w.maybeThrowDeterministicException(); err != nil { 584 // return 585 // } 586 // } 587 // if !w.Directory.FileExists(name) { 588 // return nil, errors.New(fmt.Sprintf("%v in dir=%v", name, w.Directory)) 589 // } 590 591 // // cannot open a file for input if it's still open for output, 592 // // except for segments.gen and segments_N 593 // if _, ok := w.openFilesForWrite[name]; ok && strings.HasPrefix(name, "segments") { 594 // err = w.fillOpenTrace(errors.New(fmt.Sprintf( 595 // "MockDirectoryWrapper: file '%v' is still open for writing", name)), name, false) 596 // return 597 // } 598 599 // var delegateInput store.IndexInput 600 // delegateInput, err = w.Directory.OpenInput(name, NewIOContext(w.randomState, context)) 601 // if err != nil { 602 // return 603 // } 604 605 // randomInt := w.randomState.Intn(500) 606 // if randomInt == 0 { 607 // if VERBOSE { 608 // log.Printf("MockDirectoryWrapper: using SlowClosingMockIndexInputWrapper for file %v", name) 609 // } 610 // panic("not implemented yet") 611 // } else if randomInt == 1 { 612 // if VERBOSE { 613 // log.Printf("MockDirectoryWrapper: using SlowOpeningMockIndexInputWrapper for file %v", name) 614 // } 615 // panic("not implemented yet") 616 // } else { 617 // ii = newMockIndexInputWrapper(w, name, delegateInput) 618 // } 619 // w._addFileHandle(ii, name, HANDLE_INPUT) 620 // return ii, nil 621 } 622 623 // L594 624 /* 625 Like recomputeSizeInBytes(), but uses actual file lengths rather than 626 buffer allocations (which are quantized up to nearest 627 RAMOutputStream.BUFFER_SIZE (now 1024) bytes). 628 */ 629 func (w *MockDirectoryWrapper) recomputeActualSizeInBytes() (int64, error) { 630 w.Lock() 631 defer w.Unlock() 632 // if _, ok := w.Directory.(store.RAMDirectory); !ok { 633 // return w.sizeInBytes() 634 // } 635 panic("not implemented yet") 636 } 637 638 func (w *MockDirectoryWrapper) Close() error { 639 w.Lock() 640 w.isLocked = true 641 defer func() { 642 w.isLocked = false 643 w.Unlock() 644 }() 645 646 // files that we tried to delete, but couldn't because reader were open 647 // all that matters is that we tried! (they will eventually go away) 648 pendingDeletions := make(map[string]bool) 649 for k, v := range w.openFilesDeleted { 650 pendingDeletions[k] = v 651 } 652 653 w.maybeYield() 654 655 if w.openFiles == nil { 656 w.openFiles = make(map[string]int) 657 w.openFilesDeleted = make(map[string]bool) 658 } 659 nOpenFiles := len(w.openFiles) 660 661 if w.noDeleteOpenFile && nOpenFiles > 0 { 662 // print the first one as its very verbose otherwise 663 var cause error 664 for _, v := range w.openFileHandles { 665 cause = v 666 break 667 } 668 panic(mergeError(errors.New(fmt.Sprintf( 669 "MockDirectoryWrapper: cannot close: there are still open files: %v", 670 w.openFiles)), cause)) 671 } 672 673 nOpenLocks := func() int { 674 w.openLocksLock.Lock() 675 defer w.openLocksLock.Unlock() 676 return len(w.openLocks) 677 }() 678 if w.noDeleteOpenFile && nOpenLocks > 0 { 679 panic(fmt.Sprintf("MockDirectoryWrapper: cannot close: there are still open locks: %v", w.openLocks)) 680 } 681 682 w.isOpen = false 683 if w.checkIndexOnClose { 684 w.randomErrorRate = 0 685 w.randomErrorRateOnOpen = 0 686 files, err := w._ListAll() 687 if err != nil { 688 return err 689 } 690 if index.IsIndexFileExists(files) { 691 fmt.Println("\nNOTE: MockDirectoryWrapper: now crash") 692 err = w._crash() // corrupt any unsynced-files 693 if err != nil { 694 return err 695 } 696 fmt.Println("\nNOTE: MockDirectoryWrapper: now run CheckIndex") 697 w.Unlock() // CheckIndex may access synchronized method 698 CheckIndex(w, w.crossCheckTermVectorsOnClose) 699 w.Lock() // CheckIndex may access synchronized method 700 701 // TODO: factor this out / share w/ TestIW.assertNoUnreferencedFiles 702 if w.assertNoUnreferencedFilesOnClose { 703 // now look for unreferenced files: discount ones that we tried to delete but could not 704 all, err := w._ListAll() 705 if err != nil { 706 return err 707 } 708 allFiles := make(map[string]bool) 709 for _, name := range all { 710 allFiles[name] = true 711 } 712 for name, _ := range pendingDeletions { 713 delete(allFiles, name) 714 } 715 startFiles := make([]string, 0, len(allFiles)) 716 for k, _ := range allFiles { 717 startFiles = append(startFiles, k) 718 } 719 iwc := index.NewIndexWriterConfig(TEST_VERSION_CURRENT, nil) 720 iwc.SetIndexDeletionPolicy(index.NO_DELETION_POLICY) 721 iw, err := index.NewIndexWriter(w.Directory, iwc) 722 if err != nil { 723 return err 724 } 725 err = iw.Rollback() 726 if err != nil { 727 return err 728 } 729 endFiles, err := w.Directory.ListAll() 730 if err != nil { 731 return err 732 } 733 734 hasSegmentsGenFile := sort.SearchStrings(endFiles, index.INDEX_FILENAME_SEGMENTS_GEN) >= 0 735 if pendingDeletions["segments.gen"] && hasSegmentsGenFile { 736 panic("not implemented yet") 737 } 738 739 // its possible we cannot delete the segments_N on windows if someone has it open and 740 // maybe other files too, depending on timing. normally someone on windows wouldnt have 741 // an issue (IFD would nuke this stuff eventually), but we pass NoDeletionPolicy... 742 for _, file := range pendingDeletions { 743 log.Println(file) 744 panic("not implemented yet") 745 } 746 747 sort.Strings(startFiles) 748 startFiles = uniqueStrings(startFiles) 749 sort.Strings(endFiles) 750 endFiles = uniqueStrings(endFiles) 751 752 if !reflect.DeepEqual(startFiles, endFiles) { 753 panic("not implemented") 754 } 755 756 ir1, err := index.OpenDirectoryReader(w) 757 if err != nil { 758 return err 759 } 760 numDocs1 := ir1.NumDocs() 761 err = ir1.Close() 762 if err != nil { 763 return err 764 } 765 iw, err = index.NewIndexWriter(w, index.NewIndexWriterConfig(TEST_VERSION_CURRENT, nil)) 766 if err != nil { 767 return err 768 } 769 err = iw.Close() 770 if err != nil { 771 return err 772 } 773 ir2, err := index.OpenDirectoryReader(w) 774 if err != nil { 775 return err 776 } 777 numDocs2 := ir2.NumDocs() 778 err = ir2.Close() 779 if err != nil { 780 return err 781 } 782 assert2(numDocs1 == numDocs2, fmt.Sprintf("numDocs changed after opening/closing IW: before=%v after=%v", numDocs1, numDocs2)) 783 } 784 } 785 } 786 return w.Directory.Close() 787 } 788 789 func assert(ok bool) { 790 if !ok { 791 panic("assert fail") 792 } 793 } 794 795 func assert2(ok bool, msg string) { 796 if !ok { 797 panic(msg) 798 } 799 } 800 801 func uniqueStrings(a []string) []string { 802 ans := make([]string, 0, len(a)) // inefficient for fewer unique items 803 for _, v := range a { 804 if n := len(ans); n == 0 || ans[n-1] != v { 805 ans = append(ans, v) 806 } 807 } 808 return ans 809 } 810 811 func (w *MockDirectoryWrapper) removeOpenFile(c io.Closer, name string) { 812 w.Lock() // synchronized 813 defer w.Unlock() 814 815 w._removeOpenFile(c, name) 816 } 817 818 func (w *MockDirectoryWrapper) _removeOpenFile(c io.Closer, name string) { 819 if v, ok := w.openFiles[name]; ok { 820 if v == 1 { 821 delete(w.openFiles, name) 822 } else { 823 w.openFiles[name] = v - 1 824 } 825 } 826 delete(w.openFileHandles, c) 827 } 828 829 func (w *MockDirectoryWrapper) removeIndexOutput(out store.IndexOutput, name string) { 830 w.Lock() // synchronized 831 defer w.Unlock() 832 833 delete(w.openFilesForWrite, name) 834 w._removeOpenFile(out, name) 835 } 836 837 func (w *MockDirectoryWrapper) removeIndexInput(in store.IndexInput, name string) { 838 if !w.isLocked { 839 w.Lock() // synchronized 840 defer w.Unlock() 841 } 842 843 w._removeOpenFile(in, name) 844 } 845 846 /* 847 Objects that represent fail-lable conditions. Objects of a derived 848 class are created and registered with teh mock directory. After 849 register, each object will be invoked once for each first write of a 850 file, giving the object a chance to throw an IO error. 851 */ 852 type Failure struct { 853 // eval is called on the first write of every new file 854 eval func(dir *MockDirectoryWrapper) error 855 doFail bool 856 } 857 858 /* 859 reset should set the state of the failure to its default (freshly 860 constructed) state. Reset is convenient for tests that want to create 861 one failure object and then reuse it in mutiple cases. This, combined 862 with the fact that Failure subclasses are often anonymous classes 863 makes reset difficult to do otherwise. 864 865 A typical example of use is 866 867 failure := &Failure { eval: func(dir *MockDirectoryWrapper) { ... } } 868 ... 869 mock.failOn(failure.reset()) 870 871 */ 872 func (f *Failure) Reset() *Failure { return f } 873 func (f *Failure) SetDoFail() { f.doFail = true } 874 func (f *Failure) ClearDoFail() { f.doFail = false } 875 876 /* 877 add a Failure object to the list of objects to be evaluated at every 878 potential failure opint 879 */ 880 func (w *MockDirectoryWrapper) failOn(fail *Failure) { 881 w.failures = append(w.failures, fail) 882 } 883 884 // Iterate through the failures list, giving each object a 885 // chance to return an error 886 func (w *MockDirectoryWrapper) maybeThrowDeterministicException() error { 887 for _, f := range w.failures { 888 if err := f.eval(w); err != nil { 889 return err 890 } 891 } 892 return nil 893 } 894 895 func (w *MockDirectoryWrapper) ListAll() ([]string, error) { 896 if !w.isLocked { 897 w.Lock() // synchronized 898 defer w.Unlock() 899 } 900 return w._ListAll() 901 } 902 903 func (w *MockDirectoryWrapper) _ListAll() ([]string, error) { 904 w.maybeYield() 905 return w.Directory.ListAll() 906 } 907 908 func (w *MockDirectoryWrapper) FileExists(name string) bool { 909 if !w.isLocked { 910 w.Lock() // synchronized 911 defer w.Unlock() 912 } 913 914 w.maybeYield() 915 return w.Directory.FileExists(name) 916 } 917 918 func (w *MockDirectoryWrapper) FileLength(name string) (int64, error) { 919 w.Lock() // synchronized 920 defer w.Unlock() 921 922 return w._fileLength(name) 923 } 924 925 func (w *MockDirectoryWrapper) _fileLength(name string) (int64, error) { 926 w.maybeYield() 927 return w.Directory.FileLength(name) 928 } 929 930 func (w *MockDirectoryWrapper) MakeLock(name string) store.Lock { 931 if !w.isLocked { 932 w.Lock() // synchronized 933 defer w.Unlock() 934 } 935 936 w.maybeYield() 937 return w.lockFactory().Make(name) 938 } 939 940 func (w *MockDirectoryWrapper) ClearLock(name string) error { 941 w.Lock() // synchronized 942 defer w.Unlock() 943 944 w.maybeYield() 945 return w.lockFactory().Clear(name) 946 } 947 948 func (w *MockDirectoryWrapper) SetLockFactory(lockFactory store.LockFactory) { 949 w.Lock() // synchronized 950 defer w.Unlock() 951 952 w.maybeYield() 953 // sneaky: we must pass the original this way to the dir, because 954 // some impls (e.g. FSDir) do instanceof here 955 w.Directory.SetLockFactory(lockFactory) 956 // now set out wrapped factory here 957 w.myLockFactory = newMockLockFactoryWrapper(w, w.Directory.LockFactory()) 958 } 959 960 func (w *MockDirectoryWrapper) LockFactory() store.LockFactory { 961 w.Lock() // synchronized 962 defer w.Unlock() 963 964 return w.lockFactory() 965 } 966 967 func (w *MockDirectoryWrapper) lockFactory() store.LockFactory { 968 w.maybeYield() 969 if w.wrapLockFactory { 970 return w.myLockFactory 971 } else { 972 return w.Directory.LockFactory() 973 } 974 } 975 976 func (w *MockDirectoryWrapper) LockID() string { 977 w.Lock() // synchronized 978 defer w.Unlock() 979 980 w.maybeYield() 981 return w.Directory.LockID() 982 } 983 984 func (w *MockDirectoryWrapper) Copy(to store.Directory, src string, dest string, context store.IOContext) error { 985 w.Lock() // synchronized 986 w.isLocked = true 987 defer func() { 988 w.isLocked = false 989 w.Unlock() 990 }() 991 992 w.maybeYield() 993 // randomize the IOContext here? 994 return w.Directory.Copy(to, src, dest, context) 995 } 996 997 // func (w *MockDirectoryWrapper) CreateSlicer(name string, 998 // context store.IOContext) (store.IndexInputSlicer, error) { 999 1000 // if !w.isLocked { 1001 // w.Lock() // synchronized 1002 // defer w.Unlock() 1003 // } 1004 1005 // w.maybeYield() 1006 // if !w.Directory.FileExists(name) { 1007 // return nil, errors.New(fmt.Sprintf("File not found: %v", name)) 1008 // } 1009 // // cannot open a file for input if it's still open for output, 1010 // // except for segments.gen and segments_N 1011 // if _, ok := w.openFilesForWrite[name]; ok && !strings.HasPrefix(name, "segments") { 1012 // return nil, w.fillOpenTrace(errors.New(fmt.Sprintf( 1013 // "MockDirectoryWrapper: file '%v' is still open for writing", name)), name, false) 1014 // } 1015 1016 // delegateHandle, err := w.Directory.CreateSlicer(name, context) 1017 // if err != nil { 1018 // return nil, err 1019 // } 1020 // handle := &myIndexInputSlicer{w, delegateHandle, name, false} 1021 // w._addFileHandle(handle, name, HANDLE_SLICE) 1022 // return handle, nil 1023 // } 1024 1025 // type myIndexInputSlicer struct { 1026 // owner *MockDirectoryWrapper 1027 // delegateHandle store.IndexInputSlicer 1028 // name string 1029 // isClosed bool 1030 // } 1031 1032 // func (s *myIndexInputSlicer) Close() error { 1033 // if !s.isClosed { 1034 // err := s.delegateHandle.Close() 1035 // if err != nil { 1036 // return err 1037 // } 1038 // s.owner.removeOpenFile(s, s.name) 1039 // s.isClosed = true 1040 // } 1041 // return nil 1042 // } 1043 1044 // func (s *myIndexInputSlicer) OpenSlice(desc string, offset, length int64) store.IndexInput { 1045 // s.owner.maybeYield() 1046 // slice := s.delegateHandle.OpenSlice(desc, offset, length) 1047 // ii := newMockIndexInputWrapper(s.owner, s.name, slice) 1048 // s.owner.addFileHandle(ii, s.name, HANDLE_INPUT) 1049 // return ii 1050 // } 1051 1052 // func (s *myIndexInputSlicer) OpenFullSlice() store.IndexInput { 1053 // s.owner.maybeYield() 1054 // slice := s.delegateHandle.OpenFullSlice() 1055 // ii := newMockIndexInputWrapper(s.owner, s.name, slice) 1056 // s.owner.addFileHandle(ii, s.name, HANDLE_INPUT) 1057 // return ii 1058 // } 1059 1060 // type BufferedIndexOutputWrapper struct { 1061 // *store.BufferedIndexOutput 1062 // io store.IndexOutput 1063 // } 1064 1065 // func newBufferedIndexOutputWrapper(bufferSize int, io store.IndexOutput) *BufferedIndexOutputWrapper { 1066 // ans := &BufferedIndexOutputWrapper{} 1067 // ans.BufferedIndexOutput = store.NewBufferedIndexOutput(bufferSize, ans) 1068 // ans.io = io 1069 // return ans 1070 // } 1071 1072 // func (w *BufferedIndexOutputWrapper) Length() (int64, error) { 1073 // return w.io.Length() 1074 // } 1075 1076 // func (w *BufferedIndexOutputWrapper) FlushBuffer(buf []byte) error { 1077 // return w.io.WriteBytes(buf) 1078 // } 1079 1080 // // func (w *BufferedIndexOutputWrapper) Flush() error { 1081 // // defer w.io.Flush() 1082 // // return w.BufferedIndexOutput.Flush() 1083 // // } 1084 1085 // func (w *BufferedIndexOutputWrapper) Close() error { 1086 // defer w.io.Close() 1087 // return w.BufferedIndexOutput.Close() 1088 // } 1089 1090 // store/MockLockFactoryWrapper.java 1091 1092 // Used by MockDirectoryWrapper to wrap another factory and track 1093 // open locks. 1094 type MockLockFactoryWrapper struct { 1095 store.LockFactory 1096 dir *MockDirectoryWrapper 1097 } 1098 1099 func newMockLockFactoryWrapper(dir *MockDirectoryWrapper, delegate store.LockFactory) *MockLockFactoryWrapper { 1100 return &MockLockFactoryWrapper{delegate, dir} 1101 } 1102 1103 func (w *MockLockFactoryWrapper) Make(lockName string) store.Lock { 1104 return newMockLock(w.dir, w.LockFactory.Make(lockName), lockName) 1105 } 1106 1107 func (w *MockLockFactoryWrapper) Clear(lockName string) error { 1108 err := w.LockFactory.Clear(lockName) 1109 if err != nil { 1110 return err 1111 } 1112 w.dir.openLocksLock.Lock() 1113 defer w.dir.openLocksLock.Unlock() 1114 delete(w.dir.openLocks, lockName) 1115 return nil 1116 } 1117 1118 func (w *MockLockFactoryWrapper) String() string { 1119 return fmt.Sprintf("MockLockFactoryWrapper(%v)", w.LockFactory) 1120 } 1121 1122 type MockLock struct { 1123 *store.LockImpl 1124 delegate store.Lock 1125 name string 1126 dir *MockDirectoryWrapper 1127 } 1128 1129 func newMockLock(dir *MockDirectoryWrapper, delegate store.Lock, name string) *MockLock { 1130 panic("not implemented yet") 1131 // assert(name != "") 1132 // ans := &MockLock{ 1133 // delegate: delegate, 1134 // name: name, 1135 // dir: dir, 1136 // } 1137 // ans.LockImpl = store.NewLockImpl(ans) 1138 // return ans 1139 } 1140 1141 func (lock *MockLock) Obtain() (ok bool, err error) { 1142 ok, err = lock.delegate.Obtain() 1143 if err != nil { 1144 return 1145 } 1146 if ok { 1147 lock.dir.openLocksLock.Lock() 1148 defer lock.dir.openLocksLock.Unlock() 1149 lock.dir.openLocks[lock.name] = true 1150 } 1151 return ok, nil 1152 } 1153 1154 func (lock *MockLock) Close() error { 1155 panic("not implemented yet") 1156 // if err := lock.delegate.Release(); err != nil { 1157 // return err 1158 // } 1159 // lock.dir.openLocksLock.Lock() 1160 // defer lock.dir.openLocksLock.Unlock() 1161 // delete(lock.dir.openLocks, lock.name) 1162 // return nil 1163 } 1164 1165 func (lock *MockLock) IsLocked() bool { 1166 return lock.delegate.IsLocked() 1167 } 1168 1169 // store/MockIndexInputWrapper.java 1170 1171 /* 1172 Used by MockDirectoryWrapper to create an input stream that keeps 1173 track of when it's been closed. 1174 */ 1175 type MockIndexInputWrapper struct { 1176 *store.IndexInputImpl 1177 dir *MockDirectoryWrapper 1178 delegate store.IndexInput 1179 name string 1180 isClone bool 1181 closed bool 1182 } 1183 1184 func newMockIndexInputWrapper(dir *MockDirectoryWrapper, 1185 name string, delegate store.IndexInput) *MockIndexInputWrapper { 1186 ans := &MockIndexInputWrapper{nil, dir, delegate, name, false, false} 1187 ans.IndexInputImpl = store.NewIndexInputImpl(fmt.Sprintf( 1188 "MockIndexInputWrapper(name=%v delegate=%v)", 1189 name, delegate), ans) 1190 return ans 1191 } 1192 1193 func (w *MockIndexInputWrapper) Close() (err error) { 1194 panic("not implemented yet") 1195 // defer func() { 1196 // w.closed = true 1197 // err2 := w.delegate.Close() 1198 // err = mergeError(err, err2) 1199 // if err2 == nil { 1200 // // Pending resolution on LUCENE-686 we may want to remove the 1201 // // conditional check so we also track that all clones get closed: 1202 // if !w.isClone { 1203 // w.dir.removeIndexInput(w, w.name) 1204 // } 1205 // } 1206 // }() 1207 // // turn on the following to look for leaks closing inputs, after 1208 // // fixing TestTransactions 1209 // // return w.dir.maybeThrowDeterministicException() 1210 // return nil 1211 } 1212 1213 func (w *MockIndexInputWrapper) ensureOpen() { 1214 assert2(!w.closed, "Abusing closed IndexInput!") 1215 } 1216 1217 func (w *MockIndexInputWrapper) Clone() store.IndexInput { 1218 panic("not implemented yet") 1219 } 1220 1221 func (w *MockIndexInputWrapper) FilePointer() int64 { 1222 w.ensureOpen() 1223 return w.delegate.FilePointer() 1224 } 1225 1226 func (w *MockIndexInputWrapper) Seek(pos int64) error { 1227 w.ensureOpen() 1228 return w.delegate.Seek(pos) 1229 } 1230 1231 func (w *MockIndexInputWrapper) Length() int64 { 1232 w.ensureOpen() 1233 return w.delegate.Length() 1234 } 1235 1236 func (w *MockIndexInputWrapper) ReadByte() (byte, error) { 1237 w.ensureOpen() 1238 return w.delegate.ReadByte() 1239 } 1240 1241 func (w *MockIndexInputWrapper) ReadBytes(buf []byte) error { 1242 w.ensureOpen() 1243 return w.delegate.ReadBytes(buf) 1244 } 1245 1246 func (w *MockIndexInputWrapper) ReadShort() (int16, error) { 1247 w.ensureOpen() 1248 return w.delegate.ReadShort() 1249 } 1250 1251 func (w *MockIndexInputWrapper) ReadInt() (int32, error) { 1252 w.ensureOpen() 1253 return w.delegate.ReadInt() 1254 } 1255 1256 func (w *MockIndexInputWrapper) ReadLong() (int64, error) { 1257 w.ensureOpen() 1258 return w.delegate.ReadLong() 1259 } 1260 1261 func (w *MockIndexInputWrapper) ReadString() (string, error) { 1262 w.ensureOpen() 1263 return w.delegate.ReadString() 1264 } 1265 1266 func (w *MockIndexInputWrapper) ReadStringStringMap() (map[string]string, error) { 1267 w.ensureOpen() 1268 return w.delegate.ReadStringStringMap() 1269 } 1270 1271 func (w *MockIndexInputWrapper) ReadVInt() (int32, error) { 1272 w.ensureOpen() 1273 return w.delegate.ReadVInt() 1274 } 1275 1276 func (w *MockIndexInputWrapper) ReadVLong() (int64, error) { 1277 w.ensureOpen() 1278 return w.delegate.ReadVLong() 1279 } 1280 1281 func (w *MockIndexInputWrapper) String() string { 1282 return fmt.Sprintf("MockIndexInputWrapper(%v)", w.delegate) 1283 } 1284 1285 // store/MockIndexOutputWrapper.java 1286 1287 /* 1288 Used by MockRAMDirectory to create an output stream that will throw 1289 an error on fake disk full, track max disk space actually used, and 1290 maybe throw random IO errors. 1291 */ 1292 type MockIndexOutputWrapper struct { 1293 *store.IndexOutputImpl 1294 dir *MockDirectoryWrapper 1295 delegate store.IndexOutput 1296 first bool 1297 name string 1298 singleByte []byte 1299 } 1300 1301 func newMockIndexOutputWrapper(dir *MockDirectoryWrapper, name string, delegate store.IndexOutput) *MockIndexOutputWrapper { 1302 assert(delegate != nil) 1303 ans := &MockIndexOutputWrapper{ 1304 dir: dir, 1305 name: name, 1306 delegate: delegate, 1307 first: true, 1308 singleByte: make([]byte, 1), 1309 } 1310 ans.IndexOutputImpl = store.NewIndexOutput(ans) 1311 return ans 1312 } 1313 1314 func (w *MockIndexOutputWrapper) checkCrashed() error { 1315 // If MockRAMDir crashed since we were opened, then don't write anything 1316 if w.dir.crashed { 1317 return errors.New(fmt.Sprintf("MockRAMDirectory was crashed; cannot write to %v", w.name)) 1318 } 1319 return nil 1320 } 1321 1322 func (w *MockIndexOutputWrapper) checkDiskFull(buf []byte, in util.DataInput) (err error) { 1323 panic("not implemented yet") 1324 // var freeSpace int64 = 0 1325 // if w.dir.maxSize > 0 { 1326 // sizeInBytes, err := w.dir.sizeInBytes() 1327 // if err != nil { 1328 // return err 1329 // } 1330 // freeSpace = w.dir.maxSize - sizeInBytes 1331 // } 1332 // var realUsage int64 = 0 1333 1334 // // Enforce disk full: 1335 // if w.dir.maxSize > 0 && freeSpace <= int64(len(buf)) { 1336 // // Compute the real disk free. This will greatly slow down our 1337 // // test but makes it more accurate: 1338 // realUsage, err = w.dir.recomputeActualSizeInBytes() 1339 // if err != nil { 1340 // return err 1341 // } 1342 // freeSpace = w.dir.maxSize - realUsage 1343 // } 1344 1345 // if w.dir.maxSize > 0 && freeSpace <= int64(len(buf)) { 1346 // if freeSpace > 0 { 1347 // realUsage += freeSpace 1348 // if buf != nil { 1349 // w.delegate.WriteBytes(buf[:freeSpace]) 1350 // } else { 1351 // w.CopyBytes(in, int64(len(buf))) 1352 // } 1353 // } 1354 // if realUsage > w.dir.maxUsedSize { 1355 // w.dir.maxUsedSize = realUsage 1356 // } 1357 // n, err := w.dir.recomputeActualSizeInBytes() 1358 // if err != nil { 1359 // return err 1360 // } 1361 // fLen, err := w.delegate.Length() 1362 // if err != nil { 1363 // return err 1364 // } 1365 // message := fmt.Sprintf("fake disk full at %v bytes when writing %v (file length=%v", 1366 // n, w.name, fLen) 1367 // if freeSpace > 0 { 1368 // message += fmt.Sprintf("; wrote %v of %v bytes", freeSpace, len(buf)) 1369 // } 1370 // message += ")" 1371 // if VERBOSE { 1372 // log.Println("MDW: now throw fake disk full") 1373 // debug.PrintStack() 1374 // } 1375 // return errors.New(message) 1376 // } 1377 // return nil 1378 } 1379 1380 func (w *MockIndexOutputWrapper) Close() (err error) { 1381 panic("not implemented yet") 1382 // defer func() { 1383 // err2 := w.delegate.Close() 1384 // if err2 != nil { 1385 // err = mergeError(err, err2) 1386 // return 1387 // } 1388 // if w.dir.trackDiskUsage { 1389 // // Now compute actual disk usage & track the maxUsedSize 1390 // // in the MDW: 1391 // size, err2 := w.dir.recomputeActualSizeInBytes() 1392 // if err2 != nil { 1393 // err = mergeError(err, err2) 1394 // return 1395 // } 1396 // if size > w.dir.maxUsedSize { 1397 // w.dir.maxUsedSize = size 1398 // } 1399 // } 1400 // w.dir.removeIndexOutput(w, w.name) 1401 // }() 1402 // return w.dir.maybeThrowDeterministicException() 1403 } 1404 1405 func (w *MockIndexOutputWrapper) Flush() error { 1406 panic("not implemented yet") 1407 // defer w.delegate.Flush() 1408 // return w.dir.maybeThrowDeterministicException() 1409 } 1410 1411 func (w *MockIndexOutputWrapper) WriteByte(b byte) error { 1412 w.singleByte[0] = b 1413 return w.WriteBytes(w.singleByte) 1414 } 1415 1416 func (w *MockIndexOutputWrapper) WriteBytes(buf []byte) error { 1417 assert(w.delegate != nil) 1418 err := w.checkCrashed() 1419 if err != nil { 1420 return err 1421 } 1422 err = w.checkDiskFull(buf, nil) 1423 if err != nil { 1424 return err 1425 } 1426 1427 if w.dir.randomState.Intn(200) == 0 { 1428 half := len(buf) / 2 1429 err = w.delegate.WriteBytes(buf[:half]) 1430 if err != nil { 1431 return err 1432 } 1433 runtime.Gosched() 1434 err = w.delegate.WriteBytes(buf[half:]) 1435 if err != nil { 1436 return err 1437 } 1438 } else { 1439 err = w.delegate.WriteBytes(buf) 1440 if err != nil { 1441 return err 1442 } 1443 } 1444 1445 if w.first { 1446 // Maybe throw random error; only do this on first write to a new file: 1447 w.first = false 1448 err = w.dir.maybeThrowIOException(w.name) 1449 if err != nil { 1450 return err 1451 } 1452 } 1453 return nil 1454 } 1455 1456 func (w *MockIndexOutputWrapper) FilePointer() int64 { 1457 return w.delegate.FilePointer() 1458 } 1459 1460 func (w *MockIndexOutputWrapper) Length() (int64, error) { 1461 panic("not implemented yet") 1462 // return w.delegate.Length() 1463 } 1464 1465 func (w *MockIndexOutputWrapper) CopyBytes(input util.DataInput, numBytes int64) error { 1466 panic("not implemented yet") 1467 } 1468 1469 func (w *MockIndexOutputWrapper) String() string { 1470 return fmt.Sprintf("MockIndexOutputWrapper(%v,%v)", reflect.TypeOf(w.delegate), w.delegate) 1471 }