2015-11-09 22:57:26 +03:00
|
|
|
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
// Licensed under the MIT license. See LICENSE file in the project root for details.
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bazil.org/fuse/fs"
|
|
|
|
_ "bazil.org/fuse/fs/fstestutil"
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
2017-03-11 01:31:38 +03:00
|
|
|
"io/ioutil"
|
2015-11-09 22:57:26 +03:00
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"os/signal"
|
2015-11-13 02:22:19 +03:00
|
|
|
"strings"
|
2015-11-09 22:57:26 +03:00
|
|
|
"syscall"
|
2015-11-12 01:46:51 +03:00
|
|
|
"time"
|
2015-11-09 22:57:26 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
var Usage = func() {
|
|
|
|
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
|
|
|
|
fmt.Fprintf(os.Stderr, " %s NAMENODE:PORT MOUNTPOINT\n", os.Args[0])
|
|
|
|
flag.PrintDefaults()
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
sigs := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
2015-11-13 01:29:02 +03:00
|
|
|
retryPolicy := NewDefaultRetryPolicy(WallClock{})
|
2015-11-09 22:57:26 +03:00
|
|
|
|
2015-11-10 23:37:14 +03:00
|
|
|
lazyMount := flag.Bool("lazy", false, "Allows to mount HDFS filesystem before HDFS is available")
|
2015-11-13 01:29:02 +03:00
|
|
|
flag.DurationVar(&retryPolicy.TimeLimit, "retryTimeLimit", 5*time.Minute, "time limit for all retry attempts for failed operations")
|
|
|
|
flag.IntVar(&retryPolicy.MaxAttempts, "retryMaxAttempts", 99999999, "Maxumum retry attempts for failed operations")
|
|
|
|
flag.DurationVar(&retryPolicy.MinDelay, "retryMinDelay", 1*time.Second, "minimum delay between retries (note, first retry always happens immediatelly)")
|
|
|
|
flag.DurationVar(&retryPolicy.MaxDelay, "retryMaxDelay", 60*time.Second, "maximum delay between retries")
|
2015-11-13 02:22:19 +03:00
|
|
|
allowedPrefixesString := flag.String("allowedPrefixes", "*", "Comma-separated list of allowed path prefixes on the remote file system, "+
|
|
|
|
"if specified the mount point will expose access to those prefixes only")
|
2015-11-20 04:23:44 +03:00
|
|
|
expandZips := flag.Bool("expandZips", false, "Enables automatic expansion of ZIP archives")
|
2017-06-08 06:46:18 +03:00
|
|
|
readOnly := flag.Bool("readOnly", false, "Enables mount with readonly")
|
2017-03-11 01:31:38 +03:00
|
|
|
logLevel := flag.Int("logLevel", 0, "logs to be printed. 0: only fatal/err logs; 1: +warning logs; 2: +info logs")
|
2015-11-10 23:37:14 +03:00
|
|
|
|
2015-11-09 22:57:26 +03:00
|
|
|
flag.Usage = Usage
|
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
if flag.NArg() != 2 {
|
|
|
|
Usage()
|
|
|
|
os.Exit(2)
|
|
|
|
}
|
|
|
|
|
2017-06-21 23:54:43 +03:00
|
|
|
log.Print("hdfs-mount: current head GITCommit: ", GITCOMMIT, ", Built time: ", BUILDTIME, ", Built by:", HOSTNAME)
|
|
|
|
|
2015-11-13 02:22:19 +03:00
|
|
|
allowedPrefixes := strings.Split(*allowedPrefixesString, ",")
|
|
|
|
|
2015-11-13 01:29:02 +03:00
|
|
|
retryPolicy.MaxAttempts += 1 // converting # of retry attempts to total # of attempts
|
2015-11-10 06:14:23 +03:00
|
|
|
|
2017-03-11 01:31:38 +03:00
|
|
|
if *logLevel == 0 {
|
|
|
|
InitLogger(ioutil.Discard, ioutil.Discard, os.Stdout, os.Stderr)
|
|
|
|
} else if *logLevel == 1 {
|
|
|
|
InitLogger(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr)
|
|
|
|
} else {
|
|
|
|
InitLogger(os.Stdout, os.Stdout, os.Stdout, os.Stderr)
|
|
|
|
}
|
|
|
|
|
2015-11-11 04:07:59 +03:00
|
|
|
hdfsAccessor, err := NewHdfsAccessor(flag.Arg(0), WallClock{})
|
2015-11-09 22:57:26 +03:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal("Error/NewHdfsAccessor: ", err)
|
|
|
|
}
|
|
|
|
|
2015-11-11 04:07:59 +03:00
|
|
|
// Wrapping with FaultTolerantHdfsAccessor
|
|
|
|
ftHdfsAccessor := NewFaultTolerantHdfsAccessor(hdfsAccessor, retryPolicy)
|
|
|
|
|
|
|
|
if !*lazyMount && ftHdfsAccessor.EnsureConnected() != nil {
|
|
|
|
log.Fatal("Can't establish connection to HDFS, mounting will NOT be performend (this can be suppressed with -lazy)")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creating the virtual file system
|
2017-06-08 06:46:18 +03:00
|
|
|
fileSystem, err := NewFileSystem(ftHdfsAccessor, flag.Arg(1), allowedPrefixes, *expandZips, *readOnly, retryPolicy, WallClock{})
|
2015-11-09 22:57:26 +03:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal("Error/NewFileSystem: ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
c, err := fileSystem.Mount()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2015-11-13 00:37:22 +03:00
|
|
|
log.Print("Mounted successfully")
|
2015-11-09 22:57:26 +03:00
|
|
|
|
2017-03-17 19:19:19 +03:00
|
|
|
// Increase the maximum number of file descriptor from 1K to 1M in Linux
|
2017-06-08 06:46:18 +03:00
|
|
|
rLimit := syscall.Rlimit{
|
|
|
|
Cur: 1024 * 1024,
|
|
|
|
Max: 1024 * 1024}
|
2017-03-17 19:19:19 +03:00
|
|
|
err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit)
|
|
|
|
if err != nil {
|
|
|
|
Error.Printf("Failed to update the maximum number of file descriptors from 1K to 1M, %v", err)
|
|
|
|
}
|
|
|
|
|
2015-11-09 22:57:26 +03:00
|
|
|
defer func() {
|
|
|
|
fileSystem.Unmount()
|
|
|
|
log.Print("Closing...")
|
|
|
|
c.Close()
|
|
|
|
log.Print("Closed...")
|
|
|
|
}()
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for x := range sigs {
|
|
|
|
//Handling INT/TERM signals - trying to gracefully unmount and exit
|
|
|
|
//TODO: before doing that we need to finish deferred flushes
|
|
|
|
log.Print("Signal received: " + x.String())
|
|
|
|
fileSystem.Unmount() // this will cause Serve() call below to exit
|
2015-11-10 23:37:14 +03:00
|
|
|
// Also reseting retry policy properties to stop useless retries
|
|
|
|
retryPolicy.MaxAttempts = 0
|
|
|
|
retryPolicy.MaxDelay = 0
|
2015-11-09 22:57:26 +03:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
err = fs.Serve(c, fileSystem)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// check if the mount process has an error to report
|
|
|
|
<-c.Ready
|
|
|
|
if err := c.MountError; err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|