stack.go
func (s *Stack) IterateForward(handler func(depth int, header io.Reader, body io.Reader) bool) error {
	// This operation does not relies on depth counter, so can be used for repare
	s.guard.Lock()
	defer s.guard.Unlock()
	s.lastAccess = time.Now()
	file, err := s.getFile()
	if err != nil {
		return err
	}
	//Get file size
	fileSize, err := file.Seek(0, os.SEEK_END)
	if err != nil {
		return err
	}
	_, err = file.Seek(0, os.SEEK_SET)
	if err != nil {
		return err
	}
	defer file.Seek(0, os.SEEK_END)
	var (
		currentBlock       fileBlock // Current block description
		currentBlockOffset uint64    // Current block offset from begining of file
	)
	var depth int
	for currentBlock.NextBlockPoint() < fileSize {
		newPos := currentBlock.NextBlockPoint()
		if newPos > fileSize {
			log.Println("Bad reference to next block at", currentBlockOffset, "!trunc!")
			file.Truncate(int64(currentBlockOffset))
			break
		}
		block, err := readBlockAt(file, newPos)
		// Non-full meta-info?
		if err == io.EOF {
			log.Println("Broken meta info at", newPos, "!trunc!")
			file.Truncate(newPos)
			break
		}
		// I/O error
		if err != nil {
			log.Println("Can't read block at", newPos)
			return err
		}
		// Check back-ref
		if block.PrevBlock != currentBlockOffset {
			log.Println("Bad back reference", block.PrevBlock, "!=", currentBlockOffset, "!upd!")
			block.PrevBlock = currentBlockOffset
			block.writeTo(file, newPos)
		}
		// Update current state
		currentBlockOffset = uint64(newPos)
		currentBlock = block
		body := io.NewSectionReader(file, int64(currentBlock.DataPoint), int64(currentBlock.DataSize))
		header := io.NewSectionReader(file, int64(currentBlock.HeaderPoint), int64(currentBlock.HeaderSize))
		// invoke block processor
		if handler != nil && !handler(depth, header, body) {
			return nil
		}
		depth++
	}
	s.depth = depth
	s.currentBlock = currentBlock
	s.currentBlockPos = int64(currentBlockOffset)
	return nil
}
func (s *Stack) IterateForward(handler func(depth int, header io.Reader, body io.Reader) bool) error {
	// This operation does not relies on depth counter, so can be used for repare
	s.guard.Lock()
	defer s.guard.Unlock()
	s.lastAccess = time.Now()
	file, err := s.getFile()
	if err != nil {
		return err
	}
	//Get file size
	fileSize, err := file.Seek(0, os.SEEK_END)
	if err != nil {
		return err
	}
	_, err = file.Seek(0, os.SEEK_SET)
	if err != nil {
		return err
	}
	defer file.Seek(0, os.SEEK_END)
	var (
		currentBlock       fileBlock // Current block description
		currentBlockOffset uint64    // Current block offset from begining of file
	)
	var depth int
	for currentBlock.NextBlockPoint() < fileSize {
		newPos := currentBlock.NextBlockPoint()
		if newPos > fileSize {
			log.Println("Bad reference to next block at", currentBlockOffset, "!trunc!")
			file.Truncate(int64(currentBlockOffset))
			break
		}
		block, err := readBlockAt(file, newPos)
		// Non-full meta-info?
		if err == io.EOF {
			log.Println("Broken meta info at", newPos, "!trunc!")
			file.Truncate(newPos)
			break
		}
		// I/O error
		if err != nil {
			log.Println("Can't read block at", newPos)
			return err
		}
		// Check back-ref
		if block.PrevBlock != currentBlockOffset {
			log.Println("Bad back reference", block.PrevBlock, "!=", currentBlockOffset, "!upd!")
			block.PrevBlock = currentBlockOffset
			block.writeTo(file, newPos)
		}
		// Update current state
		currentBlockOffset = uint64(newPos)
		currentBlock = block
		body := io.NewSectionReader(file, int64(currentBlock.DataPoint), int64(currentBlock.DataSize))
		header := io.NewSectionReader(file, int64(currentBlock.HeaderPoint), int64(currentBlock.HeaderSize))
		// invoke block processor
		if handler != nil && !handler(depth, header, body) {
			return nil
		}
		depth++
	}
	s.depth = depth
	s.currentBlock = currentBlock
	s.currentBlockPos = int64(currentBlockOffset)
	return nil
}
func ( s * Stack ) IterateForward ( handler func ( depth int , header io . Reader , body io . Reader ) bool ) error { // This operation does not relies on depth counter, so can be used for repare s . guard . Lock ( ) defer s . guard . Unlock ( ) s . lastAccess = time . Now ( ) file , err := s . getFile ( ) if err != nil { return err } //Get file size fileSize , err := file . Seek ( 0 , os . SEEK_END ) if err != nil { return err } _ , err = file . Seek ( 0 , os . SEEK_SET ) if err != nil { return err } defer file . Seek ( 0 , os . SEEK_END ) var ( currentBlock fileBlock // Current block description currentBlockOffset uint64 // Current block offset from begining of file ) var depth int for currentBlock . NextBlockPoint ( ) < fileSize { newPos := currentBlock . NextBlockPoint ( ) if newPos > fileSize { log . Println ( " " , currentBlockOffset , " " ) file . Truncate ( int64 ( currentBlockOffset ) ) break } block , err := readBlockAt ( file , newPos ) // Non-full meta-info? if err == io . EOF { log . Println ( " " , newPos , " " ) file . Truncate ( newPos ) break } // I/O error if err != nil { log . Println ( " " , newPos ) return err } // Check back-ref if block . PrevBlock != currentBlockOffset { log . Println ( " " , block . PrevBlock , " " , currentBlockOffset , " " ) block . PrevBlock = currentBlockOffset block . writeTo ( file , newPos ) } // Update current state currentBlockOffset = uint64 ( newPos ) currentBlock = block body := io . NewSectionReader ( file , int64 ( currentBlock . DataPoint ) , int64 ( currentBlock . DataSize ) ) header := io . NewSectionReader ( file , int64 ( currentBlock . HeaderPoint ) , int64 ( currentBlock . HeaderSize ) ) // invoke block processor if handler != nil && ! handler ( depth , header , body ) { return nil } depth ++ } s . depth = depth s . currentBlock = currentBlock s . currentBlockPos = int64 ( currentBlockOffset ) return nil }
// IterateForward - iterate over hole stack segment-by-segment from begining to end. If all segments
// iterated stack may be repaired
IterateForward - iterate over hole stack segment - by - segment from begining to end . If all segments iterated stack may be repaired