Skip to content

mmitou/pagecache

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pagecache

  • may be useful under conditions that there is not sufficient memory.
  • provides a cache layer that wraps object which also implements io.ReaderAt by page cache.
  • implements io.ReaderAt interface.
  • reads the wrapped underlayer by page.
  • manages the pages with page table.
  • drops a page by LRU(Least Recently Used) when the page table is full.

usage

Import pagecache, make an io.ReaderAt object wraps io.ReaderAt as below and call ReadAt.

import (
	"io"
	"github.com/mmitou/pagecache"
)

func MyRead(readerAt io.ReaderAt, buf []byte) (int, error) {
	pageSize := int64(1024)
	maxNumOfPages := int64(10)
	off := int64(0)
	pc := pagecache.NewReaderAt(readerAt, pageSize, maxNumOfPages)
	return pc.ReadAt(buf, off)
}

Example: unzip a big zip file in google cloud storage with google cloud functions and go.

1. checkout pagecache sample code

download sample.go.

git clone [email protected]:mmitou/pagecache.git

this Unzip function is defined in pagecache/sample.go.

func Unzip(ctx context.Context, e GCSEvent) error {
	o := storageClient.Bucket(e.Bucket).Object(e.Name)

	g, err := gcsreader.NewReader(ctx, o)
	if err != nil {
		return err
	}

	cra, err := NewReaderAt(g, 1048576, 10)
	if err != nil {
		return err
	}

	zr, err := zip.NewReader(cra, g.Size())
	if err != nil {
		return err
	}

	baseDir := strings.TrimSuffix(e.Name, filepath.Ext(e.Name))
	buffer := make([]byte, 32*1024)
	outputBucket := os.Getenv("OUTPUTBUCKET")
	for _, f := range zr.File {
		if f.FileInfo().IsDir() {
			continue
		}
		err := func() error {
			r, err := f.Open()
			if err != nil {
				return fmt.Errorf("Open: %v", err)
			}
			defer r.Close()

			p := filepath.Join(baseDir, f.Name)
			w := storageClient.Bucket(outputBucket).Object(p).NewWriter(ctx)
			defer w.Close()

			_, err = io.CopyBuffer(w, r, buffer)
			if err != nil {
				return fmt.Errorf("io.Copy: %v", err)
			}

			return nil
		}()
		if err != nil {
			return err
		}
	}

	return nil
}

2. make buckets for input and output in google cloud storage

gsutil mb gs://${INPUTBUCKET}
gsutil mb gs://${OUTPUTBUCKET}

3. deploy Unzip to google cloud functions

gcloud functions deploy unzip --set-env-vars OUTPUTBUCKET=${OUTPUT_BUCKET_ NAME}  --runtime go111 --entry-point Unzip --trigger-bucket=${INPUT_BUCKET_NAME} --region ${REGION_NAME} --source .

4. upload zip file you want to decompress.

gsutil cp zipfile.zip gs://${INPUT_BUCKET_NAME}

5. check out output

gsutil ls gs://${OUTPUT_BUCKET_NAME}