You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							114 lines
						
					
					
						
							3.4 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							114 lines
						
					
					
						
							3.4 KiB
						
					
					
				| package weed_server | |
| 
 | |
| import ( | |
| 	"context" | |
| 	"strconv" | |
| 	"time" | |
| 
 | |
| 	"github.com/seaweedfs/seaweedfs/weed/stats" | |
| 
 | |
| 	"runtime" | |
| 
 | |
| 	"github.com/prometheus/procfs" | |
| 	"github.com/seaweedfs/seaweedfs/weed/glog" | |
| 	"github.com/seaweedfs/seaweedfs/weed/pb/volume_server_pb" | |
| 	"github.com/seaweedfs/seaweedfs/weed/storage/needle" | |
| ) | |
| 
 | |
| var numCPU = runtime.NumCPU() | |
| 
 | |
| func (vs *VolumeServer) VacuumVolumeCheck(ctx context.Context, req *volume_server_pb.VacuumVolumeCheckRequest) (*volume_server_pb.VacuumVolumeCheckResponse, error) { | |
| 
 | |
| 	resp := &volume_server_pb.VacuumVolumeCheckResponse{} | |
| 
 | |
| 	garbageRatio, err := vs.store.CheckCompactVolume(needle.VolumeId(req.VolumeId)) | |
| 
 | |
| 	resp.GarbageRatio = garbageRatio | |
| 
 | |
| 	if err != nil { | |
| 		glog.V(3).Infof("check volume %d: %v", req.VolumeId, err) | |
| 	} | |
| 
 | |
| 	return resp, err | |
| 
 | |
| } | |
| 
 | |
| func (vs *VolumeServer) VacuumVolumeCompact(req *volume_server_pb.VacuumVolumeCompactRequest, stream volume_server_pb.VolumeServer_VacuumVolumeCompactServer) error { | |
| 	start := time.Now() | |
| 	defer func(start time.Time) { | |
| 		stats.VolumeServerVacuumingHistogram.WithLabelValues("compact").Observe(time.Since(start).Seconds()) | |
| 	}(start) | |
| 
 | |
| 	resp := &volume_server_pb.VacuumVolumeCompactResponse{} | |
| 	reportInterval := int64(1024 * 1024 * 128) | |
| 	nextReportTarget := reportInterval | |
| 	fs, fsErr := procfs.NewDefaultFS() | |
| 	var sendErr error | |
| 	err := vs.store.CompactVolume(needle.VolumeId(req.VolumeId), req.Preallocate, vs.compactionBytePerSecond, func(processed int64) bool { | |
| 		if processed > nextReportTarget { | |
| 			resp.ProcessedBytes = processed | |
| 			if fsErr == nil && numCPU > 0 { | |
| 				if fsLa, err := fs.LoadAvg(); err == nil { | |
| 					resp.LoadAvg_1M = float32(fsLa.Load1 / float64(numCPU)) | |
| 				} | |
| 			} | |
| 			if sendErr = stream.Send(resp); sendErr != nil { | |
| 				return false | |
| 			} | |
| 			nextReportTarget = processed + reportInterval | |
| 		} | |
| 		return true | |
| 	}) | |
| 
 | |
| 	stats.VolumeServerVacuumingCompactCounter.WithLabelValues(strconv.FormatBool(err == nil && sendErr == nil)).Inc() | |
| 	if err != nil { | |
| 		glog.Errorf("failed compact volume %d: %v", req.VolumeId, err) | |
| 		return err | |
| 	} | |
| 	if sendErr != nil { | |
| 		glog.Errorf("failed compact volume %d report progress: %v", req.VolumeId, sendErr) | |
| 		return sendErr | |
| 	} | |
| 
 | |
| 	glog.V(1).Infof("compact volume %d", req.VolumeId) | |
| 	return nil | |
| 
 | |
| } | |
| 
 | |
| func (vs *VolumeServer) VacuumVolumeCommit(ctx context.Context, req *volume_server_pb.VacuumVolumeCommitRequest) (*volume_server_pb.VacuumVolumeCommitResponse, error) { | |
| 	start := time.Now() | |
| 	defer func(start time.Time) { | |
| 		stats.VolumeServerVacuumingHistogram.WithLabelValues("commit").Observe(time.Since(start).Seconds()) | |
| 	}(start) | |
| 
 | |
| 	resp := &volume_server_pb.VacuumVolumeCommitResponse{} | |
| 
 | |
| 	readOnly, volumeSize, err := vs.store.CommitCompactVolume(needle.VolumeId(req.VolumeId)) | |
| 
 | |
| 	if err != nil { | |
| 		glog.Errorf("failed commit volume %d: %v", req.VolumeId, err) | |
| 	} else { | |
| 		glog.V(1).Infof("commit volume %d", req.VolumeId) | |
| 	} | |
| 	stats.VolumeServerVacuumingCommitCounter.WithLabelValues(strconv.FormatBool(err == nil)).Inc() | |
| 	resp.IsReadOnly = readOnly | |
| 	resp.VolumeSize = uint64(volumeSize) | |
| 	return resp, err | |
| 
 | |
| } | |
| 
 | |
| func (vs *VolumeServer) VacuumVolumeCleanup(ctx context.Context, req *volume_server_pb.VacuumVolumeCleanupRequest) (*volume_server_pb.VacuumVolumeCleanupResponse, error) { | |
| 
 | |
| 	resp := &volume_server_pb.VacuumVolumeCleanupResponse{} | |
| 
 | |
| 	err := vs.store.CommitCleanupVolume(needle.VolumeId(req.VolumeId)) | |
| 
 | |
| 	if err != nil { | |
| 		glog.Errorf("failed cleanup volume %d: %v", req.VolumeId, err) | |
| 	} else { | |
| 		glog.V(1).Infof("cleanup volume %d", req.VolumeId) | |
| 	} | |
| 
 | |
| 	return resp, err | |
| 
 | |
| }
 |