// sync syncs the pod data. By now it calls a syncfs on the filesystem // containing the pod's directory. func (p *pod) sync() error { cfd, err := p.Fd() if err != nil { return errwrap.Wrap(fmt.Errorf("error acquiring pod %v dir fd", p.uuid.String()), err) } if err := sys.Syncfs(cfd); err != nil { return errwrap.Wrap(fmt.Errorf("failed to sync pod %v data", p.uuid.String()), err) } return nil }
// Write renders the ACI with the provided key in the treestore // Write, to avoid having a rendered ACI with old stale files, requires that // the destination directory doesn't exist (usually Remove should be called // before Write) func (ts *TreeStore) Write(key string, s *Store) error { treepath := filepath.Join(ts.path, key) fi, _ := os.Stat(treepath) if fi != nil { return fmt.Errorf("treestore: path %s already exists", treepath) } imageID, err := types.NewHash(key) if err != nil { return fmt.Errorf("treestore: cannot convert key to imageID: %v", err) } if err := os.MkdirAll(treepath, 0755); err != nil { return fmt.Errorf("treestore: cannot create treestore directory %s: %v", treepath, err) } err = aci.RenderACIWithImageID(*imageID, treepath, s) if err != nil { return fmt.Errorf("treestore: cannot render aci: %v", err) } hash, err := ts.Hash(key) if err != nil { return fmt.Errorf("treestore: cannot calculate tree hash: %v", err) } err = ioutil.WriteFile(filepath.Join(treepath, hashfilename), []byte(hash), 0644) if err != nil { return fmt.Errorf("treestore: cannot write hash file: %v", err) } // before creating the "rendered" flag file we need to ensure that all data is fsynced dfd, err := syscall.Open(treepath, syscall.O_RDONLY, 0) if err != nil { return err } defer syscall.Close(dfd) if err := sys.Syncfs(dfd); err != nil { return fmt.Errorf("treestore: failed to sync data: %v", err) } // Create rendered file f, err := os.Create(filepath.Join(treepath, renderedfilename)) if err != nil { return fmt.Errorf("treestore: failed to write rendered file: %v", err) } f.Close() if err := syscall.Fsync(dfd); err != nil { return fmt.Errorf("treestore: failed to sync tree store directory: %v", err) } return nil }
// Write renders the ACI with the provided key in the treestore. id references // that specific tree store rendered image. // Write, to avoid having a rendered ACI with old stale files, requires that // the destination directory doesn't exist (usually Remove should be called // before Write) func (ts *TreeStore) Write(id string, key string, s *Store) (string, error) { treepath := ts.GetPath(id) fi, _ := os.Stat(treepath) if fi != nil { return "", fmt.Errorf("path %s already exists", treepath) } imageID, err := types.NewHash(key) if err != nil { return "", errwrap.Wrap(errors.New("cannot convert key to imageID"), err) } if err := os.MkdirAll(treepath, 0755); err != nil { return "", errwrap.Wrap(fmt.Errorf("cannot create treestore directory %s", treepath), err) } err = aci.RenderACIWithImageID(*imageID, treepath, s, uid.NewBlankUidRange()) if err != nil { return "", errwrap.Wrap(errors.New("cannot render aci"), err) } hash, err := ts.Hash(id) if err != nil { return "", errwrap.Wrap(errors.New("cannot calculate tree hash"), err) } err = ioutil.WriteFile(filepath.Join(treepath, hashfilename), []byte(hash), 0644) if err != nil { return "", errwrap.Wrap(errors.New("cannot write hash file"), err) } // before creating the "rendered" flag file we need to ensure that all data is fsynced dfd, err := syscall.Open(treepath, syscall.O_RDONLY, 0) if err != nil { return "", err } defer syscall.Close(dfd) if err := sys.Syncfs(dfd); err != nil { return "", errwrap.Wrap(errors.New("failed to sync data"), err) } // Create rendered file f, err := os.Create(filepath.Join(treepath, renderedfilename)) if err != nil { return "", errwrap.Wrap(errors.New("failed to write rendered file"), err) } f.Close() // Write the hash of the image that will use this tree store err = ioutil.WriteFile(filepath.Join(treepath, imagefilename), []byte(key), 0644) if err != nil { return "", errwrap.Wrap(errors.New("cannot write image file"), err) } if err := syscall.Fsync(dfd); err != nil { return "", errwrap.Wrap(errors.New("failed to sync tree store directory"), err) } treeSize, err := ts.Size(id) if err != nil { return "", err } if err := s.UpdateTreeStoreSize(key, treeSize); err != nil { return "", err } return string(hash), nil }
// render renders the ACI with the provided key in the treestore. id references // that specific tree store rendered image. // render, to avoid having a rendered ACI with old stale files, requires that // the destination directory doesn't exist (usually remove should be called // before render) func (ts *Store) render(id string, key string) (string, error) { treepath := ts.GetPath(id) fi, _ := os.Stat(treepath) if fi != nil { return "", fmt.Errorf("path %s already exists", treepath) } imageID, err := types.NewHash(key) if err != nil { return "", errwrap.Wrap(errors.New("cannot convert key to imageID"), err) } if err := os.MkdirAll(treepath, 0755); err != nil { return "", errwrap.Wrap(fmt.Errorf("cannot create treestore directory %s", treepath), err) } err = aci.RenderACIWithImageID(*imageID, treepath, ts.store, user.NewBlankUidRange()) if err != nil { return "", errwrap.Wrap(errors.New("cannot render aci"), err) } hash, err := ts.Hash(id) if err != nil { return "", errwrap.Wrap(errors.New("cannot calculate tree hash"), err) } err = ioutil.WriteFile(filepath.Join(treepath, hashfilename), []byte(hash), 0644) if err != nil { return "", errwrap.Wrap(errors.New("cannot write hash file"), err) } // before creating the "rendered" flag file we need to ensure that all data is fsynced dfd, err := syscall.Open(treepath, syscall.O_RDONLY, 0) if err != nil { return "", err } defer syscall.Close(dfd) if err := sys.Syncfs(dfd); err != nil { return "", errwrap.Wrap(errors.New("failed to sync data"), err) } // Create rendered file f, err := os.Create(filepath.Join(treepath, renderedfilename)) if err != nil { return "", errwrap.Wrap(errors.New("failed to write rendered file"), err) } f.Close() // Write the hash of the image that will use this tree store err = ioutil.WriteFile(filepath.Join(treepath, imagefilename), []byte(key), 0644) if err != nil { return "", errwrap.Wrap(errors.New("cannot write image file"), err) } if err := syscall.Fsync(dfd); err != nil { return "", errwrap.Wrap(errors.New("failed to sync tree store directory"), err) } // TODO(sgotti) this is wrong for various reasons: // * Doesn't consider that can there can be multiple treestore per ACI // (and fixing this adding/subtracting sizes is bad since cannot be // atomic and could bring to duplicated/missing subtractions causing // wrong sizes) // * ImageStore and TreeStore are decoupled (TreeStore should just use acirenderer.ACIRegistry interface) treeSize, err := ts.Size(id) if err != nil { return "", err } if err := ts.store.UpdateTreeStoreSize(key, treeSize); err != nil { return "", err } return string(hash), nil }