Skip to content

Commit 83f9fa1

Browse files
committed
initial import
Signed-off-by: Vasiliy Tolstov <v.tolstov@selfip.ru>
0 parents  commit 83f9fa1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+4302
-0
lines changed

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2016-2018 sdstack and other authors.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
storage
2+
=======
3+

api/api.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package api
2+
3+
/*
4+
import (
5+
"fmt"
6+
"strings"
7+
8+
"github.com/sdstack/storage/kv"
9+
)
10+
11+
var apiTypes map[string]Api
12+
13+
func init() {
14+
apiTypes = make(map[string]Api)
15+
}
16+
17+
func RegisterApi(engine string, api Api) {
18+
apiTypes[engine] = proxy
19+
}
20+
21+
// Proxy represents proxy interface
22+
type Proxy interface {
23+
Start() error
24+
Stop() error
25+
Configure(*kv.KV, interface{}) error
26+
// Format() error
27+
// Check() error
28+
// Recover() error
29+
// Info() (*Info, error)
30+
// Snapshot() error
31+
// Reweight() error
32+
// Members() []Member
33+
}
34+
35+
func New(ptype string, cfg interface{}, engine *kv.KV) (Proxy, error) {
36+
var err error
37+
38+
proxy, ok := proxyTypes[ptype]
39+
if !ok {
40+
return nil, fmt.Errorf("unknown proxy type %s, only %s supported", ptype, strings.Join(ProxyTypes(), ","))
41+
}
42+
43+
err = proxy.Configure(engine, cfg)
44+
if err != nil {
45+
return nil, err
46+
}
47+
48+
return proxy, nil
49+
}
50+
51+
func ProxyTypes() []string {
52+
var ptypes []string
53+
for ptype, _ := range proxyTypes {
54+
ptypes = append(ptypes, ptype)
55+
}
56+
return ptypes
57+
}
58+
*/

backend/backend.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package backend
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"io"
7+
"strings"
8+
)
9+
10+
/*
11+
You could do "files" as variable length blocks, where you have a list of blocks needed to reconstruct. To insert data you create a new block, keep the original, but specify that you only need parts of the data.
12+
A file is a list of blocks. When you insert new data, you create a new block, and adjust start/end of affected blocks.
13+
This allows you to insert data at the same speed as end-of-file writes. You can add some lazy cleanup, that removes unused parts of blocks and recompresses them, but the important part is that you do not need to do that when the file is updated.
14+
There will only be a read overhead when "start" of a block is >0. That will be the same for using "ReadAt". You skip in your blocks until you get to the position you want and start decoding from there.
15+
If blocks are stored based on their uncompressed hash, you furthermore get a coarse high-level deduplication, though that of course makes it more difficult to figure out when a block is no longer used by any file.
16+
With that, you should get pretty good performance, even with block sizes up to 16-64MB.
17+
For each block, I would probably go with variably sized de-duplication, with a 4K average, and deflate the result @level 1. That should give you ~50-60MB/core throughput. If you need higher write throughput, you can always set deflate to level 0 (store), and leave it up to a lazy task to compress the data. That should give you about 150MB/core. Obviously you can de-duplicate/compress several blocks in parallel.
18+
*/
19+
20+
/*
21+
type File struct {
22+
Name string
23+
Size uint64
24+
Blocks []Block
25+
Ring *config.Ring
26+
}
27+
28+
type Block struct {
29+
Start uint64
30+
Stop uint64
31+
Size uint64
32+
}
33+
*/
34+
35+
var (
36+
ErrIO = errors.New("IO error")
37+
)
38+
39+
var backendTypes map[string]Backend
40+
41+
func init() {
42+
backendTypes = make(map[string]Backend)
43+
}
44+
45+
func RegisterBackend(engine string, backend Backend) {
46+
backendTypes[engine] = backend
47+
}
48+
49+
func New(btype string, cfg interface{}) (Backend, error) {
50+
var err error
51+
52+
backend, ok := backendTypes[btype]
53+
if !ok {
54+
return nil, fmt.Errorf("unknown backend type %s. only %s supported", btype, strings.Join(BackendTypes(), ","))
55+
}
56+
57+
if cfg == nil {
58+
return backend, nil
59+
}
60+
61+
err = backend.Init(cfg)
62+
if err != nil {
63+
return nil, err
64+
}
65+
66+
return backend, nil
67+
}
68+
69+
func BackendTypes() []string {
70+
var btypes []string
71+
for btype, _ := range backendTypes {
72+
btypes = append(btypes, btype)
73+
}
74+
return btypes
75+
}
76+
77+
type Backend interface {
78+
Configure(interface{}) error
79+
Init(interface{}) error
80+
ReaderFrom(string, io.Reader, int64, int64, int, int) (int64, error)
81+
WriterTo(string, io.Writer, int64, int64, int, int) (int64, error)
82+
WriteAt(string, []byte, int64, int, int) (int, error)
83+
ReadAt(string, []byte, int64, int, int) (int, error)
84+
Allocate(string, int64, int, int) error
85+
Remove(string, int, int) error
86+
Exists(string, int, int) (bool, error)
87+
}

backend/block/block.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package block
2+
3+
/*
4+
import (
5+
"fmt"
6+
"os"
7+
8+
"github.com/mitchellh/mapstructure"
9+
"golang.org/x/sys/unix"
10+
"github.com/sdstack/storage/backend"
11+
)
12+
13+
type StoreBlock struct {
14+
store []string
15+
}
16+
17+
type ObjectBlock struct {
18+
fs *StoreBlock
19+
fp *os.File
20+
}
21+
22+
func init() {
23+
backend.RegisterBackend("block", &StoreBlock{})
24+
}
25+
func (s *StoreBlock) Init(data interface{}) error {
26+
var err error
27+
28+
err = mapstructure.Decode(data, &s.store)
29+
if err != nil {
30+
return err
31+
}
32+
fmt.Printf("%#+v\n", s)
33+
return nil
34+
}
35+
36+
func (s *StoreBlock) Configure(data interface{}) error {
37+
var err error
38+
39+
err = mapstructure.Decode(data, &s.store)
40+
if err != nil {
41+
return err
42+
}
43+
fmt.Printf("%#+v\n", s)
44+
return nil
45+
}
46+
47+
func (s *StoreBlock) Open() error {
48+
return nil
49+
}
50+
51+
func (s *StoreBlock) Close() error {
52+
return nil
53+
}
54+
55+
func (o *ObjectBlock) Allocate(mode uint64, offset uint64, length uint64) error {
56+
return unix.Fallocate(int(o.fp.Fd()), uint32(mode), int64(offset), int64(length))
57+
}
58+
59+
func (o *ObjectBlock) Delete(flags uint64) error {
60+
return nil
61+
// return os.Remove(filepath.Join())
62+
}
63+
64+
func (o *ObjectBlock) ReadAt(data []byte, offset uint64, flags uint64) (uint64, error) {
65+
return 0, nil
66+
}
67+
68+
func (o *ObjectBlock) WriteAt(data []byte, offset uint64, flags uint64) (uint64, error) {
69+
return 0, nil
70+
}
71+
72+
func (o *ObjectBlock) Read(data []byte) (int, error) {
73+
return o.fp.Read(data)
74+
}
75+
76+
func (o *ObjectBlock) Write(data []byte) (int, error) {
77+
return o.fp.Write(data)
78+
}
79+
80+
func (o *ObjectBlock) Seek(offset int64, whence int) (int64, error) {
81+
return o.fp.Seek(offset, whence)
82+
}
83+
84+
func (o *StoreBlock) ObjectExists(name string) (bool, error) {
85+
_, err := os.Stat(name)
86+
return os.IsNotExist(err), nil
87+
}
88+
89+
func (o *ObjectBlock) Sync() error {
90+
return o.fp.Sync()
91+
}
92+
93+
func (o *ObjectBlock) Close() error {
94+
return o.fp.Close()
95+
}
96+
97+
func (o *ObjectBlock) Remove() error {
98+
return nil
99+
}
100+
*/

0 commit comments

Comments
 (0)