-
Notifications
You must be signed in to change notification settings - Fork 2
/
removerCC.go
143 lines (120 loc) · 5.04 KB
/
removerCC.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
package statemanager
import (
"fmt"
"strconv"
"strings"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
var logger = shim.NewLogger("RemoverCCLog")
// Key for storing namespaces on the blockchain
const Key = "fabric-state-manager"
// RemoverCC chaincode structure
type RemoverCC struct {
}
// Init initializes chaincode
func (t *RemoverCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
logger.Info("########### RemoverCC Init ###########")
methodName := "Init()"
_, args := stub.GetFunctionAndParameters()
t.Initialize(stub, args)
logger.Infof("- End execution - %s\n", methodName)
return shim.Success(nil)
}
// Initialize initializes chaincode
func (t *RemoverCC) Initialize(stub shim.ChaincodeStubInterface, namespaces []string) pb.Response {
logger.Info("########### RemoverCC Initialize ###########")
methodName := "Initialize()"
if len(namespaces) == 0 {
warningMsg := fmt.Sprintf("%s - No namespaces were provided to RemoverCC.", methodName)
logger.Warning(warningMsg)
}
// Store namespaces on the blockchain
namespacesAsBytes := []byte(strings.Join(namespaces, ","))
err := stub.PutState(Key, namespacesAsBytes)
if err != nil {
errorMsg := fmt.Sprintf("Error storing namespaces: %s", err.Error())
logger.Error(errorMsg)
return shim.Error(errorMsg)
}
logger.Infof("%s - Namespaces provided to RemoverCC: %v", methodName, namespaces)
logger.Infof("- End execution - %s\n", methodName)
return shim.Success(nil)
}
// Invoke is the entry point for all invocations
func (t *RemoverCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
logger.Info("########### RemoverCC Invoke ###########")
function, _ := stub.GetFunctionAndParameters()
switch function {
case "DeleteState":
logger.Info("########### Calling DeleteState ###########")
return t.DeleteState(stub)
}
errorMsg := fmt.Sprintf("Could not find function named '%s' in RemoverCC.", function)
logger.Errorf(errorMsg)
return shim.Error(errorMsg)
}
// DeleteState deletes all data found under each one of the namespaces provided in the Init() method
func (t *RemoverCC) DeleteState(stub shim.ChaincodeStubInterface) pb.Response {
methodName := "DeleteState()"
logger.Infof("- Begin execution - %s", methodName)
totalRecordsDeleted := 0
namespacesAsBytes, err := stub.GetState(Key)
if err != nil {
errorMsg := fmt.Sprintf("Error reading namespaces: %s", err.Error())
logger.Error(errorMsg)
return shim.Error(errorMsg)
}
namespaces := strings.Split(string(namespacesAsBytes), ",")
logger.Infof("%s - Deleting data for namespaces: '%s'", methodName, strings.Join(namespaces, ","))
// Delete records/state in each namespace
for _, namespace := range namespaces {
logger.Infof("%s - Deleting data for namespace '%s'.", methodName, namespace)
recordsDeleted, err := t.DeleteRecordsByPartialKey(stub, namespace)
if err != nil {
return shim.Error(err.Error())
}
totalRecordsDeleted += recordsDeleted
logger.Infof("%s - DeleteRecordsByPartialKey returned with total # of records deleted - %d for namespace %s", methodName, recordsDeleted, namespace)
}
logger.Infof("%s - Total number of records deleted accross all namespaces - %d", methodName, totalRecordsDeleted)
totalDeleteCountInBytes := []byte(strconv.Itoa(totalRecordsDeleted))
return shim.Success(totalDeleteCountInBytes)
}
// DeleteRecordsByPartialKey deletes records using a partial composite key (helper function used by DeleteState)
func (t *RemoverCC) DeleteRecordsByPartialKey(stub shim.ChaincodeStubInterface, namespace string) (int, error) {
methodName := "DeleteRecordsByPartialKey()"
logger.Infof("- Begin execution - %s", methodName)
var recordsDeletedCount = 0
// Create composite partial key for namespace
iterator, err := stub.GetStateByPartialCompositeKey(namespace, []string{})
if err != nil {
errorMsg := fmt.Sprintf("%s - Failed to get iterator for partial composite key: %s. Error: %s", methodName, namespace, err.Error())
logger.Error(errorMsg)
return recordsDeletedCount, err
}
// Once we are done with the iterator, we must close it
defer iterator.Close()
logger.Infof("%s - Starting to delete all records with namespace %s", methodName, namespace)
for iterator.HasNext() {
responseRange, err := iterator.Next()
if err != nil {
errorMsg := fmt.Sprintf("Failed to get next record from iterator: %s", err.Error())
logger.Error(errorMsg)
return recordsDeletedCount, err
}
recordKey := responseRange.GetKey()
logger.Infof("About to delete record with key %s", recordKey)
err = stub.DelState(recordKey)
if err != nil {
errorMsg := fmt.Sprintf("Failed to delete record '%d' with key %s: %s", recordsDeletedCount, recordKey, err.Error())
logger.Error(errorMsg)
return recordsDeletedCount, err
}
recordsDeletedCount++
logger.Debugf("%s - Successfully deleted record '%d' with composite key: %s", methodName, recordsDeletedCount, recordKey)
}
logger.Infof("%s - Finished deleting all records found in %s", methodName, namespace)
logger.Infof("- End execution - %s", methodName)
return recordsDeletedCount, nil
}