add cache and rich put

parent ecb36a82
......@@ -9,6 +9,7 @@ import (
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
"reflect"
"sync"
"time"
)
......@@ -46,12 +47,70 @@ type Schema struct {
SAuth Auth `json:"auth"`
}
type Node struct {
Key string
Value []byte
pre *Node
next *Node
}
type LRUCache struct {
limit int
HashMap map[string]*Node
head *Node
end *Node
}
var (
defValue = "***" //查询用户权限不足的情况下默认返回值
PREFIX = "GXH"
IsUsers = false //是否启用用户权限,false 表示启用Roles
GxhSchema = "gxhSchema" //schema 存储前缀,为了实现复合主键使用。
InitSchemaLength = 12 //初始化时schema 的长度
schemaCache = Constructor(InitSchemaLength)
once = sync.Once{}
)
func initSchema(stub shim.ChaincodeStubInterface)error{
var errinfo error
once.Do(func(){
schemaIterator,err := stub.GetStateByPartialCompositeKey(GxhSchema,nil)
if err != nil {
errinfo = err
return
}
defer schemaIterator.Close()
index := 1
for schemaIterator.HasNext(){
querykv,err := schemaIterator.Next()
if err != nil {
errinfo = err
return
}
fmt.Println("add cache key:",querykv.Key)
_,compisiteKeys ,err := stub.SplitCompositeKey(querykv.Key)
if err!=nil{
errinfo = err
return
}
schemaCache.Put(compisiteKeys[0],querykv.Value)
fmt.Println("add cache key:",querykv.Key)
index++
if index > InitSchemaLength {
fmt.Println("cache data length :",len(schemaCache.HashMap))
return
}
}
fmt.Println("cache data length :",len(schemaCache.HashMap))
return
})
if errinfo != nil{
return errinfo
}
return nil
}
// Init does nothing for this cc
func (t *GXHCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success([]byte("GXHCC init successful! "))
......@@ -61,7 +120,10 @@ func (t *GXHCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
func (t *GXHCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
// get arguments and transient
functionName, args := stub.GetFunctionAndParameters()
err := initSchema(stub)
if err !=nil{
return shim.Error(err.Error())
}
switch functionName {
case "authority":
......@@ -90,7 +152,12 @@ func (t *GXHCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Error(fmt.Sprintf("update data function err: %s", err))
}
return shim.Success([]byte(res))
case "getCertCommonName":
name,err := getCertificateCommonName(stub)
if err != nil{
return shim.Error(fmt.Sprintf("get certificate CommonName fail,err: %s",err))
}
return shim.Success([]byte("current user certificate commonname :" +name))
default:
return shim.Error(fmt.Sprintf("Unsupported function %s", functionName))
}
......@@ -142,6 +209,10 @@ func put(args []string, stub shim.ChaincodeStubInterface) (string, error) {
if err := stub.PutState(PREFIX+"_"+args[0]+"_"+Id.(string), putDate); err != nil {
return "", fmt.Errorf("PutState fail, err :%s", err)
}
err := tableDifferentiate(args[0],mapres,stub)
if err != nil{
return "", err
}
}
return fmt.Sprintf("%s put data success!", args[0]), nil
}
......@@ -331,6 +402,7 @@ func SchemaProcess(args []string, stub shim.ChaincodeStubInterface) (string, err
return schema.update(args[1:], stub)
case "get":
return schema.getSchema(args[1], stub)
default:
return "", fmt.Errorf(fmt.Sprintf("Unsupported schema function of %s", args[0]))
......@@ -365,13 +437,22 @@ func (this *Schema) put(args []string, stub shim.ChaincodeStubInterface) (string
if !ok {
return "", fmt.Errorf("The id field must exist ")
}
if value, _ := stub.GetState(PREFIX+"_"+args[0]); value != nil {
CompositeKey,err := stub.CreateCompositeKey(GxhSchema,[]string{args[0]})
if err != nil{
return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", args[0],err)
}
if schemaCache.Get(args[0]) != nil {
fmt.Println("schemaCache.Get err")
return "", fmt.Errorf("the schema %s already exists and cannot be added", args[0])
}else if value, _ := stub.GetState(CompositeKey); value != nil {
fmt.Println("GetState.Get err")
return "", fmt.Errorf("the schema %s already exists and cannot be added", args[0])
}
putDate, _ := json.Marshal(schema) //处理重复字段
if err := stub.PutState(PREFIX+"_"+args[0], putDate); err != nil {
if err := stub.PutState(CompositeKey, putDate); err != nil {
return "", fmt.Errorf("Schema PutState fail,err: %s ", err)
}
schemaCache.Put(args[0],putDate)
return fmt.Sprintf("%s schema put success!", args[0]), nil
}
......@@ -399,12 +480,19 @@ func (this *Schema) update(args []string, stub shim.ChaincodeStubInterface) (str
if !ok {
return "", fmt.Errorf("The id field must exist ")
}
result, err := stub.GetState(PREFIX+"_"+args[0])
if err != nil || result == nil {
return "", fmt.Errorf("%s schema data doesn't exist,please check your parameters ",args[0])
CompositeKey,err := stub.CreateCompositeKey(GxhSchema,[]string{args[0]})
if err != nil{
return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", args[0],err)
}
if err := json.Unmarshal([]byte(result), &schema); err != nil {
var result []byte
if result = schemaCache.Get(args[0]);result == nil{
fmt.Println("schemaCache.Get nil")
result, err := stub.GetState(CompositeKey)
if err != nil || result == nil {
return "", fmt.Errorf("%s schema data doesn't exist,please check your parameters ",args[0])
}
}
if err := json.Unmarshal(result, &schema); err != nil {
return "", fmt.Errorf("The parameters Unmarshal to a Schema structural fail, err: %s ", err)
}
commonName, err := getCertificateCommonName(stub)
......@@ -414,25 +502,44 @@ func (this *Schema) update(args []string, stub shim.ChaincodeStubInterface) (str
if ok,err := authorityCheck(schema.SchemaAuth.Write,commonName);!ok{
return "", fmt.Errorf("update %s schema fail,err: %s ",args[0],err)
}
if err = stub.PutState(PREFIX+"_"+args[0], []byte(args[1]));err != nil{
if err = stub.PutState(CompositeKey, []byte(args[1]));err != nil{
return "", fmt.Errorf("%s schema data PutState fail,please try again ",args[0])
}
schemaCache.Put(args[0],[]byte(args[1]))
return fmt.Sprintf("%s schema update success!", args[0]), err
}
func (this *Schema) get(args string, stub shim.ChaincodeStubInterface) (string, error) {
result, err := stub.GetState(PREFIX+"_"+args)
if err != nil || result == nil {
return "", fmt.Errorf("GetSchema %s data fail,please check your parameters:err : %s ",args,err)
var result []byte
if result = schemaCache.Get(args);result == nil{
fmt.Println("schemaCache.Get nil")
CompositeKey,err := stub.CreateCompositeKey(GxhSchema,[]string{args})
if err != nil{
return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", args,err)
}
result, err = stub.GetState(CompositeKey)
if err != nil || result == nil {
return "", fmt.Errorf("%s schema data doesn't exist,please check your parameters ",args)
}
schemaCache.Put(args,result)
}
return string(result), nil
}
func (this *Schema) getSchema(args string, stub shim.ChaincodeStubInterface)(string, error) {
result, err := stub.GetState(PREFIX+"_"+args)
if err != nil || result == nil {
return "", fmt.Errorf("GetSchema %s data fail,please check your parameters:err : %s ",args,err)
var result []byte
if result = schemaCache.Get(args);result == nil{
fmt.Println("schemaCache.Get nil")
CompositeKey,err := stub.CreateCompositeKey(GxhSchema,[]string{args})
if err != nil{
return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", args,err)
}
result, err = stub.GetState(CompositeKey)
if err != nil || result == nil {
return "", fmt.Errorf("%s schema data doesn't exist,please check your parameters ",args)
}
schemaCache.Put(args,result)
}
if err := json.Unmarshal(result, this); err != nil {
return "", fmt.Errorf("SchemaData Unmarshal fail, err: %s", err)
......@@ -448,7 +555,6 @@ func (this *Schema) getSchema(args string, stub shim.ChaincodeStubInterface)(str
}
func getCertificateCommonName(stub shim.ChaincodeStubInterface) (string, error) {
return "Admin@org2.example.com",nil
creatorByte, _ := stub.GetCreator()
certStart := bytes.IndexAny(creatorByte, "-----BEGIN")
if certStart == -1 {
......@@ -459,7 +565,6 @@ func getCertificateCommonName(stub shim.ChaincodeStubInterface) (string, error)
if bl == nil {
return "", fmt.Errorf("Could not decode the PEM structure ")
}
cert, err := x509.ParseCertificate(bl.Bytes)
if err != nil {
return "", fmt.Errorf("ParseCertificate failed")
......@@ -614,6 +719,143 @@ func fieldCheckout(check *Checks,val interface{})error{
return nil
}
/*
根据参数区分不同的表,并执行不同的操作
*/
func tableDifferentiate(tableName string,value map[string]interface{}, stub shim.ChaincodeStubInterface)(error){
switch tableName {
case "alibusi":
return alibusiCompositeKey(tableName,value, stub)
case "alibusirecord":
//return addAlibusirecord(tableName,value, stub)
case "merchants":
//return merchantsLeadger(tableName,value, stub)
case "couincomingparts":
//return addMerchantsale(args[1:],stub)
case "merchantsale":
//return addMerchantsale(tableName,value, stub)
case "coutickets":
//return couticketsLeadger(tableName,value, stub)
case "coutcantm":
//return coutcantmLeadger(tableName,value, stub)
case "couticketcodes":
//return coupartnersLeadger(args[1:],stub)
case "coupartners":
//return coupartnersLeadger(tableName,value, stub)
case "couticketorders":
// return addCouticketorders(tableName,value,stub)
default:
return fmt.Errorf(fmt.Sprintf("Unsupported table name of %s", tableName))
}
return nil
}
func alibusiCompositeKey(tableName string,value map[string]interface{}, stub shim.ChaincodeStubInterface)error{
valBy,_ := json.Marshal(value)
Id := value["id"].(string)
aname,ok := value["aname"].(string)
if !ok{
return fmt.Errorf("aname fields type not string! ")
}
anamecomKey,err :=stub.CreateCompositeKey(tableName,[]string{aname,Id})
if err!=nil{
return err
}
alinkman,ok := value["alinkman"].(string)
if !ok{
return fmt.Errorf("alinkman fields type not string! ")
}
alinkmancomKey,err :=stub.CreateCompositeKey(tableName,[]string{alinkman,Id})
if err!=nil{
return err
}
amob,ok := value["amob"].(string)
if !ok{
return fmt.Errorf("amob fields type not string! ")
}
amobcomKey,err :=stub.CreateCompositeKey(tableName,[]string{amob,Id})
if err!=nil{
return err
}
if err := stub.PutState(anamecomKey, valBy); err != nil {
return fmt.Errorf("Put %s date fail, err :%s ",anamecomKey, err)
}
if err := stub.PutState(alinkmancomKey, valBy); err != nil {
return fmt.Errorf("Put %s date fail, err :%s ",alinkmancomKey, err)
}
if err := stub.PutState(amobcomKey, valBy); err != nil {
return fmt.Errorf("Put %s date fail, err :%s ",amobcomKey, err)
}
return nil
}
func Constructor(capacity int) LRUCache{
lruCache := LRUCache{limit:capacity}
lruCache.HashMap = make(map[string]*Node, capacity)
return lruCache
}
func (l *LRUCache) Get(key string) []byte {
if v,ok:= l.HashMap[key];ok {
l.refreshNode(v)
return v.Value
}else {
return nil
}
}
func (l *LRUCache) Put(key string, value []byte) {
if v,ok := l.HashMap[key];!ok{
if len(l.HashMap) >= l.limit{
oldKey := l.removeNode(l.head)
delete(l.HashMap, oldKey)
}
node := Node{Key:key, Value:value}
l.addNode(&node)
l.HashMap[key] = &node
}else {
v.Value = value
l.refreshNode(v)
}
}
func (l *LRUCache) refreshNode(node *Node){
if node == l.end {
return
}
l.removeNode(node)
l.addNode(node)
}
func (l *LRUCache) removeNode(node *Node) string{
if node == l.end {
l.end = l.end.pre
l.end.next = nil
}else if node == l.head {
l.head = l.head.next
l.head.pre = nil
}else {
node.pre.next = node.next
node.next.pre = node.pre
}
return node.Key
}
func (l *LRUCache) addNode(node *Node){
if l.end != nil {
l.end.next = node
node.pre = l.end
node.next = nil
}
l.end = node
if l.head == nil {
l.head = node
}
}
func main() {
err := shim.Start(&GXHCC{})
if err != nil {
......
......@@ -7,6 +7,24 @@ import (
"testing"
)
var schemaCheck = `{"fields":{"alinkman":{"val":10.34,"auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1583501961}},"write":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1583501961}}},"fcheck":{"ftype":"float64","must":true,"fieldlen":1}},
"amob":{"val":"0001-01-01T00:00:00Z","auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1583501961}},"write":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":
1583501961}}},"fcheck":{"ftype":"time.Time","must":true,"fieldlen":0}},"aname":{"val":"Aname","auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1583501961}},"write":{"users":{"Admin@org2.example.com":0},
"roles":{"Admin@org2.example.com":1583501961}}},"fcheck":{"ftype":"string","must":true,"fieldlen":16}},"atype":{"val":100,
"auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1583501961}},"write":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1583501961}}},"fcheck":{"ftype":"int",
"must":true,"fieldlen":1}},"backup":{"val":{"aname":"Aname","atype":"Atype"},"auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1583501961}},"write":{"users":{"Admin@org2.example.com":0},
"roles":{"Admin@org2.example.com":1583501961}}},"fcheck":null},"id":{"val":"1","auth":{"read":{"users":null,"roles":null},
"write":{"users":null,"roles":null}},"fcheck":null}},"schema_auth":{"read":{"users":null,"roles":null},"write":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1583501961}}},"auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":0}},"write":{"users":{"Admin@org2.example.com":0},
"roles":{"Admin@org2.example.com":0}}}}
`
var schema = `{"fields":{"alinkman":{"val":"Alinkman","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}},"amob":{"val":"Amob","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
......@@ -56,7 +74,7 @@ func TestGXHSchemaAuth(t *testing.T){
fmt.Println("========================================invoke schema put============================================")
fmt.Println()
fmt.Println()
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("alibusi"),[]byte(schema)})
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("alibusi"),[]byte(schemaCheck)})
fmt.Printf("Invoke status %d,message %s and payload %s\n",
responseByPutschema.Status,responseByPutschema.Message,string(responseByPutschema.Payload))
fmt.Println()
......@@ -187,24 +205,7 @@ func TestFieldCheck(t *testing.T){
}
}
var schemaCheck = `{"fields":{"alinkman":{"val":10.34,"auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1583501961}},"write":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1583501961}}},"fcheck":{"ftype":"float64","must":true,"fieldlen":1}},
"amob":{"val":"0001-01-01T00:00:00Z","auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1583501961}},"write":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":
1583501961}}},"fcheck":{"ftype":"time.Time","must":true,"fieldlen":0}},"aname":{"val":"Aname","auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1583501961}},"write":{"users":{"Admin@org2.example.com":0},
"roles":{"Admin@org2.example.com":1583501961}}},"fcheck":{"ftype":"string","must":true,"fieldlen":16}},"atype":{"val":100,
"auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1583501961}},"write":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1583501961}}},"fcheck":{"ftype":"int",
"must":true,"fieldlen":1}},"backup":{"val":{"aname":"Aname","atype":"Atype"},"auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1583501961}},"write":{"users":{"Admin@org2.example.com":0},
"roles":{"Admin@org2.example.com":1583501961}}},"fcheck":null},"id":{"val":"1","auth":{"read":{"users":null,"roles":null},
"write":{"users":null,"roles":null}},"fcheck":null}},"schema_auth":{"read":{"users":null,"roles":null},"write":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1583501961}}},"auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":0}},"write":{"users":{"Admin@org2.example.com":0},
"roles":{"Admin@org2.example.com":0}}}}
`
var (
inputC = `{"id":"1","aname":"alibusi","atype":1000,"alinkman":1.233,
"amob":"new1234567890","backup":{"aname":"alibusi","atype":"type"}}`
......
package main
import (
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
"testing"
)
func TestGetCommonName(t *testing.T){
cc := new(GXHCC)
stub := shim.NewMockStub("GXHCC",cc)
stub.MockInit("init",nil)
fmt.Println()
fmt.Println("========================================invoke schema put============================================")
fmt.Println()
fmt.Println()
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("getCertCommonName")})
fmt.Printf("Invoke status %d,message %s and payload %s\n",
responseByPutschema.Status,responseByPutschema.Message,string(responseByPutschema.Payload))
}
//7455 162316 ns/op
//5402 214421 ns/op
func BenchmarkPut(b *testing.B){
cc := new(GXHCC)
stub := shim.NewMockStub("GXHCC",cc)
stub.MockInit("init",nil)
fmt.Println()
fmt.Println("========================================invoke schema put============================================")
fmt.Println()
fmt.Println()
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("alibusi"),[]byte(schemaCheck)})
fmt.Printf("Invoke status %d,message %s and payload %s\n",
responseByPutschema.Status,responseByPutschema.Message,string(responseByPutschema.Payload))
fmt.Println()
fmt.Println("========================================invoke schema get============================================")
fmt.Println()
fmt.Println()
responseByget := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("get"),[]byte("alibusi")})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget.Status,responseByget.Message,string(responseByget.Payload))
for i:=0;i<b.N ;i++ {
responseByPut := stub.MockInvoke("invoke1",[][]byte{[]byte("put"), []byte("alibusi"),[]byte(inputCs)})
if responseByPut.Status != 200{
fmt.Println()
fmt.Println("========================================invoke data put============================================")
fmt.Println()
fmt.Println()
fmt.Printf("Invoke status %d,message %s ,and payload %s\n",
responseByPut.Status,responseByPut.Message,string(responseByPut.Payload))
return
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment