func (d *driver) createRepoState(repo *pfs.Repo) { if _, ok := d.diffs[repo.Name]; ok { return // this function is idempotent } d.diffs[repo.Name] = make(map[uint64]map[string]*pfs.DiffInfo) d.dags[repo.Name] = dag.NewDAG(nil) d.branches[repo.Name] = make(map[string]string) }
func (d *driver) AddShard(shard uint64) error { blockClient, err := d.getBlockClient() if err != nil { return err } listDiffClient, err := blockClient.ListDiff(context.Background(), &pfs.ListDiffRequest{Shard: shard}) if err != nil { return err } diffInfos := make(diffMap) dags := make(map[string]*dag.DAG) for { diffInfo, err := listDiffClient.Recv() if err != nil && err != io.EOF { return err } if err == io.EOF { break } if diffInfo.Diff == nil || diffInfo.Diff.Commit == nil || diffInfo.Diff.Commit.Repo == nil { return fmt.Errorf("broken diff info: %v; this is likely a bug", diffInfo) } repoName := diffInfo.Diff.Commit.Repo.Name if _, ok := diffInfos[repoName]; !ok { diffInfos[repoName] = make(map[uint64]map[string]*pfs.DiffInfo) dags[repoName] = dag.NewDAG(nil) } updateDAG(diffInfo, dags[repoName]) if err := diffInfos.insert(diffInfo); err != nil { return err } } for repoName, dag := range dags { if ghosts := dag.Ghosts(); len(ghosts) != 0 { return fmt.Errorf("error adding shard %d, repo %s has ghost commits: %+v", shard, repoName, ghosts) } } d.lock.Lock() defer d.lock.Unlock() for repoName, dag := range dags { for _, commitID := range dag.Sorted() { d.createRepoState(client.NewRepo(repoName)) if diffInfo, ok := diffInfos.get(client.NewDiff(repoName, commitID, shard)); ok { if err := d.insertDiffInfo(diffInfo); err != nil { return err } if diffInfo.Finished == nil { return fmt.Errorf("diff %s/%s/%d is not finished; this is likely a bug", repoName, commitID, shard) } } else { return fmt.Errorf("diff %s/%s/%d not found; this is likely a bug", repoName, commitID, shard) } } } return nil }