Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Trim space down on full nodes.

Closes #70
  • Loading branch information...
commit ee20c9be00ce1503564f266fcbbb82b9538b5d94 1 parent a431a7f
@dustin dustin authored
Showing with 113 additions and 1 deletion.
  1. +10 −1 config/config.go
  2. +11 −0 nodes.go
  3. +92 −0 tasks.go
View
11 config/config.go
@@ -47,6 +47,12 @@ type CBFSConfig struct {
DefaultVersionCount int `json:"defaultVersionCount"`
// How often to update the node sizes
UpdateNodeSizesFreq time.Duration `json:"updateSizesFreq"`
+ // How frequently to free space from full nodes
+ TrimFullNodesFreq time.Duration `json:"trimFullFreq"`
+ // How many items to move from full nodes.
+ TrimFullNodesCount int `json:"trimFullCount"`
+ // How much space to keep free on nodes.
+ TrimFullNodesSpace int64 `json:"trimFullSize"`
}
// Get the default configuration
@@ -68,6 +74,9 @@ func DefaultConfig() CBFSConfig {
ReplicationCheckLimit: 10000,
DefaultVersionCount: 0,
UpdateNodeSizesFreq: time.Second * 5,
+ TrimFullNodesFreq: time.Hour,
+ TrimFullNodesCount: 1000,
+ TrimFullNodesSpace: 1 * 1024 * 1024 * 1024,
}
}
@@ -144,7 +153,7 @@ func (conf *CBFSConfig) SetParameter(name string, inval interface{}) error {
case sf.Type.Kind() == reflect.String:
val.Field(i).SetString(inval.(string))
return nil
- case sf.Type.Kind() == reflect.Int:
+ case sf.Type.Kind() == reflect.Int, sf.Type.Kind() == reflect.Int64:
v := int64(0)
switch i := inval.(type) {
case string:
View
11 nodes.go
@@ -318,6 +318,17 @@ func (nl NodeList) withAtLeast(free uint64) NodeList {
return rv
}
+// Find nodes with no more than this much space free.
+func (nl NodeList) withNoMoreThan(free uint64) NodeList {
+ rv := NodeList{}
+ for _, node := range nl {
+ if node.Free <= free {
+ rv = append(rv, node)
+ }
+ }
+ return rv
+}
+
func (nl NodeList) candidatesFor(oid string, exclude NodeList) NodeList {
// Find the owners of this blob
ownership := BlobOwnership{}
View
92 tasks.go
@@ -61,6 +61,12 @@ func init() {
},
updateNodeSizes,
},
+ "trimFullNodes": &PeriodicJob{
+ func() time.Duration {
+ return globalConfig.TrimFullNodesFreq
+ },
+ trimFullNodes,
+ },
}
}
@@ -348,6 +354,92 @@ func garbageCollectBlobs() error {
garbageCollectBlobsTask)
}
+func moveSomeOffOf(n StorageNode, nl NodeList) {
+ log.Printf("Freeing up some space from %v", n)
+
+ viewRes := struct {
+ Rows []struct {
+ Id string
+ Doc struct {
+ Json struct {
+ Nodes map[string]string
+ }
+ }
+ }
+ Errors []cb.ViewError
+ }{}
+
+ err := couchbase.ViewCustom("cbfs", "node_blobs",
+ map[string]interface{}{
+ "key": n.name,
+ "limit": globalConfig.TrimFullNodesCount,
+ "reduce": false,
+ "include_docs": true,
+ "stale": false,
+ }, &viewRes)
+ if err != nil {
+ log.Printf("Error executing node_blobs view: %v", err)
+ return
+ }
+
+ log.Printf("Moving %v blobs from %v", len(viewRes.Rows), n)
+ for _, row := range viewRes.Rows {
+ oid := row.Id[1:]
+ candidates := NodeList{}
+
+ if len(row.Doc.Json.Nodes)-1 < globalConfig.MinReplicas {
+ for _, n := range nl {
+ if _, ok := row.Doc.Json.Nodes[n.name]; !ok {
+ candidates = append(candidates, n)
+ }
+ }
+
+ if len(candidates) == 0 {
+ log.Printf("No candidates available to move %v",
+ oid)
+ continue
+ }
+
+ newnode := candidates[rand.Intn(len(candidates))]
+
+ log.Printf("Moving replica of %v from %v to %v",
+ oid, n, newnode)
+ queueBlobAcquire(newnode, oid, n.name)
+ } else {
+ // There are enough, just trim it.
+ log.Printf("Just trimming %v from %v", oid, n)
+ queueBlobRemoval(n, oid)
+ }
+ }
+
+}
+
+func trimFullNodes() error {
+ nl, err := findAllNodes()
+ if err != nil {
+ return err
+ }
+
+ toRelieve := nl.withNoMoreThan(0)
+ if len(toRelieve) == 0 {
+ log.Printf("No nodes need space freed")
+ return nil
+ }
+
+ hasSpace := nl.withAtLeast(uint64(globalConfig.TrimFullNodesSpace))
+
+ if len(hasSpace) == 0 {
+ log.Printf("No needs have sufficient free space")
+ return nil
+ }
+
+ for _, n := range toRelieve {
+ moveSomeOffOf(n, hasSpace)
+ }
+
+ return nil
+}
+
func okToClean(oid string) bool {
ob, err := getBlobOwnership(oid)
if err == nil {
Please sign in to comment.
Something went wrong with that request. Please try again.