Skip to content

Commit 03d61ae

Browse files
authored
Feat/hashnode API (#558)
* feat(writemarker): updated WriteMarker mutex * feat(writemarker): updated CreateAt with int64 * fix(ref): load root hash node * fix(ref): added unit tests for hashnode * fix(ref): added unit tests for hashnode * feat(writemarker): updated WriteMarker mutex * feat(writemarker): updated CreateAt with int64 * fix(ref): load root hash node * fix(ref): added unit tests for hashnode * fix(ref): added unit tests for hashnode * fix(ref):fixed typo * fix(ref):fixed typo * fix(writelock):renamed connectionID with sessionID * fix(writelock):renamed connectionID with sessionID * fix(writelock):revered sessionID to connectionID * fix(gomod): upgraded gorm * feat(writemarker): fixed sql issue on postgres * feat(gomod): updated gosdk
1 parent 8ff5a54 commit 03d61ae

File tree

17 files changed

+651
-158
lines changed

17 files changed

+651
-158
lines changed

code/go/0chain.net/blobbercore/handler/context.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ func WithHandler(handler func(ctx *Context) (interface{}, error)) func(w http.Re
8484
statusCode = http.StatusInternalServerError
8585
}
8686

87-
buf, _ := json.Marshal(err)
88-
http.Error(w, string(buf), statusCode)
87+
http.Error(w, err.Error(), statusCode)
8988
return
9089
}
9190

@@ -97,8 +96,7 @@ func WithHandler(handler func(ctx *Context) (interface{}, error)) func(w http.Re
9796
statusCode = http.StatusInternalServerError
9897
}
9998

100-
buf, _ := json.Marshal(err)
101-
http.Error(w, string(buf), statusCode)
99+
http.Error(w, err.Error(), statusCode)
102100
return
103101
}
104102

code/go/0chain.net/blobbercore/handler/handler.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,10 @@ func SetupHandlers(r *mux.Router) {
7878

7979
// lightweight http handler without heavy postgres transaction to improve performance
8080

81-
r.HandleFunc("/v1/writemarker/lock/{allocation}", WithHandler(LockWriteMarker)).Methods(http.MethodPost)
82-
r.HandleFunc("/v1/writemarker/lock/{allocation}", WithHandler(UnlockWriteMarker)).Methods(http.MethodDelete)
81+
r.HandleFunc("/v1/writemarker/lock/{allocation}", WithHandler(LockWriteMarker)).Methods(http.MethodPost, http.MethodOptions)
82+
r.HandleFunc("/v1/writemarker/lock/{allocation}", WithHandler(UnlockWriteMarker)).Methods(http.MethodDelete, http.MethodOptions)
83+
84+
r.HandleFunc("/v1/hashnode/root/{allocation}", WithHandler(LoadRootHashnode)).Methods(http.MethodGet, http.MethodOptions)
8385
}
8486

8587
func WithReadOnlyConnection(handler common.JSONResponderF) common.JSONResponderF {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//go:build !integration_tests
2+
// +build !integration_tests
3+
4+
package handler
5+
6+
import "github.com/0chain/blobber/code/go/0chain.net/blobbercore/reference"
7+
8+
// LoadRootHashnode load root node with its descendant nodes
9+
func LoadRootHashnode(ctx *Context) (interface{}, error) {
10+
11+
root, err := reference.LoadRootHashnode(ctx, ctx.AllocationTx)
12+
if err != nil {
13+
return nil, err
14+
}
15+
return root, nil
16+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package handler
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
"net/http/httptest"
7+
"testing"
8+
9+
"github.com/0chain/blobber/code/go/0chain.net/blobbercore/datastore"
10+
"github.com/0chain/blobber/code/go/0chain.net/blobbercore/reference"
11+
"github.com/gorilla/mux"
12+
gomocket "github.com/selvatico/go-mocket"
13+
"github.com/stretchr/testify/require"
14+
)
15+
16+
func TestHashnodeHanders_LoadRootHashnode(t *testing.T) {
17+
18+
datastore.UseMocket(true)
19+
20+
gomocket.Catcher.NewMock().
21+
WithQuery(`SELECT allocation_id, type, name, path, content_hash, merkle_root, actual_file_hash, attributes, chunk_size,size,actual_file_size, parent_path
22+
FROM reference_objects`).
23+
WithArgs("allocation_handler_load_root").
24+
WithReply([]map[string]interface{}{
25+
{
26+
"allocation_id": "allocation_handler_load_root",
27+
"type": "D",
28+
"name": "/",
29+
"path": "/",
30+
"content_hash": "",
31+
"merkle_root": "",
32+
"actual_file_hash": "",
33+
"attributes": []byte("null"),
34+
"chunk_size": 0,
35+
"size": 0,
36+
"actual_file_size": 0,
37+
"parent_path": "",
38+
},
39+
{
40+
"allocation_id": "allocation_handler_load_root",
41+
"type": "D",
42+
"name": "sub1",
43+
"path": "/sub1",
44+
"content_hash": "",
45+
"merkle_root": "",
46+
"actual_file_hash": "",
47+
"attributes": []byte("null"),
48+
"chunk_size": 0,
49+
"size": 0,
50+
"actual_file_size": 0,
51+
"parent_path": "/",
52+
},
53+
{
54+
"allocation_id": "allocation_handler_load_root",
55+
"type": "D",
56+
"name": "sub2",
57+
"path": "/sub2",
58+
"content_hash": "",
59+
"merkle_root": "",
60+
"actual_file_hash": "",
61+
"attributes": []byte("null"),
62+
"chunk_size": 0,
63+
"size": 0,
64+
"actual_file_size": 0,
65+
"parent_path": "/",
66+
},
67+
{
68+
"allocation_id": "allocation_handler_load_root",
69+
"type": "D",
70+
"name": "file1",
71+
"path": "/sub1/file1",
72+
"content_hash": "",
73+
"merkle_root": "",
74+
"actual_file_hash": "",
75+
"attributes": []byte("null"),
76+
"chunk_size": 0,
77+
"size": 0,
78+
"actual_file_size": 0,
79+
"parent_path": "/sub1",
80+
},
81+
})
82+
83+
r := mux.NewRouter()
84+
SetupHandlers(r)
85+
86+
req, err := http.NewRequest(http.MethodGet, "/v1/refs/root/{allocation}", nil)
87+
if err != nil {
88+
t.Fatal(err)
89+
}
90+
91+
rr := httptest.NewRecorder()
92+
handler := http.HandlerFunc(WithHandler(func(ctx *Context) (interface{}, error) {
93+
ctx.AllocationTx = "allocation_handler_load_root"
94+
return LoadRootHashnode(ctx)
95+
}))
96+
97+
handler.ServeHTTP(rr, req)
98+
99+
require.Equal(t, http.StatusOK, rr.Code)
100+
101+
var root reference.Hashnode
102+
103+
err = json.Unmarshal(rr.Body.Bytes(), &root)
104+
require.Nil(t, err)
105+
106+
require.NotNil(t, root)
107+
require.Len(t, root.Children, 2)
108+
109+
require.Equal(t, root.Children[0].Name, "sub1")
110+
require.Len(t, root.Children[0].Children, 1)
111+
require.Equal(t, root.Children[0].Children[0].Name, "file1")
112+
require.Equal(t, root.Children[1].Name, "sub2")
113+
}

code/go/0chain.net/blobbercore/handler/handler_writemarker.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ var WriteMarkerMutext = &writemarker.Mutex{}
1111

1212
// LockWriteMarker try to lock writemarker for specified allocation id, and return latest RefTree
1313
func LockWriteMarker(ctx *Context) (interface{}, error) {
14-
sessionID := ctx.FormValue("session_id")
14+
connectionID := ctx.FormValue("connection_id")
1515
requestTime := ctx.FormTime("request_time")
1616

17-
result, err := WriteMarkerMutext.Lock(ctx, ctx.AllocationTx, sessionID, requestTime)
17+
result, err := WriteMarkerMutext.Lock(ctx, ctx.AllocationTx, connectionID, requestTime)
1818
if err != nil {
1919
return nil, err
2020
}
@@ -24,7 +24,7 @@ func LockWriteMarker(ctx *Context) (interface{}, error) {
2424

2525
// UnlockWriteMarker release WriteMarkerMutex
2626
func UnlockWriteMarker(ctx *Context) (interface{}, error) {
27-
sessionID := ctx.FormValue("session_id")
27+
sessionID := ctx.FormValue("connection_id")
2828

2929
err := WriteMarkerMutext.Unlock(ctx, ctx.AllocationTx, sessionID)
3030
if err != nil {

code/go/0chain.net/blobbercore/handler/handler_writemarker_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func TestWriteMarkerHandlers_Lock(t *testing.T) {
2828

2929
now := time.Now()
3030

31-
formWriter.WriteField("session_id", "session_id") //nolint: errcheck
31+
formWriter.WriteField("connection_id", "connection_id") //nolint: errcheck
3232
formWriter.WriteField("request_time", strconv.FormatInt(now.Unix(), 10)) //nolint: errcheck
3333
formWriter.Close()
3434

@@ -68,7 +68,7 @@ func TestWriteMarkerHandlers_Unlock(t *testing.T) {
6868

6969
now := time.Now()
7070

71-
formWriter.WriteField("session_id", "session_id") //nolint: errcheck
71+
formWriter.WriteField("connection_id", "connection_id") //nolint: errcheck
7272
formWriter.WriteField("request_time", strconv.FormatInt(now.Unix(), 10)) //nolint: errcheck
7373
formWriter.Close()
7474

code/go/0chain.net/blobbercore/mock/init.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package mock
22

33
import (
4+
"encoding/json"
45
"io"
56
"net/http"
67
"net/http/httptest"
78

9+
"github.com/0chain/gosdk/core/zcncrypto"
810
"github.com/0chain/gosdk/sdks"
911
"github.com/0chain/gosdk/sdks/blobber"
1012
)
@@ -18,11 +20,13 @@ const (
1820
// )
1921

2022
func NewBlobberClient() *blobber.Blobber {
21-
z := sdks.New("9a566aa4f8e8c342fed97c8928040a21f21b8f574e5782c28568635ba9c75a85", "40cd10039913ceabacf05a7c60e1ad69bb2964987bc50f77495e514dc451f907c3d8ebcdab20eedde9c8f39b9a1d66609a637352f318552fb69d4b3672516d1a", "bls0chain")
22-
err := z.InitWallet(zboxWallet)
23+
wallet := &zcncrypto.Wallet{}
24+
err := json.Unmarshal([]byte(zboxWallet), wallet) //nolint: errcheck
2325
if err != nil {
2426
panic("mock: z.InitWallet " + err.Error())
2527
}
28+
z := sdks.New("9a566aa4f8e8c342fed97c8928040a21f21b8f574e5782c28568635ba9c75a85", "40cd10039913ceabacf05a7c60e1ad69bb2964987bc50f77495e514dc451f907c3d8ebcdab20eedde9c8f39b9a1d66609a637352f318552fb69d4b3672516d1a", "bls0chain", wallet)
29+
2630
z.NewRequest = func(method, url string, body io.Reader) (*http.Request, error) {
2731
return httptest.NewRequest(method, url, body), nil
2832
}

code/go/0chain.net/blobbercore/reference/dao.go

Lines changed: 0 additions & 73 deletions
This file was deleted.
Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
package reference
22

33
import (
4-
"strconv"
5-
"strings"
6-
74
"gorm.io/datatypes"
85
)
96

10-
// HashNode ref node in hash tree
11-
type HashNode struct {
7+
// Hashnode ref node in hash tree
8+
type Hashnode struct {
129
// hash data
1310
AllocationID string `gorm:"column:allocation_id" json:"allocation_id,omitempty"`
1411
Type string `gorm:"column:type" json:"type,omitempty"`
@@ -24,46 +21,23 @@ type HashNode struct {
2421

2522
// other data
2623
ParentPath string `gorm:"parent_path" json:"-"`
27-
Children []*HashNode `gorm:"-" json:"children,omitempty"`
24+
Children []*Hashnode `gorm:"-" json:"children,omitempty"`
2825
}
2926

3027
// TableName get table name of Ref
31-
func (HashNode) TableName() string {
28+
func (Hashnode) TableName() string {
3229
return TableNameReferenceObjects
3330
}
3431

35-
func (n *HashNode) AddChild(c *HashNode) {
32+
func (n *Hashnode) AddChild(c *Hashnode) {
3633
if n.Children == nil {
37-
n.Children = make([]*HashNode, 0, 10)
34+
n.Children = make([]*Hashnode, 0, 10)
3835
}
3936

4037
n.Children = append(n.Children, c)
4138
}
4239

4340
// GetLookupHash get lookuphash
44-
func (n *HashNode) GetLookupHash() string {
41+
func (n *Hashnode) GetLookupHash() string {
4542
return GetReferenceLookup(n.AllocationID, n.Path)
4643
}
47-
48-
// GetHashCode get hash code
49-
func (n *HashNode) GetHashCode() string {
50-
51-
if len(n.Attributes) == 0 {
52-
n.Attributes = datatypes.JSON("{}")
53-
}
54-
hashArray := []string{
55-
n.AllocationID,
56-
n.Type,
57-
n.Name,
58-
n.Path,
59-
strconv.FormatInt(n.Size, 10),
60-
n.ContentHash,
61-
n.MerkleRoot,
62-
strconv.FormatInt(n.ActualFileSize, 10),
63-
n.ActualFileHash,
64-
string(n.Attributes),
65-
strconv.FormatInt(n.ChunkSize, 10),
66-
}
67-
68-
return strings.Join(hashArray, ":")
69-
}

0 commit comments

Comments
 (0)