github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/mongo/prealloc.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package mongo 5 6 import ( 7 "bytes" 8 "fmt" 9 "os/exec" 10 "runtime" 11 "strconv" 12 "strings" 13 ) 14 15 var ( 16 runtimeGOOS = runtime.GOOS 17 18 smallOplogSizeMB = 512 19 regularOplogSizeMB = 1024 20 smallOplogBoundary = 15360.0 21 22 availSpace = fsAvailSpace 23 ) 24 25 // defaultOplogSize returns the default size in MB for the 26 // mongo oplog based on the directory of the mongo database. 27 // 28 // Since we limit the maximum oplog size to 1GB and every change 29 // in opLogSize requires mongo restart we are not using the default 30 // MongoDB formula but simply using 512MB for small disks and 1GB 31 // for larger ones. 32 func defaultOplogSize(dir string) (int, error) { 33 // "For 64-bit OS X systems, MongoDB allocates 183 megabytes of 34 // space to the oplog." 35 if runtimeGOOS == "darwin" { 36 return 183, nil 37 } 38 39 avail, err := availSpace(dir) 40 if err != nil { 41 return -1, err 42 } 43 if avail < smallOplogBoundary { 44 return smallOplogSizeMB, nil 45 } else { 46 return regularOplogSizeMB, nil 47 } 48 } 49 50 // fsAvailSpace returns the available space in MB on the 51 // filesystem containing the specified directory. 52 func fsAvailSpace(dir string) (avail float64, err error) { 53 var stderr bytes.Buffer 54 cmd := exec.Command("df", dir) 55 cmd.Stderr = &stderr 56 out, err := cmd.Output() 57 if err != nil { 58 err := fmt.Errorf("df failed: %v", err) 59 if stderr.Len() > 0 { 60 err = fmt.Errorf("%s (%q)", err, stderr.String()) 61 } 62 return -1, err 63 } 64 lines := strings.Split(strings.TrimSpace(string(out)), "\n") 65 if len(lines) < 2 { 66 logger.Errorf("unexpected output: %q", out) 67 return -1, fmt.Errorf("could not determine available space on %q", dir) 68 } 69 fields := strings.Fields(lines[1]) 70 if len(fields) < 4 { 71 logger.Errorf("unexpected output: %q", out) 72 return -1, fmt.Errorf("could not determine available space on %q", dir) 73 } 74 kilobytes, err := strconv.Atoi(fields[3]) 75 if err != nil { 76 return -1, err 77 } 78 return float64(kilobytes) / 1024, err 79 }