ioextras

package module
v0.0.0-...-af05ae2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 1, 2015 License: MIT Imports: 7 Imported by: 14

README

go-ioextras

Build Status

ioextras provides a number of interfaces that semantically reinforces the Go's standard io primitives interfaces with a number of extra concepts, in addition to utility functions.

See https://godoc.org/github.com/moriyoshi/go-ioextras for detail.

License

Copyright (c) 2014-2015 Moriyoshi Koizumi

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Documentation

Overview

ioextras provides a number of interfaces that semantically reinforces the Go's standard io primitives interfaces with a number of extra concepts, in addition to utility functions.

An I/O channel is an abstraction of a stateful object (that is either taken care of by the operating system or implemented in userland) from/to which information is retrieved / stored through a set of I/O primitives, such as Read() and Write().

A blob is opaque data which can be randomly accessed by io.ReaderAt and io.WriterAt while a stream can be accessed by io.Reader and io.Writer, additionally with io.Seeker.

Index

Examples

Constants

This section is empty.

Variables

View Source
var Unsupported = errors.New("Unsupported operation")

Returned by IOCombo methods when the specified operation is not supported by the underlying implementation.

Functions

func StandardWriterFactory

func StandardWriterFactory(path string, _ interface{}) (io.Writer, error)

Just a thin wrapper of os.OpenFile, passing os.O_CREATE | os.O_WRONLY | os.O_APPEND to the second argument and os.FileMode(0666) as the third argument.

Types

type CloseHook

type CloseHook struct {
	IOCombo
	Callback func(s io.Closer)
}

CloseHook wraps a io.Closer so that it will call the specified callback function on closing the channel. The callback will only be called on an explicit close operation by the user.

Example
f, err := os.OpenFile("/dev/null", os.O_RDWR, os.FileMode(0666))
hf := ioextras.NewCloseHook(f, func(io.Closer) {
	log.Printf("File has been closed")
})
defer hf.Close()
if err != nil {
	log.Fatalf("Failed to open file: %v", err)
}
_, err = f.Write([]byte("test"))
if err != nil {
	log.Fatalf("Failed to write data", err)
}
Output:

func NewCloseHook

func NewCloseHook(c io.Closer, callback func(s io.Closer)) *CloseHook

Creates a new CloseHook from a io.Closer and a callback that will be called on Close().

func (*CloseHook) Close

func (c *CloseHook) Close() error

type CloserErrorPair

type CloserErrorPair struct {
	Closer io.Closer
	Error  error
}

CloserErrorPair identifies the place where the I/O error has occurred during closing the file.

type ContextualReader

type ContextualReader interface {
	ReadWithCtx([]byte, interface{}) (int, error)
}

Defines a reader interface accompanied by the opaque context information

type ContextualWriter

type ContextualWriter interface {
	WriteWithCtx([]byte, interface{}) (int, error)
}

Defines a writer interface accompanied by the opaque context information

type DynamicRotatingWriter

type DynamicRotatingWriter struct {
	IDBuilder            IDBuilder
	WriterFactory        WriterFactory
	HeadPathGenerator    HeadPathGenerator
	RotationCallback     RotationCallback
	CloseErrorReportChan chan<- CloserErrorPair
	// contains filtered or unexported fields
}

DynamicRotatingWriter is an io.Writer that writes the data to the file determined by HeadPathGenerator until the next rotation cycle. The rotation cycle is determined by the return value of IDBuilder. The file is created by WriterFactory. RotationCallback will be called on rotation.

Example
currentId := 0
maxSize := int64(4)
w := ioextras.NewDynamicRotatingWriter(
	// IDBuilder
	func(f io.Writer, _ interface{}) string {
		_f, ok := f.(*os.File)
		if !ok {
			panic("WTF?")
		}
		fi, err := _f.Stat()
		if err != nil {
			return strconv.Itoa(currentId)
		}
		if fi.Size() > maxSize {
			currentId++
		}
		return strconv.Itoa(currentId)
	},
	// WriterFactory
	ioextras.StandardWriterFactory,
	// HeadPathGenerator
	func(id string, _ interface{}) string {
		return "/tmp/demo.log"
	},
	// RotationCallback
	ioextras.SerialRotationCallbackFactory(3),
	// CloseErrorReportChan
	nil,
)
var err error

_, err = w.Write([]byte("test"))
if err != nil {
	log.Fatalf("error writing data: %v", err)
}
_, err = w.Write([]byte("test"))
if err != nil {
	log.Fatalf("error writing data: %v", err)
}
_, err = w.Write([]byte("test"))
if err != nil {
	log.Fatalf("error writing data: %v", err)
}
_, err = w.Write([]byte("test"))
if err != nil {
	log.Fatalf("error writing data: %v", err)
}
Output:

func NewDynamicRotatingWriter

func NewDynamicRotatingWriter(idBuilder IDBuilder, writerFactory WriterFactory, headPathGenerator HeadPathGenerator, rotationCallback RotationCallback, closeErrorReportChan chan<- CloserErrorPair) *DynamicRotatingWriter

Creates a new DynamicRotatingWriter. Pass StandardWriterFactory as writerFactory if you aren't interested in any contextual information passed as the second argument of WriteWithCtx() when opening the file. closeErrorReportChan is a channel that will asynchronously receive errors that occur during closing files that have been opened bby writerFastory. closeErrorReportChan can be nil.

func (*DynamicRotatingWriter) Close

func (w *DynamicRotatingWriter) Close() error

func (*DynamicRotatingWriter) Write

func (w *DynamicRotatingWriter) Write(b []byte) (int, error)

Write() method of io.Writer() interface. This simply calls WriteWithCtx() with the second argument being nil.

func (*DynamicRotatingWriter) WriteWithCtx

func (w *DynamicRotatingWriter) WriteWithCtx(b []byte, ctx interface{}) (int, error)

WriteWithCtx() method of ContextualWriter interface. This function is designed to be reentrant, Because of the dynamic nature of

type Flusher

type Flusher interface {
	Flush() error
}

Flusher is an I/O channel (or stream) that provides `Flush` operation.

type HeadPathGenerator

type HeadPathGenerator func(ID string, ctx interface{}) string

HeadPathGenerator is supposed to return the path to the file data is written to. Generally the path is a static location. ctx argument is the value passed to WriteWithCtx() method as the second argument.

type IDBuilder

type IDBuilder func(w io.Writer, ctx interface{}) string

IDBuilder is supposed to return a string that determines the rotation cycle. Rotation occurs when it returns an identifier different from the one obtained during the previous call to WriteWithCtx() method. ctx argument is the value passed to WriteWithCtx() method as the second argument.

type IOCombo

type IOCombo struct {
	Reader           io.Reader
	ReaderAt         io.ReaderAt
	ContextualReader ContextualReader
	Writer           io.Writer
	WriterAt         io.WriterAt
	ContextualWriter ContextualWriter
	Seeker           io.Seeker
	Closer           io.Closer
	Flusher          Flusher
	Sized            Sized
	Named            Named
}

IOCombo combines objects implementing I/O primitives interfaces in the way it would virtually provide all of the I/O privimites supported by the given objects.

Typical usage is to provide extra primitives interfaces such as io.Closer for a single I/O privimitives interface like io.Reader. In that case, ioutil.NopCloser() can be used instead unless any operation is needed in a call to Close() method.

Call on an unsupported operation returns the Unsupported error (that is a singleton).

Example
package main

import (
	"github.com/moriyoshi/go-ioextras"
	"io"
	"log"
	"strings"
)

type myCloser int

func (myCloser) Close() error {
	log.Printf("File is being closed")
	return nil
}

func main() {
	combo := &ioextras.IOCombo{
		Reader: strings.NewReader("test"),
		Closer: myCloser(0),
	}
	// an IOCombo should have provide io.ReadCloser interface.
	rc := io.ReadCloser(combo)

	b := make([]byte, 4)
	_, err := rc.Read(b)
	if err != nil {
		log.Fatalf("Error during reading: %v", err)
	}
	rc.Close()
}
Output:

func (*IOCombo) Close

func (w *IOCombo) Close() error

func (*IOCombo) Flush

func (w *IOCombo) Flush() error

func (*IOCombo) Name

func (w *IOCombo) Name() string

func (*IOCombo) Read

func (w *IOCombo) Read(b []byte) (int, error)

func (*IOCombo) ReadAt

func (w *IOCombo) ReadAt(b []byte, o int64) (int, error)

func (*IOCombo) ReadWithCtx

func (w *IOCombo) ReadWithCtx(b []byte, ctx interface{}) (int, error)

func (*IOCombo) Seek

func (w *IOCombo) Seek(o int64, whence int) (int64, error)

func (*IOCombo) Size

func (w *IOCombo) Size() (int64, error)

func (*IOCombo) Write

func (w *IOCombo) Write(b []byte) (int, error)

func (*IOCombo) WriteAt

func (w *IOCombo) WriteAt(b []byte, o int64) (int, error)

func (*IOCombo) WriteWithCtx

func (w *IOCombo) WriteWithCtx(b []byte, ctx interface{}) (int, error)

type MemoryRandomAccessStore

type MemoryRandomAccessStore struct {
	// contains filtered or unexported fields
}

MemoryRandomAccessStore implements a RandomAccessStore backed by a byte slice.

func NewMemoryRandomAccessStore

func NewMemoryRandomAccessStore() *MemoryRandomAccessStore

func (*MemoryRandomAccessStore) Close

func (s *MemoryRandomAccessStore) Close() error

func (*MemoryRandomAccessStore) ReadAt

func (s *MemoryRandomAccessStore) ReadAt(p []byte, offset int64) (int, error)

func (*MemoryRandomAccessStore) Size

func (s *MemoryRandomAccessStore) Size() (int64, error)

func (*MemoryRandomAccessStore) WriteAt

func (s *MemoryRandomAccessStore) WriteAt(p []byte, offset int64) (int, error)

type MemoryRandomAccessStoreFactory

type MemoryRandomAccessStoreFactory struct{}

func (*MemoryRandomAccessStoreFactory) RandomAccessStore

func (ras *MemoryRandomAccessStoreFactory) RandomAccessStore() (RandomAccessStore, error)

type Named

type Named interface {
	Name() string
}

Named is an I/O concept for a named blob. An I/O channel (or stream) backed by such a blob may also have this.

type NamedRandomAccessStore

type NamedRandomAccessStore interface {
	RandomAccessStore
	Name() string
}

NamedRandomAccessStore models an I/O channel for a named blob (probably a file)

type PathBuilder

type PathBuilder func(ctx interface{}) (string, error)

PathBuilder is supposed to return the path to the file to write the data to. The argument is the value passed as the second argument of WriteWithCtx().

type RandomAccessStore

type RandomAccessStore interface {
	io.ReaderAt
	io.WriterAt
	io.Closer
}

RandomAccessStore models an I/O channel for a blob.

type RandomAccessStoreFactory

type RandomAccessStoreFactory interface {
	RandomAccessStore() (RandomAccessStore, error)
}

RandomAccessStoreFactory creates a RandomAccessStore instance.

type RotationCallback

type RotationCallback func(ID, path string, ctx interface{}) error

RotationCallback is called when rotation occurs. Typically the callback would rename the file specified by path to something like xxx.1 so that the generated files are rotating.

func SerialRotationCallbackFactory

func SerialRotationCallbackFactory(maxFiles int) RotationCallback

This is a factory function that returns a typical implementation of RotationCallback which move the file specified by path argument to the one suffixed by ".1" after moving the file in the destination path to that with the suffix changed to what the number part is incremented by one (".2" for ".1"). Renaming is done accordingly until at most maxFile number of files remain.

type SeekerWrapper

type SeekerWrapper struct {
	// contains filtered or unexported fields
}

SeekerWrapper wraps a RandomAccessStore for it to behave as io.Seeker.

func NewSeekerWrapper

func NewSeekerWrapper(s RandomAccessStore) *SeekerWrapper

Creates a new SeekerWrapper instance.

func (*SeekerWrapper) Close

func (s *SeekerWrapper) Close() error

Just delegates the operation to the underlying RandomAccessStore's Close() method.

func (*SeekerWrapper) Name

func (s *SeekerWrapper) Name() string

If the underlying RandomAccessStore also provides NamedRandomAccessStore, delegates the call to its Name() method. Otherwise, returns an empty string.

func (*SeekerWrapper) ReadAt

func (s *SeekerWrapper) ReadAt(p []byte, offset int64) (int, error)

Just delegates the operation to the underlying RandomAccessStore's ReadAt() method.

func (*SeekerWrapper) Size

func (s *SeekerWrapper) Size() (int64, error)

Just delegates the operation to the underlying RandomAccessStore's Size() method.

func (*SeekerWrapper) WriteAt

func (s *SeekerWrapper) WriteAt(p []byte, offset int64) (int, error)

Just delegates the operation to the underlying RandomAccessStore's WriteAt() method.

type Sized

type Sized interface {
	Size() (int64, error)
}

Sized is an I/O concept for a blob of a specific size. An I/O channel (or stream) backed by such a blob may also have this.

type SizedRandomAccessStore

type SizedRandomAccessStore interface {
	RandomAccessStore
	Size() (int64, error)
}

SizedRandomAccessStore models an I/O channel for a blob is supposed to have a specific size.

type StaticRotatingWriter

type StaticRotatingWriter struct {
	PathBuilder          PathBuilder
	WriterFactory        WriterFactory
	CloseErrorReportChan chan<- CloserErrorPair
	// contains filtered or unexported fields
}

StaticRotatingWriter is an io.Writer that writes the data to the file whose path is determined by the given PathBuilder. It can be used in combination with the standard log package to support logging to rotating files.

func NewStaticRotatingWriter

func NewStaticRotatingWriter(pathBuilder PathBuilder, writerFactory WriterFactory, closeErrorReportChan chan<- CloserErrorPair) *StaticRotatingWriter

Creates a new StaticRotatingWriter. Pass StandardWriterFactory as writerFactory if you aren't interested in any contextual information passed as the second argument of WriteWithCtx() when opening the file. closeErrorReportChan is a channel that will asynchronously receive errors that occur during closing files that have been opened bby writerFastory. closeErrorReportChan can be nil.

func (*StaticRotatingWriter) Close

func (w *StaticRotatingWriter) Close() error

Closes the opened files. It needs to be made sure that this is called after all the ongoing write operations have been done. Otherwise the files may be left open.

func (*StaticRotatingWriter) Write

func (w *StaticRotatingWriter) Write(b []byte) (int, error)

Write() method of io.Writer() interface. This simply calls WriteWithCtx() with the second argument being nil.

func (*StaticRotatingWriter) WriteWithCtx

func (w *StaticRotatingWriter) WriteWithCtx(b []byte, ctx interface{}) (int, error)

WriteWithCtx() method of ContextualWriter interface. This function is designed to be reentrant, and takes care of the situation where multiple writes to the different files occur simultaneously.

type StoreReadWriter

type StoreReadWriter struct {
	Store    RandomAccessStore
	Position int64
	Size     int64
}

StoreReadWriter wraps a RandomAccessStore for it to behave like io.Reader or io.Writer.

func (*StoreReadWriter) Close

func (rw *StoreReadWriter) Close() error

func (*StoreReadWriter) Read

func (rw *StoreReadWriter) Read(p []byte) (int, error)

func (*StoreReadWriter) Seek

func (rw *StoreReadWriter) Seek(pos int64, whence int) (int64, error)

func (*StoreReadWriter) Write

func (rw *StoreReadWriter) Write(p []byte) (int, error)

type TempFileRandomAccessStoreFactory

type TempFileRandomAccessStoreFactory struct {
	Dir    string
	Prefix string
	GCChan chan *os.File
}

TempFileRandomAccessStoreFactory implements a RandomAccessStore backed by a temporary file that is created by ioutil.TempFIle. If the RandomAccessStore is closed, the underlying temporary file is deleted accordingly.

func (*TempFileRandomAccessStoreFactory) RandomAccessStore

func (ras *TempFileRandomAccessStoreFactory) RandomAccessStore() (RandomAccessStore, error)

type WriterFactory

type WriterFactory func(path string, ctx interface{}) (io.Writer, error)

WriterFactory is supposed to return an io.Writer object according to the arguments. The first argument is the path to the file for which io.Writer is prepared, and the second argument is the value passed as the second argument of WriteWithCtx().

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL