forked from cayleygraph/cayley
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathquadstore.go
158 lines (128 loc) · 4.98 KB
/
quadstore.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright 2014 The Cayley Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package graph
// Defines the QuadStore interface. Every backing store must implement at
// least this interface.
//
// Most of these are pretty straightforward. As long as we can surface this
// interface, the rest of the stack will "just work" and we can connect to any
// quad backing store we prefer.
import (
"context"
"errors"
"fmt"
"reflect"
"github.com/cayleygraph/cayley/graph/iterator"
"github.com/cayleygraph/cayley/graph/refs"
"github.com/cayleygraph/quad"
)
// Ref defines an opaque "quad store reference" type. However the backend wishes
// to implement it, a Ref is merely a token to a quad or a node that the
// backing store itself understands, and the base iterators pass around.
//
// For example, in a very traditional, graphd-style graph, these are int64s
// (guids of the primitives). In a very direct sort of graph, these could be
// pointers to structs, or merely quads, or whatever works best for the
// backing store.
//
// These must be comparable, or return a comparable version on Key.
type Ref = refs.Ref
func ValuesOf(ctx context.Context, qs refs.Namer, vals []Ref) ([]quad.Value, error) {
return refs.ValuesOf(ctx, qs, vals)
}
func RefsOf(ctx context.Context, qs refs.Namer, nodes []quad.Value) ([]Ref, error) {
return refs.RefsOf(ctx, qs, nodes)
}
type QuadIndexer interface {
// Given an opaque token, returns the quad for that token from the store.
Quad(Ref) quad.Quad
// Given a direction and a token, creates an iterator of links which have
// that node token in that directional field.
QuadIterator(quad.Direction, Ref) iterator.Shape
// QuadIteratorSize returns an estimated size of an iterator.
QuadIteratorSize(ctx context.Context, d quad.Direction, v Ref) (refs.Size, error)
// Convenience function for speed. Given a quad token and a direction
// return the node token for that direction. Sometimes, a QuadStore
// can do this without going all the way to the backing store, and
// gives the QuadStore the opportunity to make this optimization.
//
// Iterators will call this. At worst, a valid implementation is
//
// qs.ValueOf(qs.Quad(id).Get(dir))
//
QuadDirection(id Ref, d quad.Direction) Ref
// Stats returns the number of nodes and quads currently stored.
// Exact flag controls the correctness of the value. It can be an estimation, or a precise calculation.
// The quadstore may have a fast way of retrieving the precise stats, in this case it may ignore 'exact'
// flag and always return correct stats (with an appropriate flags set in the output).
Stats(ctx context.Context, exact bool) (Stats, error)
}
// Stats of a graph.
type Stats struct {
Nodes refs.Size // number of nodes
Quads refs.Size // number of quads
}
type QuadStore interface {
refs.Namer
QuadIndexer
// The only way in is through building a transaction, which
// is done by a replication strategy.
ApplyDeltas(in []Delta, opts IgnoreOpts) error
// NewQuadWriter starts a batch quad import process.
// The order of changes is not guaranteed, neither is the order and result of concurrent ApplyDeltas.
NewQuadWriter() (quad.WriteCloser, error)
// Returns an iterator enumerating all nodes in the graph.
NodesAllIterator() iterator.Shape
// Returns an iterator enumerating all links in the graph.
QuadsAllIterator() iterator.Shape
// Close the quad store and clean up. (Flush to disk, cleanly
// sever connections, etc)
Close() error
}
type Options map[string]interface{}
var (
typeInt = reflect.TypeOf(int(0))
)
func (d Options) IntKey(key string, def int) (int, error) {
if val, ok := d[key]; ok {
if reflect.TypeOf(val).ConvertibleTo(typeInt) {
i := reflect.ValueOf(val).Convert(typeInt).Int()
return int(i), nil
}
return def, fmt.Errorf("Invalid %s parameter type from config: %T", key, val)
}
return def, nil
}
func (d Options) StringKey(key string, def string) (string, error) {
if val, ok := d[key]; ok {
if v, ok := val.(string); ok {
return v, nil
}
return def, fmt.Errorf("Invalid %s parameter type from config: %T", key, val)
}
return def, nil
}
func (d Options) BoolKey(key string, def bool) (bool, error) {
if val, ok := d[key]; ok {
if v, ok := val.(bool); ok {
return v, nil
}
return def, fmt.Errorf("Invalid %s parameter type from config: %T", key, val)
}
return def, nil
}
var (
ErrDatabaseExists = errors.New("quadstore: cannot init; database already exists")
ErrNotInitialized = errors.New("quadstore: not initialized")
)