Пример #1
0
// Ensure the file ahs room for more data.
func (file *File) Ensure(more uint64) (err error) {
	if file.Append+more <= file.Size {
		return
	}
	if file.Buf != nil {
		if err = file.Buf.Unmap(); err != nil {
			return
		}
	}
	if _, err = file.Fh.Seek(0, os.SEEK_END); err != nil {
		return
	}
	if _, err = file.Fh.Write(make([]byte, file.Growth)); err != nil {
		return
	}
	if err = file.Fh.Sync(); err != nil {
		return
	}
	if file.Buf, err = gommap.Map(file.Fh, gommap.RDWR, 0); err != nil {
		return
	}
	file.Size += file.Growth
	log.Printf("File %s has grown %d bytes\n", file.Name, file.Growth)
	return file.Ensure(more)
}
Пример #2
0
// Open (create if non-exist) the file.
func Open(name string, growth uint64) (file *File, err error) {
	if growth < 1 {
		err = errors.New(fmt.Sprintf("Opening %s, file growth (%d) is too small", name, growth))
	}
	file = &File{Name: name, Growth: growth}
	if file.Fh, err = os.OpenFile(name, os.O_CREATE|os.O_RDWR, 0600); err != nil {
		return
	}
	fsize, err := file.Fh.Seek(0, os.SEEK_END)
	if err != nil {
		return
	}
	file.Size = uint64(fsize)
	if file.Size == 0 {
		file.CheckSizeAndEnsure(file.Growth)
		return
	}

	if file.Buf, err = gommap.Map(file.Fh, gommap.RDWR, 0); err != nil {
		return
	}
	// find append position
	for pos := file.Size - 1; pos > 0; pos-- {
		if file.Buf[pos] != 0 {
			file.Append = pos + 1
			break
		}
	}
	return
}
Пример #3
0
// Open (create if non-exist) the file.
func Open(name string, growth uint64) (file *File, err error) {
	if growth < 1 {
		err = errors.New(fmt.Sprintf("Opening %s, file growth (%d) is too small", name, growth))
	}
	file = &File{Name: name, Growth: growth, Sync: new(sync.RWMutex)}
	if file.Fh, err = os.OpenFile(name, os.O_CREATE|os.O_RDWR, 0600); err != nil {
		return
	}
	fsize, err := file.Fh.Seek(0, os.SEEK_END)
	if err != nil {
		return
	}
	if int(fsize) < 0 {
		log.Panicf("File %s is too large to mmap", name)
	}
	file.Size = uint64(fsize)
	if file.Size == 0 {
		return file, file.Ensure(file.Growth)
	}

	if file.Buf, err = gommap.Map(file.Fh, gommap.RDWR, 0); err != nil {
		return
	}
	// find append position
	for low, mid, high := uint64(0), file.Size/2, file.Size; ; {
		switch {
		case high-mid == 1:
			if file.Buf[mid] == 0 {
				if file.Buf[mid-1] == 0 {
					file.Append = mid - 1
				} else {
					file.Append = mid
				}
				return
			}
			file.Append = high
			return
		case file.Buf[mid] == 0:
			high = mid
			mid = low + (mid-low)/2
		default:
			low = mid
			mid = mid + (high-mid)/2
		}
	}
	return
}
Пример #4
0
// Open (create if non-exist) the file.
func Open(name string, growth uint64) (file *File, err error) {
	if growth < 1 {
		err = errors.New(fmt.Sprintf("Growth size (%d) is too small (opening %s)", growth, name))
	}
	file = &File{Name: name, Growth: growth}
	if file.Fh, err = os.OpenFile(name, os.O_CREATE|os.O_RDWR, 0600); err != nil {
		return
	}
	fsize, err := file.Fh.Seek(0, os.SEEK_END)
	if err != nil {
		return
	}
	file.Size = uint64(fsize)
	if file.Size == 0 {
		file.CheckSizeAndEnsure(file.Growth)
		return
	}

	if file.Buf, err = gommap.Map(file.Fh, gommap.RDWR, 0); err != nil {
		return
	}
	// find used size
	for low, mid, high := uint64(0), file.Size/2, file.Size; ; {
		switch {
		case high-mid == 1:
			if file.Buf[mid] == 0 {
				if file.Buf[mid-1] == 0 {
					file.UsedSize = mid - 1
				} else {
					file.UsedSize = mid
				}
				return
			}
			file.UsedSize = high
			return
		case file.Buf[mid] == 0:
			high = mid
			mid = low + (mid-low)/2
		default:
			low = mid
			mid = mid + (high-mid)/2
		}
	}
	log.Printf("%s has %d bytes out of %d bytes in-use", name, file.UsedSize, file.Size)
	return
}
Пример #5
0
// Ensure the file ahs room for more data.
func (file *File) CheckSizeAndEnsure(more uint64) {
	if file.UsedSize+more <= file.Size {
		return
	}
	var err error
	if file.Buf != nil {
		if err = file.Buf.Unmap(); err != nil {
			panic(err)
		}
	}
	if _, err = file.Fh.Seek(0, os.SEEK_END); err != nil {
		panic(err)
	}
	// grow the file incrementally
	zeroBuf := make([]byte, FILE_GROWTH_INCREMENTAL)
	for i := uint64(0); i < file.Growth; i += FILE_GROWTH_INCREMENTAL {
		var slice []byte
		if i+FILE_GROWTH_INCREMENTAL > file.Growth {
			slice = zeroBuf[0 : i+FILE_GROWTH_INCREMENTAL-file.Growth]
		} else {
			slice = zeroBuf
		}
		if _, err = file.Fh.Write(slice); err != nil {
			panic(err)
		}
	}
	if err = file.Fh.Sync(); err != nil {
		panic(err)
	}
	if file.Buf, err = gommap.Map(file.Fh, gommap.RDWR, 0); err != nil {
		panic(err)
	}
	file.Size += file.Growth
	log.Printf("File %s has grown %d bytes\n", file.Name, file.Growth)
	file.CheckSizeAndEnsure(more)
}