Beispiel #1
0
func update(stm *semantic.Statement, store storage.Store, f updater) error {
	var (
		mu   sync.Mutex
		wg   sync.WaitGroup
		errs []string
	)
	appendError := func(err error) {
		mu.Lock()
		defer mu.Unlock()
		errs = append(errs, err.Error())
	}

	for _, graphBinding := range stm.Graphs() {
		wg.Add(1)
		go func(graph string) {
			defer wg.Done()
			g, err := store.Graph(graph)
			if err != nil {
				appendError(err)
				return
			}
			err = f(g, stm.Data())
			if err != nil {
				appendError(err)
			}
		}(graphBinding)
	}
	wg.Wait()
	if len(errs) > 0 {
		return errors.New(strings.Join(errs, "; "))
	}
	return nil
}
Beispiel #2
0
// getGraphFromStore returns a Graph. Will create it if it does not exist.
func getGraphFromStore(ctx context.Context, st storage.Store, id string) (storage.Graph, error) {
	g, err := st.Graph(ctx, id)
	if err == nil {
		return g, nil
	}
	return st.NewGraph(ctx, id)
}
Beispiel #3
0
// newQueryPlan returns a new query plan ready to be excecuted.
func newQueryPlan(store storage.Store, stm *semantic.Statement) (*queryPlan, error) {
	bs := []string{}
	for _, b := range stm.Bindings() {
		bs = append(bs, b)
	}
	t, err := table.New([]string{})
	if err != nil {
		return nil, err
	}
	var gs []storage.Graph
	for _, g := range stm.Graphs() {
		ng, err := store.Graph(g)
		if err != nil {
			return nil, err
		}
		gs = append(gs, ng)
	}
	return &queryPlan{
		stm:       stm,
		store:     store,
		bndgs:     bs,
		grfs:      gs,
		grfsNames: stm.Graphs(),
		cls:       stm.SortedGraphPatternClauses(),
		tbl:       t,
	}, nil
}
Beispiel #4
0
// BQLRandomGraphWalking creates the benchmark.
func BQLRandomGraphWalking(ctx context.Context, st storage.Store, chanSize int) ([]*runtime.BenchEntry, error) {
	rgSize := []int{1000, 10000}
	sizes := []int{10, 1000, 100000}
	var trplSets [][]*triple.Triple
	var ids []string
	var gids []string
	var gSizes []int
	gs, err := getGraphGenerators(rgSize)
	if err != nil {
		return nil, err
	}
	for idx, g := range gs {
		for _, s := range sizes {
			ts, err := g.Generate(s)
			if err != nil {
				return nil, err
			}
			trplSets = append(trplSets, ts)
			ids = append(ids, fmt.Sprintf("bql rg branch_factor=%04d, size=%07d", rgSize[idx], s))
			gids = append(gids, fmt.Sprintf("bql_b%d_s%d", rgSize[idx], s))
			gSizes = append(gSizes, s)
		}
	}
	var bes []*runtime.BenchEntry
	reps := []int{10}
	for bqlIdx, bqlQuery := range treeGraphWalkingBQL {
		bql := bqlQuery
		for i, max := 0, len(ids); i < max; i++ {
			for idxReps, r := range reps {
				var g storage.Graph
				gID := fmt.Sprintf("bql_rg_%d_%s_r%d_i%d", bqlIdx, gids[i], i, idxReps)
				data := trplSets[i]
				bes = append(bes, &runtime.BenchEntry{
					BatteryID: fmt.Sprintf("Run BQL random graph walking query %d", bqlIdx),
					ID:        fmt.Sprintf("%s, reps=%02d", ids[i], r),
					Triples:   gSizes[i],
					Reps:      r,
					Setup: func() error {
						var err error
						g, err = st.NewGraph(ctx, "?"+gID)
						if err != nil {
							return err
						}
						return g.AddTriples(ctx, data)
					},
					F: func() error {
						query := fmt.Sprintf(bql, gID)
						_, err := run.BQL(ctx, query, st, chanSize)
						return err
					},
					TearDown: func() error {
						return st.DeleteGraph(ctx, "?"+gID)
					},
				})
			}
		}
	}
	return bes, nil
}
Beispiel #5
0
// cleanSources create all the graph required for the story and
// populates it with the provided data.
func (s *Story) cleanSources(ctx context.Context, st storage.Store) error {
	for _, src := range s.Sources {
		if err := st.DeleteGraph(ctx, src.ID); err != nil {
			return err
		}
	}
	return nil
}
Beispiel #6
0
// RemoveExistingTreeTriplesBenchmark creates the benchmark.
func RemoveExistingTreeTriplesBenchmark(ctx context.Context, st storage.Store, chanSize int) ([]*runtime.BenchEntry, error) {
	bFactors := []int{2, 200}
	sizes := []int{10, 1000, 100000}
	var trplSets [][]*triple.Triple
	var ids []string
	var gids []string
	var gSizes []int
	gs, err := getTreeGenerators(bFactors)
	if err != nil {
		return nil, err
	}
	for idx, g := range gs {
		for _, s := range sizes {
			ts, err := g.Generate(s)
			if err != nil {
				return nil, err
			}
			trplSets = append(trplSets, ts)
			ids = append(ids, fmt.Sprintf("etg branch_factor=%04d, size=%07d", bFactors[idx], s))
			gids = append(gids, fmt.Sprintf("b%d_s%d", bFactors[idx], s))
			gSizes = append(gSizes, s)
		}
	}
	var bes []*runtime.BenchEntry
	reps := []int{10}
	for i, max := 0, len(ids); i < max; i++ {
		for idxReps, r := range reps {
			var g storage.Graph
			gID := fmt.Sprintf("remove_existing_tree_%s_r%d_i%d", gids[i], i, idxReps)
			data := trplSets[i]
			bes = append(bes, &runtime.BenchEntry{
				BatteryID: "Remove existing triples",
				ID:        fmt.Sprintf("%s, reps=%02d", ids[i], r),
				Triples:   gSizes[i],
				Reps:      r,
				Setup: func() error {
					var err error
					g, err = st.NewGraph(ctx, gID)
					if err != nil {
						return err
					}
					return g.AddTriples(ctx, data)
				},
				F: func() error {
					return g.RemoveTriples(ctx, data)
				},
				TearDown: func() error {
					return st.DeleteGraph(ctx, gID)
				},
			})
		}
	}
	return bes, nil
}
Beispiel #7
0
// Eval loads the triples in the file against as indicated by the command.
func Eval(ctx context.Context, usage string, args []string, store storage.Store, bulkSize int) int {
	if len(args) <= 3 {
		fmt.Fprintf(os.Stderr, "[ERROR] Missing required file path and/or graph names.\n\n%s", usage)
		return 2
	}
	graphs, path := strings.Split(args[len(args)-2], ","), args[len(args)-1]
	f, err := os.Create(path)
	if err != nil {
		fmt.Fprintf(os.Stderr, "[ERROR] Failed to open target file %q with error %v.\n\n", path, err)
		return 2
	}
	defer f.Close()
	var sgs []storage.Graph
	for _, gr := range graphs {
		g, err := store.Graph(ctx, gr)
		if err != nil {
			fmt.Fprintf(os.Stderr, "[ERROR] Failed to retrieve graph %q with error %v.\n\n", gr, err)
			return 2
		}
		sgs = append(sgs, g)
	}

	cnt := 0
	var errs []error
	var mu sync.Mutex
	chn := make(chan *triple.Triple, bulkSize)
	for _, vg := range sgs {
		go func(g storage.Graph) {
			err := g.Triples(ctx, chn)
			mu.Lock()
			errs = append(errs, err)
			mu.Unlock()
		}(vg)
	}

	for t := range chn {
		if _, err := f.WriteString(t.String() + "\n"); err != nil {
			fmt.Fprintf(os.Stderr, "[ERROR] Failed to write triple %s to file %q, %v.\n\n", t.String(), path, err)
			return 2
		}
		cnt++
	}
	for _, err := range errs {
		if err != nil {
			fmt.Fprintf(os.Stderr, "[ERROR] Failed to retrieve triples with error %v.\n\n", err)
			return 2
		}
	}

	fmt.Printf("Successfully written %d triples to file %q.\nTriples exported from graphs:\n\t- %s\n", cnt, path, strings.Join(graphs, "\n\t- "))
	return 0
}
Beispiel #8
0
func flush(ctx context.Context, graphs []string, store storage.Store) error {
	defer func() {
		workingTrpls = nil
	}()
	if len(workingTrpls) > 0 {
		for _, graph := range graphs {
			g, err := store.Graph(ctx, graph)
			if err != nil {
				return err
			}
			if err := g.AddTriples(ctx, workingTrpls); err != nil {
				return err
			}
		}
	}
	return nil
}
Beispiel #9
0
// REPL starts a read-evaluation-print-loop to run BQL commands.
func REPL(driver storage.Store, input *os.File, rl ReadLiner, chanSize, bulkSize, builderSize int) int {
	ctx := context.Background()
	fmt.Printf("Welcome to BadWolf vCli (%d.%d.%d-%s)\n", version.Major, version.Minor, version.Patch, version.Release)
	fmt.Printf("Using driver %q. Type quit; to exit\n", driver.Name(ctx))
	fmt.Printf("Session started at %v\n\n", time.Now())
	defer func() {
		fmt.Printf("\n\nThanks for all those BQL queries!\n\n")
	}()
	fmt.Print(prompt)
	l := ""
	for line := range rl(input) {
		nl := strings.TrimSpace(line)
		if nl == "" {
			fmt.Print(prompt)
			continue
		}
		if l != "" {
			l = l + " " + nl
		} else {
			l = nl
		}
		if !strings.HasSuffix(nl, ";") {
			// Not done with the statement.
			continue
		}
		if strings.HasPrefix(l, "quit") {
			break
		}
		if strings.HasPrefix(l, "help") {
			printHelp()
			fmt.Print(prompt)
			l = ""
			continue
		}
		if strings.HasPrefix(l, "export") {
			args := strings.Split("bw "+strings.TrimSpace(l[:len(l)-1]), " ")
			usage := "Wrong syntax\n\n\tload <graph_names_separated_by_commas> <file_path>\n"
			export.Eval(ctx, usage, args, driver, bulkSize)
			fmt.Print(prompt)
			l = ""
			continue
		}
		if strings.HasPrefix(l, "load") {
			args := strings.Split("bw "+strings.TrimSpace(l[:len(l)-1]), " ")
			usage := "Wrong syntax\n\n\tload <file_path> <graph_names_separated_by_commas>\n"
			load.Eval(ctx, usage, args, driver, bulkSize, builderSize)
			fmt.Print(prompt)
			l = ""
			continue
		}
		if strings.HasPrefix(l, "run") {
			path, cmds, err := runBQLFromFile(ctx, driver, chanSize, strings.TrimSpace(l[:len(l)-1]))
			if err != nil {
				fmt.Printf("[ERROR] %s\n\n", err)
			} else {
				fmt.Printf("Loaded %q and run %d BQL commands successfully\n\n", path, cmds)
			}
			fmt.Print(prompt)
			l = ""
			continue
		}

		table, err := runBQL(ctx, l, driver, chanSize)
		l = ""
		if err != nil {
			fmt.Printf("[ERROR] %s\n\n", err)
		} else {
			if len(table.Bindings()) > 0 {
				fmt.Println(table.String())
			}
			fmt.Println("[OK]")
		}
		fmt.Print(prompt)
	}
	return 0
}