Skip to content

Commit

Permalink
Return possible states a heal operation (minio#4045)
Browse files Browse the repository at this point in the history
  • Loading branch information
krisis authored and harshavardhana committed Apr 14, 2017
1 parent 5f065e2 commit ca64b86
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 15 deletions.
47 changes: 36 additions & 11 deletions cmd/admin-handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -630,9 +630,40 @@ func isDryRun(qval url.Values) bool {
return false
}

type healObjectResult struct {
HealedCount int
OfflineCount int
// healResult - represents result of a heal operation like
// heal-object, heal-upload.
type healResult struct {
State healState `json:"state"`
}

// healState - different states of heal operation
type healState int

const (
// healNone - none of the disks healed
healNone healState = iota
// healPartial - some disks were healed, others were offline
healPartial
// healOK - all disks were healed
healOK
)

// newHealResult - returns healResult given number of disks healed and
// number of disks offline
func newHealResult(numHealedDisks, numOfflineDisks int) healResult {
var state healState
switch {
case numHealedDisks == 0:
state = healNone

case numOfflineDisks > 0:
state = healPartial

default:
state = healOK
}

return healResult{State: state}
}

// HealObjectHandler - POST /?heal&bucket=mybucket&object=myobject&dry-run
Expand Down Expand Up @@ -683,10 +714,7 @@ func (adminAPI adminAPIHandlers) HealObjectHandler(w http.ResponseWriter, r *htt
return
}

jsonBytes, err := json.Marshal(healObjectResult{
HealedCount: numHealedDisks,
OfflineCount: numOfflineDisks,
})
jsonBytes, err := json.Marshal(newHealResult(numHealedDisks, numOfflineDisks))
if err != nil {
writeErrorResponse(w, toAPIErrorCode(err), r.URL)
return
Expand Down Expand Up @@ -761,10 +789,7 @@ func (adminAPI adminAPIHandlers) HealUploadHandler(w http.ResponseWriter, r *htt
return
}

jsonBytes, err := json.Marshal(healObjectResult{
HealedCount: numHealedDisks,
OfflineCount: numOfflineDisks,
})
jsonBytes, err := json.Marshal(newHealResult(numHealedDisks, numOfflineDisks))
if err != nil {
writeErrorResponse(w, toAPIErrorCode(err), r.URL)
return
Expand Down
26 changes: 26 additions & 0 deletions cmd/admin-handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1586,3 +1586,29 @@ func TestListHealUploadsHandler(t *testing.T) {

}
}

// Test for newHealResult helper function.
func TestNewHealResult(t *testing.T) {
testCases := []struct {
healedDisks int
offlineDisks int
state healState
}{
// 1. No disks healed, no disks offline.
{0, 0, healNone},
// 2. No disks healed, non-zero disks offline.
{0, 1, healNone},
// 3. Non-zero disks healed, no disks offline.
{1, 0, healOK},
// 4. Non-zero disks healed, non-zero disks offline.
{1, 1, healPartial},
}

for i, test := range testCases {
actual := newHealResult(test.healedDisks, test.offlineDisks)
if actual.State != test.state {
t.Errorf("Test %d: Expected %v but received %v", i+1,
test.state, actual.State)
}
}
}
13 changes: 11 additions & 2 deletions cmd/xl-v1-healing.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,12 +336,19 @@ func healObject(storageDisks []StorageAPI, bucket string, object string, quorum
return 0, 0, toObjectErr(aErr, bucket, object)
}

numAvailableDisks := 0
// Number of disks which don't serve data.
numOfflineDisks := 0
for index, disk := range availableDisks {
for index, disk := range storageDisks {
switch {
case disk == nil, errs[index] == errDiskNotFound:
numOfflineDisks++
}
}

// Number of disks which have all parts of the given object.
numAvailableDisks := 0
for _, disk := range availableDisks {
switch {
case disk != nil:
numAvailableDisks++
}
Expand All @@ -357,6 +364,8 @@ func healObject(storageDisks []StorageAPI, bucket string, object string, quorum
outDatedDisks := outDatedDisks(storageDisks, availableDisks, errs, partsMetadata,
bucket, object)

// Number of disks that had outdated content of the given
// object and are online to be healed.
numHealedDisks := 0
for _, disk := range outDatedDisks {
if disk != nil {
Expand Down
23 changes: 23 additions & 0 deletions pkg/madmin/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,18 @@ __Example__
### HealObject(bucket, object string, isDryRun bool) (HealResult, error)
If object is successfully healed returns nil, otherwise returns error indicating the reason for failure. If isDryRun is true, then the object is not healed, but heal object request is validated by the server. e.g, if the object exists, if object name is valid etc.

| Param | Type | Description |
|---|---|---|
|`h.State` | _HealState_ | Represents the result of heal operation. It could be one of `HealNone`, `HealPartial` or `HealOK`. |


| Value | Description |
|---|---|
|`HealNone` | Object/Upload wasn't healed on any of the disks |
|`HealPartial` | Object/Upload was healed on some of the disks needing heal |
| `HealOK` | Object/Upload was healed on all the disks needing heal |


__Example__

``` go
Expand Down Expand Up @@ -327,6 +339,17 @@ __Example__
### HealUpload(bucket, object, uploadID string, isDryRun bool) (HealResult, error)
If upload is successfully healed returns nil, otherwise returns error indicating the reason for failure. If isDryRun is true, then the upload is not healed, but heal upload request is validated by the server. e.g, if the upload exists, if upload name is valid etc.

| Param | Type | Description |
|---|---|---|
|`h.State` | _HealState_ | Represents the result of heal operation. It could be one of `HealNone`, `HealPartial` or `HealOK`. |


| Value | Description |
|---|---|
| `HealNone` | Object/Upload wasn't healed on any of the disks |
| `HealPartial` | Object/Upload was healed on some of the disks needing heal |
| `HealOK` | Object/Upload was healed on all the disks needing heal |

``` go
isDryRun = false
healResult, err := madmClnt.HealUpload("mybucket", "myobject", "myUploadID", isDryRun)
Expand Down
15 changes: 13 additions & 2 deletions pkg/madmin/heal-commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -494,10 +494,21 @@ func (adm *AdminClient) HealUpload(bucket, object, uploadID string, dryrun bool)

// HealResult - represents result of heal-object admin API.
type HealResult struct {
HealedCount int // number of disks that were healed.
OfflineCount int // number of disks that needed healing but were offline.
State HealState `json:"state"`
}

// HealState - different states of heal operation
type HealState int

const (
// HealNone - none of the disks healed
HealNone HealState = iota
// HealPartial - some disks were healed, others were offline
HealPartial
// HealOK - all disks were healed
HealOK
)

// HealObject - Heal the given object.
func (adm *AdminClient) HealObject(bucket, object string, dryrun bool) (HealResult, error) {
// Construct query params.
Expand Down

0 comments on commit ca64b86

Please sign in to comment.