github.com/lnzx/goofys@v0.24.0/internal/backend_adlv2.go (about)

     1  // Copyright 2019 Databricks
     2  // Copyright (c) Microsoft and contributors for generated code from azure-sdk-for-go
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package internal
    17  
    18  import (
    19  	. "github.com/kahing/goofys/api/common"
    20  
    21  	"context"
    22  	"encoding/base64"
    23  	"encoding/json"
    24  	"fmt"
    25  	"io"
    26  	"net/http"
    27  	"net/url"
    28  	"strconv"
    29  	"strings"
    30  	"sync/atomic"
    31  	"syscall"
    32  	"time"
    33  
    34  	"github.com/google/uuid"
    35  	"github.com/jacobsa/fuse"
    36  	"github.com/sirupsen/logrus"
    37  
    38  	adl2 "github.com/Azure/azure-sdk-for-go/services/storage/datalake/2018-11-09/storagedatalake"
    39  	"github.com/Azure/go-autorest/autorest"
    40  	"github.com/Azure/go-autorest/autorest/azure"
    41  )
    42  
    43  type ADLv2 struct {
    44  	cap Capabilities
    45  
    46  	flags  *FlagStorage
    47  	config *ADLv2Config
    48  
    49  	client adl2PathClient
    50  	bucket string
    51  }
    52  
    53  const ADL2_CLIENT_REQUEST_ID = "X-Ms-Client-Request-Id"
    54  const ADL2_REQUEST_ID = "X-Ms-Request-Id"
    55  
    56  var adl2Log = GetLogger("adlv2")
    57  
    58  type ADLv2MultipartBlobCommitInput struct {
    59  	Size           uint64
    60  	ContentType    string
    61  	RenewLeaseStop chan bool
    62  }
    63  
    64  func IsADLv2Endpoint(endpoint string) bool {
    65  	return strings.HasPrefix(endpoint, "abfs://")
    66  }
    67  
    68  func adl2LogResp(level logrus.Level, r *http.Response) {
    69  	if r == nil {
    70  		return
    71  	}
    72  
    73  	if adl2Log.IsLevelEnabled(level) {
    74  		requestId := r.Request.Header.Get(ADL2_CLIENT_REQUEST_ID)
    75  		respId := r.Header.Get(ADL2_REQUEST_ID)
    76  		// don't log anything if this is being called twice,
    77  		// which it is via ResponseInspector
    78  		if respId != "" {
    79  			adl2Log.Logf(level, "%v %v %v %v %v", r.Request.Method,
    80  				r.Request.URL.String(),
    81  				requestId, r.Status, respId)
    82  			r.Header.Del(ADL2_REQUEST_ID)
    83  		}
    84  	}
    85  }
    86  
    87  func NewADLv2(bucket string, flags *FlagStorage, config *ADLv2Config) (*ADLv2, error) {
    88  	u, err := url.Parse(config.Endpoint)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	parts := strings.SplitN(u.Hostname(), ".", 2)
    94  	if len(parts) != 2 {
    95  		return nil, fmt.Errorf("Invalid endpoint: %v", config.Endpoint)
    96  	}
    97  	storageAccountName := parts[0]
    98  	dnsSuffix := parts[1]
    99  
   100  	LogRequest := func(p autorest.Preparer) autorest.Preparer {
   101  		return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) {
   102  			r.URL.Scheme = u.Scheme
   103  			date := time.Now().Format(time.RFC1123)
   104  			date = strings.Replace(date, "UTC", "GMT", 1)
   105  
   106  			r.Header.Set("X-Ms-Date", date)
   107  			r.Header.Set("X-Ms-Version", "2018-11-09")
   108  			r.Header.Set(ADL2_CLIENT_REQUEST_ID, uuid.New().String())
   109  			r.Header.Set("Accept-Charset", "utf-8")
   110  			r.Header.Set("Content-Type", "")
   111  			r.Header.Set("Accept", "application/json, application/octet-stream")
   112  			// set transfer encoding and non-nil Body to
   113  			// ensure Content-Length: 0 is sent, seems
   114  			// like an idiotic golang behavior:
   115  			// https://github.com/golang/go/issues/20257
   116  			// azure server side rejects the request if
   117  			// Content-Length is missing
   118  			r.TransferEncoding = []string{"identity"}
   119  			if r.Header.Get("Content-Length") == "0" {
   120  				r.Body = http.NoBody
   121  			} else if r.Body == nil {
   122  				r.Body = http.NoBody
   123  			}
   124  
   125  			if adl2Log.IsLevelEnabled(logrus.DebugLevel) {
   126  				requestId := r.Header.Get(ADL2_CLIENT_REQUEST_ID)
   127  				op := r.Method
   128  				switch op {
   129  				case http.MethodPost:
   130  					// this is a lease
   131  					leaseAction := r.Header.Get("X-Ms-Lease-Action")
   132  					leaseId := r.Header.Get("X-Ms-Lease-Id")
   133  					proposeLeaseId := r.Header.Get("X-Ms-Proposed-Lease-Id")
   134  					op += fmt.Sprintf(" %v (%v, %v)",
   135  						leaseAction, leaseId, proposeLeaseId)
   136  				case http.MethodPatch:
   137  					action := r.URL.Query().Get("action")
   138  					op += " " + action
   139  					if action == "append" {
   140  						op += fmt.Sprintf("(%v)", r.ContentLength)
   141  					}
   142  				}
   143  				adl2Log.Debugf("%v %v %v", op,
   144  					r.URL.String(), requestId)
   145  			}
   146  
   147  			r, err := p.Prepare(r)
   148  			if err != nil {
   149  				adl2Log.Error(err)
   150  			}
   151  			return r, err
   152  		})
   153  	}
   154  
   155  	LogResponse := func(p autorest.Responder) autorest.Responder {
   156  		return autorest.ResponderFunc(func(r *http.Response) error {
   157  			adl2LogResp(logrus.DebugLevel, r)
   158  			err := p.Respond(r)
   159  			if err != nil {
   160  				adl2Log.Error(err)
   161  			}
   162  			return err
   163  		})
   164  	}
   165  
   166  	client := adl2.NewWithoutDefaults("", storageAccountName, dnsSuffix)
   167  	client.Authorizer = config.Authorizer
   168  	client.RequestInspector = LogRequest
   169  	client.ResponseInspector = LogResponse
   170  	client.Sender.(*http.Client).Transport = GetHTTPTransport()
   171  
   172  	b := &ADLv2{
   173  		flags:  flags,
   174  		config: config,
   175  		client: adl2PathClient{client},
   176  		bucket: bucket,
   177  		cap: Capabilities{
   178  			DirBlob: true,
   179  			Name:    "adl2",
   180  			// tested on 2019-11-07, seems to have same
   181  			// limit as azblob
   182  			MaxMultipartSize: 100 * 1024 * 1024,
   183  		},
   184  	}
   185  
   186  	return b, nil
   187  }
   188  
   189  func (b *ADLv2) Bucket() string {
   190  	return b.bucket
   191  }
   192  
   193  func (b *ADLv2) Delegate() interface{} {
   194  	return b
   195  }
   196  
   197  func (b *ADLv2) Init(key string) (err error) {
   198  	_, err = b.HeadBlob(&HeadBlobInput{Key: key})
   199  	if err == fuse.ENOENT {
   200  		err = nil
   201  	}
   202  	return
   203  }
   204  
   205  func (b *ADLv2) Capabilities() *Capabilities {
   206  	return &b.cap
   207  }
   208  
   209  type ADL2Error struct {
   210  	adl2.DataLakeStorageError
   211  }
   212  
   213  func (e ADL2Error) Error() string {
   214  	return fmt.Sprintf("%v: %v", *e.DataLakeStorageError.Error.Code,
   215  		*e.DataLakeStorageError.Error.Message)
   216  }
   217  
   218  func decodeADLv2Error(body io.Reader) (adlErr adl2.DataLakeStorageError, err error) {
   219  	decoder := json.NewDecoder(body)
   220  	err = decoder.Decode(&adlErr)
   221  	return
   222  }
   223  
   224  func adlv2ErrLogHeaders(errCode string, resp *http.Response) {
   225  	switch errCode {
   226  	case "MissingRequiredHeader", "UnsupportedHeader":
   227  		var s strings.Builder
   228  		for k, _ := range resp.Request.Header {
   229  			s.WriteString(k)
   230  			s.WriteString(" ")
   231  		}
   232  		adl2Log.Errorf("%v, sent: %v", errCode, s.String())
   233  	case "InvalidHeaderValue":
   234  		var s strings.Builder
   235  		for k, v := range resp.Request.Header {
   236  			if k != "Authorization" {
   237  				s.WriteString(k)
   238  				s.WriteString(":")
   239  				s.WriteString(v[0])
   240  				s.WriteString(" ")
   241  			}
   242  		}
   243  		adl2Log.Errorf("%v, sent: %v", errCode, s.String())
   244  	case "InvalidSourceUri":
   245  		adl2Log.Errorf("SourceUri: %v",
   246  			resp.Request.Header.Get("X-Ms-Rename-Source"))
   247  	}
   248  }
   249  
   250  func mapADLv2Error(resp *http.Response, err error, rawError bool) error {
   251  
   252  	if resp == nil {
   253  		if err != nil {
   254  			if detailedError, ok := err.(autorest.DetailedError); ok {
   255  				if urlErr, ok := detailedError.Original.(*url.Error); ok {
   256  					adl2Log.Errorf("url.Err: %T: %v %v %v %v %v", urlErr.Err, urlErr.Err, urlErr.Temporary(), urlErr.Timeout(), urlErr.Op, urlErr.URL)
   257  				} else {
   258  					adl2Log.Errorf("%T: %v", detailedError.Original, detailedError.Original)
   259  				}
   260  			} else {
   261  				adl2Log.Errorf("unknown error: %v", err)
   262  			}
   263  			return syscall.EAGAIN
   264  		} else {
   265  			return err
   266  		}
   267  	}
   268  
   269  	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
   270  		defer resp.Body.Close()
   271  		if rawError {
   272  			adlErr, err := decodeADLv2Error(resp.Body)
   273  			if err == nil {
   274  				return ADL2Error{adlErr}
   275  			} else {
   276  				adl2Log.Errorf("cannot parse error: %v", err)
   277  				return syscall.EAGAIN
   278  			}
   279  		} else {
   280  			switch resp.StatusCode {
   281  			case http.StatusBadRequest:
   282  				if !adl2Log.IsLevelEnabled(logrus.DebugLevel) {
   283  					adl2LogResp(logrus.ErrorLevel, resp)
   284  				}
   285  				adlErr, err := decodeADLv2Error(resp.Body)
   286  				if err == nil {
   287  					adlv2ErrLogHeaders(*adlErr.Error.Code, resp)
   288  				}
   289  			case http.StatusPreconditionFailed:
   290  				return syscall.EAGAIN
   291  			}
   292  
   293  			err = mapHttpError(resp.StatusCode)
   294  			if err != nil {
   295  				return err
   296  			} else {
   297  				if !adl2Log.IsLevelEnabled(logrus.DebugLevel) {
   298  					adl2LogResp(logrus.ErrorLevel, resp)
   299  				}
   300  				adl2Log.Errorf("resp: %#v %v", resp, err)
   301  				return syscall.EINVAL
   302  			}
   303  		}
   304  	} else if resp.StatusCode == http.StatusOK && err != nil {
   305  		// trying to capture this error:
   306  		// autorest.DetailedError{Original:(*errors.errorString)(0xc0003eb3f0),
   307  		// PackageType:"storagedatalake.adl2PathClient",
   308  		// Method:"List", StatusCode:200, Message:"Failure
   309  		// responding to request", ServiceError:[]uint8(nil),
   310  		// Response:(*http.Response)(0xc0016517a0)}
   311  		// ("storagedatalake.adl2PathClient#List: Failure
   312  		// responding to request: StatusCode=200 -- Original
   313  		// Error: Error occurred reading http.Response#Body -
   314  		// Error = 'read tcp
   315  		// 10.20.255.49:34194->52.239.155.98:443: read:
   316  		// connection reset by peer'")
   317  		if detailedErr, ok := err.(autorest.DetailedError); ok {
   318  			if detailedErr.Method == "List" &&
   319  				strings.Contains(detailedErr.Error(),
   320  					"read: connection reset by peer") {
   321  				return syscall.ECONNRESET
   322  			}
   323  		}
   324  	}
   325  
   326  	return err
   327  }
   328  
   329  func getHeader(resp *http.Response, key string) *string {
   330  	if v, set := resp.Header[http.CanonicalHeaderKey(key)]; set {
   331  		return &v[0]
   332  	} else {
   333  		return nil
   334  	}
   335  }
   336  
   337  func parseADLv2Time(v string) *time.Time {
   338  	t, err := time.Parse(time.RFC1123, v)
   339  	if err == nil {
   340  		return &t
   341  	} else {
   342  		return nil
   343  	}
   344  }
   345  
   346  func adlv2ToBlobItem(resp *http.Response, key string) BlobItemOutput {
   347  	return BlobItemOutput{
   348  		Key:          &key,
   349  		ETag:         getHeader(resp, "ETag"),
   350  		Size:         uint64(resp.ContentLength),
   351  		LastModified: parseADLv2Time(resp.Header.Get("Last-Modified")),
   352  	}
   353  }
   354  
   355  func (b *ADLv2) HeadBlob(param *HeadBlobInput) (*HeadBlobOutput, error) {
   356  	key := param.Key
   357  	if strings.HasSuffix(key, "/") {
   358  		key = key[:len(key)-1]
   359  	}
   360  
   361  	// GetProperties(GetStatus) does not return user defined
   362  	// properties, despite what the documentation says, use a 0
   363  	// bytes range get instead
   364  	res, err := b.GetBlob(&GetBlobInput{
   365  		Key:   key,
   366  		Start: 0,
   367  		Count: 0,
   368  	})
   369  	if err != nil {
   370  		return nil, err
   371  	}
   372  	res.Body.Close()
   373  
   374  	return &res.HeadBlobOutput, nil
   375  }
   376  
   377  // autorest handles retry based on request errors but doesn't retry on
   378  // reading body. List is idempotent anyway so we can retry it here
   379  func (b *ADLv2) listBlobs(param *ListBlobsInput, maxResults *int32) (adl2PathList, error) {
   380  	var err error
   381  	var res adl2PathList
   382  
   383  	// autorest's DefaultMaxRetry is 3 which seems wrong. Also
   384  	// read errors are transient and should probably be retried more
   385  	for attempt := 0; attempt < 30; attempt++ {
   386  		res, err = b.client.List(context.TODO(), param.Delimiter == nil, b.bucket,
   387  			nilStr(param.Prefix), nilStr(param.ContinuationToken), maxResults,
   388  			nil, "", nil, "")
   389  		err = mapADLv2Error(res.Response.Response, err, false)
   390  		if err == nil {
   391  			break
   392  		} else if err != syscall.ECONNRESET {
   393  			return res, err
   394  		} else {
   395  			// autorest's DefaultRetryDuration is 30s but
   396  			// that's for failed requests. Read errors is
   397  			// probably more transient and should be
   398  			// retried faster
   399  			if !autorest.DelayForBackoffWithCap(
   400  				30*time.Millisecond,
   401  				0,
   402  				attempt,
   403  				res.Response.Response.Request.Context().Done()) {
   404  				return res, err
   405  			}
   406  		}
   407  
   408  	}
   409  
   410  	return res, err
   411  }
   412  
   413  func (b *ADLv2) ListBlobs(param *ListBlobsInput) (*ListBlobsOutput, error) {
   414  	if param.Delimiter != nil && *param.Delimiter != "/" {
   415  		return nil, fuse.EINVAL
   416  	}
   417  
   418  	var maxResults *int32
   419  	if param.MaxKeys != nil {
   420  		maxResults = PInt32(int32(*param.MaxKeys))
   421  	}
   422  
   423  	res, err := b.listBlobs(param, maxResults)
   424  	if err != nil {
   425  		if err == fuse.ENOENT {
   426  			return &ListBlobsOutput{
   427  				RequestId: res.Response.Response.Header.Get(ADL2_REQUEST_ID),
   428  			}, nil
   429  		} else {
   430  			return nil, err
   431  		}
   432  	}
   433  
   434  	var prefixes []BlobPrefixOutput
   435  	var items []BlobItemOutput
   436  
   437  	if param.Delimiter != nil && param.Prefix != nil {
   438  		// we didn't get 404 which means the path must
   439  		// exists. If the path is actually a file, adlv2
   440  		// returns the file itself as the result. That's
   441  		// already handled by the loop below
   442  		if len(*res.Paths) != 1 ||
   443  			*(*res.Paths)[0].Name != strings.TrimRight(*param.Prefix, "/") {
   444  			// the prefix we listed is a directory
   445  			if strings.HasSuffix(*param.Prefix, "/") {
   446  				// we listed for the dir object itself
   447  				items = append(items, BlobItemOutput{
   448  					Key: param.Prefix,
   449  				})
   450  			} else {
   451  				prefixes = append(prefixes, BlobPrefixOutput{
   452  					PString(*param.Prefix + "/"),
   453  				})
   454  			}
   455  		} else {
   456  			if strings.HasSuffix(*param.Prefix, "/") {
   457  				// we asked for a dir and got a file
   458  				return &ListBlobsOutput{
   459  					RequestId: res.Response.Response.Header.Get(ADL2_REQUEST_ID),
   460  				}, nil
   461  			}
   462  		}
   463  	}
   464  
   465  	for _, p := range *res.Paths {
   466  		if param.Delimiter != nil {
   467  			if p.isDirectory() {
   468  				prefixes = append(prefixes, BlobPrefixOutput{
   469  					PString(*p.Name + "/"),
   470  				})
   471  				continue
   472  			}
   473  		}
   474  
   475  		key := *p.Name
   476  		if p.isDirectory() {
   477  			key += "/"
   478  		}
   479  		items = append(items, BlobItemOutput{
   480  			Key:          &key,
   481  			ETag:         p.ETag,
   482  			LastModified: parseADLv2Time(nilStr(p.LastModified)),
   483  			Size:         uint64(p.contentLength()),
   484  		})
   485  	}
   486  
   487  	continuationToken := getHeader(res.Response.Response, "x-ms-continuation")
   488  
   489  	return &ListBlobsOutput{
   490  		Prefixes:              prefixes,
   491  		Items:                 items,
   492  		NextContinuationToken: continuationToken,
   493  		IsTruncated:           continuationToken != nil,
   494  		RequestId:             res.Response.Response.Header.Get(ADL2_REQUEST_ID),
   495  	}, nil
   496  }
   497  
   498  func (b *ADLv2) DeleteBlob(param *DeleteBlobInput) (*DeleteBlobOutput, error) {
   499  	if strings.HasSuffix(param.Key, "/") {
   500  		return b.DeleteBlob(&DeleteBlobInput{param.Key[:len(param.Key)-1]})
   501  	}
   502  
   503  	res, err := b.client.Delete(context.TODO(), b.bucket, param.Key, nil, "", "",
   504  		/*ifMatch=*/ "", "", "", "", "", nil, "")
   505  	err = mapADLv2Error(res.Response, err, false)
   506  	if err != nil {
   507  		return nil, err
   508  	}
   509  	return &DeleteBlobOutput{}, nil
   510  }
   511  
   512  func (b *ADLv2) DeleteBlobs(param *DeleteBlobsInput) (*DeleteBlobsOutput, error) {
   513  	return nil, syscall.ENOTSUP
   514  }
   515  
   516  func (b *ADLv2) RenameBlob(param *RenameBlobInput) (*RenameBlobOutput, error) {
   517  	var continuation string
   518  
   519  	renameDest := param.Destination
   520  	if strings.HasSuffix(renameDest, "/") {
   521  		renameDest = renameDest[:len(renameDest)-1]
   522  	}
   523  	renameSource := param.Source
   524  	if strings.HasSuffix(renameSource, "/") {
   525  		renameSource = renameSource[:len(renameSource)-1]
   526  	}
   527  	renameSource = "/" + b.bucket + "/" + url.PathEscape(renameSource)
   528  
   529  	var requestId string
   530  	for cont := true; cont; cont = continuation != "" {
   531  		res, err := b.client.Create(context.TODO(), b.bucket, renameDest,
   532  			"", continuation, "", "", "", "", "", "", "", "", "", "",
   533  			renameSource, "", "", "", "", "", "", "", "", "", "", "",
   534  			"", "", "", nil, "")
   535  		if err != nil {
   536  			return nil, mapADLv2Error(res.Response, err, false)
   537  		}
   538  
   539  		continuation = res.Header.Get("x-ms-continuation")
   540  		requestId = res.Header.Get(ADL2_REQUEST_ID)
   541  	}
   542  
   543  	return &RenameBlobOutput{requestId}, nil
   544  }
   545  
   546  func (b *ADLv2) CopyBlob(param *CopyBlobInput) (*CopyBlobOutput, error) {
   547  	if param.Source != param.Destination || param.Metadata == nil {
   548  		return nil, syscall.ENOTSUP
   549  	}
   550  
   551  	res, err := b.client.Update(context.TODO(), adl2.SetProperties, b.bucket, param.Source, nil,
   552  		nil, nil, nil, "", "", "", "", "", "", "", "", b.toADLProperties(param.Metadata),
   553  		"", "", "", "", "", "", "", "", nil, "", nil, "")
   554  	if err != nil {
   555  		return nil, mapADLv2Error(res.Response, err, false)
   556  	}
   557  
   558  	return &CopyBlobOutput{
   559  		RequestId: res.Response.Header.Get(ADL2_REQUEST_ID),
   560  	}, nil
   561  }
   562  
   563  func (b *ADLv2) GetBlob(param *GetBlobInput) (*GetBlobOutput, error) {
   564  	var bytes string
   565  	if param.Start != 0 || param.Count != 0 {
   566  		if param.Count != 0 {
   567  			bytes = fmt.Sprintf("bytes=%v-%v", param.Start, param.Start+param.Count-1)
   568  		} else {
   569  			bytes = fmt.Sprintf("bytes=%v-", param.Start)
   570  		}
   571  	}
   572  
   573  	res, err := b.client.Read(context.TODO(), b.bucket, param.Key, bytes,
   574  		"", nil, nilStr(param.IfMatch), "", "", "",
   575  		"", nil, "")
   576  	if err != nil {
   577  		return nil, mapADLv2Error(res.Response.Response, err, false)
   578  	}
   579  
   580  	metadata := make(map[string]*string)
   581  	for _, p := range res.Header["X-Ms-Properties"] {
   582  		csv := strings.Split(p, ",")
   583  		for _, kv := range csv {
   584  			kv = strings.TrimSpace(kv)
   585  			if len(kv) == 0 {
   586  				continue
   587  			}
   588  
   589  			s := strings.SplitN(kv, "=", 2)
   590  			if len(s) != 2 {
   591  				adl2Log.Warnf("Dropping property: %v: %v", param.Key, kv)
   592  				continue
   593  			}
   594  			key := strings.TrimSpace(s[0])
   595  			value := strings.TrimSpace(s[1])
   596  			buf, err := base64.StdEncoding.DecodeString(value)
   597  			if err != nil {
   598  				adl2Log.Warnf("Unable to decode property: %v: %v",
   599  					param.Key, key)
   600  				continue
   601  			}
   602  			metadata[key] = PString(string(buf))
   603  		}
   604  	}
   605  
   606  	return &GetBlobOutput{
   607  		HeadBlobOutput: HeadBlobOutput{
   608  			BlobItemOutput: adlv2ToBlobItem(res.Response.Response, param.Key),
   609  			ContentType:    getHeader(res.Response.Response, "Content-Type"),
   610  			IsDirBlob:      res.Header.Get("X-Ms-Resource-Type") == string(adl2.Directory),
   611  			Metadata:       metadata,
   612  		},
   613  		Body: *res.Value,
   614  	}, nil
   615  }
   616  
   617  func (b *ADLv2) toADLProperties(metadata map[string]*string) string {
   618  	var buf strings.Builder
   619  	for k, v := range metadata {
   620  		buf.WriteString(k)
   621  		buf.WriteString("=")
   622  		buf.WriteString(base64.StdEncoding.EncodeToString([]byte(*v)))
   623  		buf.WriteString(",")
   624  	}
   625  	var s = buf.String()
   626  	if len(s) != 0 {
   627  		// remove trailing comma
   628  		s = s[:len(s)-1]
   629  	}
   630  	return s
   631  }
   632  
   633  func (b *ADLv2) create(key string, pathType adl2.PathResourceType, contentType *string,
   634  	metadata map[string]*string, leaseId string) (resp autorest.Response, err error) {
   635  	resp, err = b.client.Create(context.TODO(), b.bucket, key,
   636  		pathType, "", "", "", "", "", "", "", nilStr(contentType),
   637  		"", "", "", "", leaseId, "", b.toADLProperties(metadata), "", "", "", "", "", "",
   638  		"", "", "", "", "", nil, "")
   639  	if err != nil {
   640  		err = mapADLv2Error(resp.Response, err, false)
   641  	}
   642  	return
   643  }
   644  
   645  func (b *ADLv2) append(key string, offset int64, size int64, body io.ReadSeeker,
   646  	leaseId string) (resp autorest.Response, err error) {
   647  	resp, err = b.client.Update(context.TODO(), adl2.Append, b.bucket,
   648  		key, &offset, nil, nil, &size, "", leaseId, "",
   649  		"", "", "", "", "", "", "", "", "", "",
   650  		"", "", "", "", &ReadSeekerCloser{body},
   651  		"", nil, "")
   652  	if err != nil {
   653  		err = mapADLv2Error(resp.Response, err, false)
   654  	}
   655  	return
   656  }
   657  
   658  func (b *ADLv2) flush(key string, offset int64, contentType string, leaseId string) (res autorest.Response, err error) {
   659  	res, err = b.client.Update(context.TODO(), adl2.Flush, b.bucket,
   660  		key, &offset, PBool(false), PBool(true), PInt64(0), "", leaseId, "",
   661  		contentType, "", "", "", "", "", "", "", "", "",
   662  		"", "", "", "", nil, "", nil, "")
   663  	if err != nil {
   664  		err = mapADLv2Error(res.Response, err, false)
   665  	}
   666  	return
   667  }
   668  
   669  func (b *ADLv2) PutBlob(param *PutBlobInput) (*PutBlobOutput, error) {
   670  	if param.DirBlob {
   671  		res, err := b.create(param.Key, adl2.Directory, param.ContentType,
   672  			param.Metadata, "")
   673  		if err != nil {
   674  			return nil, err
   675  		}
   676  		return &PutBlobOutput{
   677  			ETag:         getHeader(res.Response, "ETag"),
   678  			LastModified: parseADLv2Time(res.Response.Header.Get("Last-Modified")),
   679  		}, nil
   680  	} else {
   681  		if param.Size == nil {
   682  			panic("size cannot be nil")
   683  		}
   684  
   685  		create, err := b.create(param.Key, adl2.File, param.ContentType,
   686  			param.Metadata, "")
   687  		if err != nil {
   688  			return nil, err
   689  		}
   690  
   691  		size := int64(*param.Size)
   692  		if size == 0 {
   693  			// nothing to write, we can return
   694  			// here. appending a 0-size buffer
   695  			// causes azure to fail with 400 bad
   696  			// request
   697  			return &PutBlobOutput{
   698  				ETag: getHeader(create.Response, "ETag"),
   699  			}, nil
   700  		}
   701  
   702  		// not doing a lease for these because append to 0
   703  		// would guarantee that we don't have concurrent
   704  		// appends, and flushing is safe to do
   705  		_, err = b.append(param.Key, 0, size, param.Body, "")
   706  		if err != nil {
   707  			return nil, err
   708  		}
   709  
   710  		flush, err := b.flush(param.Key, size, nilStr(param.ContentType), "")
   711  		if err != nil {
   712  			return nil, err
   713  		}
   714  
   715  		return &PutBlobOutput{
   716  			ETag:         getHeader(flush.Response, "ETag"),
   717  			LastModified: parseADLv2Time(flush.Response.Header.Get("Last-Modified")),
   718  		}, nil
   719  	}
   720  }
   721  
   722  // adlv2 doesn't have atomic multipart upload, instead we will hold a
   723  // lease, replace the object, then release the lease
   724  func (b *ADLv2) MultipartBlobBegin(param *MultipartBlobBeginInput) (*MultipartBlobCommitInput, error) {
   725  	leaseId := uuid.New().String()
   726  	err := b.lease(adl2.Acquire, param.Key, leaseId, 60, "")
   727  	if err == fuse.ENOENT {
   728  		// the file didn't exist, we will create the file
   729  		// first and then acquire the lease
   730  		create, err := b.create(param.Key, adl2.File, param.ContentType, param.Metadata, "")
   731  		if err != nil {
   732  			return nil, err
   733  		}
   734  
   735  		err = b.lease(adl2.Acquire, param.Key, leaseId, 60,
   736  			create.Response.Header.Get("ETag"))
   737  		if err != nil {
   738  			return nil, err
   739  		}
   740  	} else {
   741  		if err != nil {
   742  			return nil, err
   743  		}
   744  
   745  		defer func() {
   746  			if err != nil {
   747  				err2 := b.lease(adl2.Release, param.Key, leaseId, 0, "")
   748  				if err2 != nil {
   749  					adl2Log.Errorf("Unable to release lease for %v: %v",
   750  						param.Key, err2)
   751  				}
   752  			}
   753  		}()
   754  
   755  		_, err = b.create(param.Key, adl2.File, param.ContentType, param.Metadata, leaseId)
   756  		if err != nil {
   757  			return nil, err
   758  		}
   759  
   760  	}
   761  
   762  	commitData := &ADLv2MultipartBlobCommitInput{
   763  		ContentType:    nilStr(param.ContentType),
   764  		RenewLeaseStop: make(chan bool, 1),
   765  	}
   766  
   767  	go func() {
   768  		for {
   769  			select {
   770  			case <-commitData.RenewLeaseStop:
   771  				break
   772  			case <-time.After(30 * time.Second):
   773  				b.lease(adl2.Renew, param.Key, leaseId, 60, "")
   774  			}
   775  		}
   776  	}()
   777  
   778  	return &MultipartBlobCommitInput{
   779  		Key:         &param.Key,
   780  		Metadata:    param.Metadata,
   781  		UploadId:    &leaseId,
   782  		backendData: commitData,
   783  	}, nil
   784  }
   785  
   786  func (b *ADLv2) lease(action adl2.PathLeaseAction, key string, leaseId string, durationSec int32,
   787  	ifMatch string) error {
   788  	var proposeLeaseId string
   789  	var prevLeaseId string
   790  	if action == adl2.Acquire {
   791  		proposeLeaseId = leaseId
   792  	} else {
   793  		prevLeaseId = leaseId
   794  	}
   795  
   796  	var duration *int32
   797  	if durationSec != 0 {
   798  		duration = &durationSec
   799  	}
   800  
   801  	res, err := b.client.Lease(context.TODO(), action, b.bucket, key,
   802  		duration, nil, prevLeaseId, proposeLeaseId, ifMatch, "", "", "", "", nil, "")
   803  	if err != nil {
   804  		err = mapADLv2Error(res.Response, err, false)
   805  	}
   806  	return err
   807  }
   808  
   809  func (b *ADLv2) MultipartBlobAdd(param *MultipartBlobAddInput) (*MultipartBlobAddOutput, error) {
   810  	var commitData *ADLv2MultipartBlobCommitInput
   811  	var ok bool
   812  	if commitData, ok = param.Commit.backendData.(*ADLv2MultipartBlobCommitInput); !ok {
   813  		panic("Incorrect commit data type")
   814  	}
   815  
   816  	res, err := b.append(*param.Commit.Key, int64(param.Offset), int64(param.Size),
   817  		param.Body, *param.Commit.UploadId)
   818  	if err != nil {
   819  		return nil, err
   820  	}
   821  	atomic.AddUint64(&commitData.Size, param.Size)
   822  
   823  	return &MultipartBlobAddOutput{
   824  		res.Response.Header.Get(ADL2_REQUEST_ID),
   825  	}, nil
   826  }
   827  
   828  func (b *ADLv2) MultipartBlobAbort(param *MultipartBlobCommitInput) (*MultipartBlobAbortOutput, error) {
   829  	if param.UploadId != nil {
   830  		err := b.lease(adl2.Release, *param.Key, *param.UploadId, 0, "")
   831  		if err != nil {
   832  			return nil, err
   833  		}
   834  	}
   835  	return &MultipartBlobAbortOutput{}, nil
   836  }
   837  
   838  func (b *ADLv2) MultipartBlobCommit(param *MultipartBlobCommitInput) (*MultipartBlobCommitOutput, error) {
   839  	var commitData *ADLv2MultipartBlobCommitInput
   840  	var ok bool
   841  	if commitData, ok = param.backendData.(*ADLv2MultipartBlobCommitInput); !ok {
   842  		panic("Incorrect commit data type")
   843  	}
   844  
   845  	defer func() {
   846  		commitData.RenewLeaseStop <- true
   847  		leaseId := *param.UploadId
   848  		// if the commit failed, we don't need to release the
   849  		// lease during abort
   850  		param.UploadId = nil
   851  
   852  		err2 := b.lease(adl2.Release, *param.Key, leaseId, 0, "")
   853  		if err2 != nil {
   854  			adl2Log.Errorf("Unable to release lease for %v: %v",
   855  				*param.Key, err2)
   856  		}
   857  	}()
   858  
   859  	flush, err := b.flush(*param.Key, int64(commitData.Size), commitData.ContentType, *param.UploadId)
   860  	if err != nil {
   861  		return nil, err
   862  	}
   863  
   864  	return &MultipartBlobCommitOutput{
   865  		LastModified: parseADLv2Time(flush.Response.Header.Get("Last-Modified")),
   866  		ETag:         getHeader(flush.Response, "ETag"),
   867  		RequestId:    flush.Response.Header.Get(ADL2_REQUEST_ID),
   868  	}, nil
   869  }
   870  
   871  func (b *ADLv2) MultipartExpire(param *MultipartExpireInput) (*MultipartExpireOutput, error) {
   872  	return nil, syscall.ENOTSUP
   873  }
   874  
   875  func (b *ADLv2) RemoveBucket(param *RemoveBucketInput) (*RemoveBucketOutput, error) {
   876  	fs := adl2.FilesystemClient{b.client.BaseClient}
   877  	res, err := fs.Delete(context.TODO(), b.bucket, "", "", uuid.New().String(), nil, "")
   878  	if err != nil {
   879  		return nil, mapADLv2Error(res.Response, err, false)
   880  	}
   881  	return &RemoveBucketOutput{}, nil
   882  }
   883  
   884  func (b *ADLv2) MakeBucket(param *MakeBucketInput) (*MakeBucketOutput, error) {
   885  	fs := adl2.FilesystemClient{b.client.BaseClient}
   886  	res, err := fs.Create(context.TODO(), b.bucket, "", uuid.New().String(), nil, "")
   887  	if err != nil {
   888  		return nil, mapADLv2Error(res.Response, err, false)
   889  	}
   890  	return &MakeBucketOutput{}, nil
   891  }
   892  
   893  // hacked from azure-sdk-for-go
   894  // remove after these bugs are fixed:
   895  // https://github.com/Azure/azure-sdk-for-go/issues/5502
   896  // https://github.com/Azure/azure-sdk-for-go/issues/5550
   897  // https://github.com/Azure/azure-sdk-for-go/issues/5549
   898  type adl2PathClient struct {
   899  	adl2.BaseClient
   900  }
   901  
   902  func (client adl2PathClient) Create(ctx context.Context, filesystem string, pathParameter string, resource adl2.PathResourceType, continuation string, mode adl2.PathRenameMode, cacheControl string, contentEncoding string, contentLanguage string, contentDisposition string, xMsCacheControl string, xMsContentType string, xMsContentEncoding string, xMsContentLanguage string, xMsContentDisposition string, xMsRenameSource string, xMsLeaseID string, xMsSourceLeaseID string, xMsProperties string, xMsPermissions string, xMsUmask string, ifMatch string, ifNoneMatch string, ifModifiedSince string, ifUnmodifiedSince string, xMsSourceIfMatch string, xMsSourceIfNoneMatch string, xMsSourceIfModifiedSince string, xMsSourceIfUnmodifiedSince string, xMsClientRequestID string, timeout *int32, xMsDate string) (result autorest.Response, err error) {
   903  	req, err := client.CreatePreparer(ctx, filesystem, pathParameter, resource, continuation, mode, cacheControl, contentEncoding, contentLanguage, contentDisposition, xMsCacheControl, xMsContentType, xMsContentEncoding, xMsContentLanguage, xMsContentDisposition, xMsRenameSource, xMsLeaseID, xMsSourceLeaseID, xMsProperties, xMsPermissions, xMsUmask, ifMatch, ifNoneMatch, ifModifiedSince, ifUnmodifiedSince, xMsSourceIfMatch, xMsSourceIfNoneMatch, xMsSourceIfModifiedSince, xMsSourceIfUnmodifiedSince, xMsClientRequestID, timeout, xMsDate)
   904  	if err != nil {
   905  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "Create", nil, "Failure preparing request")
   906  		return
   907  	}
   908  
   909  	resp, err := client.CreateSender(req)
   910  	if err != nil {
   911  		result.Response = resp
   912  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "Create", resp, "Failure sending request")
   913  		return
   914  	}
   915  
   916  	result, err = client.CreateResponder(resp)
   917  	if err != nil {
   918  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "Create", resp, "Failure responding to request")
   919  	}
   920  
   921  	return
   922  }
   923  
   924  // CreatePreparer prepares the Create request.
   925  func (client adl2PathClient) CreatePreparer(ctx context.Context, filesystem string, pathParameter string, resource adl2.PathResourceType, continuation string, mode adl2.PathRenameMode, cacheControl string, contentEncoding string, contentLanguage string, contentDisposition string, xMsCacheControl string, xMsContentType string, xMsContentEncoding string, xMsContentLanguage string, xMsContentDisposition string, xMsRenameSource string, xMsLeaseID string, xMsSourceLeaseID string, xMsProperties string, xMsPermissions string, xMsUmask string, ifMatch string, ifNoneMatch string, ifModifiedSince string, ifUnmodifiedSince string, xMsSourceIfMatch string, xMsSourceIfNoneMatch string, xMsSourceIfModifiedSince string, xMsSourceIfUnmodifiedSince string, xMsClientRequestID string, timeout *int32, xMsDate string) (*http.Request, error) {
   926  	urlParameters := map[string]interface{}{
   927  		"accountName": client.AccountName,
   928  		"dnsSuffix":   client.DNSSuffix,
   929  	}
   930  
   931  	pathParameters := map[string]interface{}{
   932  		"filesystem": autorest.Encode("path", filesystem),
   933  		//"path":       url.PathEscape(pathParameter),
   934  		"path": autorest.Encode("path", pathParameter),
   935  	}
   936  
   937  	queryParameters := map[string]interface{}{}
   938  	if len(string(resource)) > 0 {
   939  		queryParameters["resource"] = autorest.Encode("query", resource)
   940  	}
   941  	if len(continuation) > 0 {
   942  		queryParameters["continuation"] = autorest.Encode("query", continuation)
   943  	}
   944  	if len(string(mode)) > 0 {
   945  		queryParameters["mode"] = autorest.Encode("query", mode)
   946  	}
   947  	if timeout != nil {
   948  		queryParameters["timeout"] = autorest.Encode("query", *timeout)
   949  	}
   950  
   951  	preparer := autorest.CreatePreparer(
   952  		autorest.AsPut(),
   953  		autorest.WithCustomBaseURL("http://{accountName}.{dnsSuffix}", urlParameters),
   954  		autorest.WithPathParameters("/{filesystem}/{path}", pathParameters),
   955  		autorest.WithQueryParameters(queryParameters))
   956  	if len(cacheControl) > 0 {
   957  		preparer = autorest.DecoratePreparer(preparer,
   958  			autorest.WithHeader("Cache-Control", autorest.String(cacheControl)))
   959  	}
   960  	if len(contentEncoding) > 0 {
   961  		preparer = autorest.DecoratePreparer(preparer,
   962  			autorest.WithHeader("Content-Encoding", autorest.String(contentEncoding)))
   963  	}
   964  	if len(contentLanguage) > 0 {
   965  		preparer = autorest.DecoratePreparer(preparer,
   966  			autorest.WithHeader("Content-Language", autorest.String(contentLanguage)))
   967  	}
   968  	if len(contentDisposition) > 0 {
   969  		preparer = autorest.DecoratePreparer(preparer,
   970  			autorest.WithHeader("Content-Disposition", autorest.String(contentDisposition)))
   971  	}
   972  	if len(xMsCacheControl) > 0 {
   973  		preparer = autorest.DecoratePreparer(preparer,
   974  			autorest.WithHeader("x-ms-cache-control", autorest.String(xMsCacheControl)))
   975  	}
   976  	if len(xMsContentType) > 0 {
   977  		preparer = autorest.DecoratePreparer(preparer,
   978  			autorest.WithHeader("x-ms-content-type", autorest.String(xMsContentType)))
   979  	}
   980  	if len(xMsContentEncoding) > 0 {
   981  		preparer = autorest.DecoratePreparer(preparer,
   982  			autorest.WithHeader("x-ms-content-encoding", autorest.String(xMsContentEncoding)))
   983  	}
   984  	if len(xMsContentLanguage) > 0 {
   985  		preparer = autorest.DecoratePreparer(preparer,
   986  			autorest.WithHeader("x-ms-content-language", autorest.String(xMsContentLanguage)))
   987  	}
   988  	if len(xMsContentDisposition) > 0 {
   989  		preparer = autorest.DecoratePreparer(preparer,
   990  			autorest.WithHeader("x-ms-content-disposition", autorest.String(xMsContentDisposition)))
   991  	}
   992  	if len(xMsRenameSource) > 0 {
   993  		preparer = autorest.DecoratePreparer(preparer,
   994  			autorest.WithHeader("x-ms-rename-source", autorest.String(xMsRenameSource)))
   995  	}
   996  	if len(xMsLeaseID) > 0 {
   997  		preparer = autorest.DecoratePreparer(preparer,
   998  			autorest.WithHeader("x-ms-lease-id", autorest.String(xMsLeaseID)))
   999  	}
  1000  	if len(xMsSourceLeaseID) > 0 {
  1001  		preparer = autorest.DecoratePreparer(preparer,
  1002  			autorest.WithHeader("x-ms-source-lease-id", autorest.String(xMsSourceLeaseID)))
  1003  	}
  1004  	if len(xMsProperties) > 0 {
  1005  		preparer = autorest.DecoratePreparer(preparer,
  1006  			autorest.WithHeader("x-ms-properties", autorest.String(xMsProperties)))
  1007  	}
  1008  	if len(xMsPermissions) > 0 {
  1009  		preparer = autorest.DecoratePreparer(preparer,
  1010  			autorest.WithHeader("x-ms-permissions", autorest.String(xMsPermissions)))
  1011  	}
  1012  	if len(xMsUmask) > 0 {
  1013  		preparer = autorest.DecoratePreparer(preparer,
  1014  			autorest.WithHeader("x-ms-umask", autorest.String(xMsUmask)))
  1015  	}
  1016  	if len(ifMatch) > 0 {
  1017  		preparer = autorest.DecoratePreparer(preparer,
  1018  			autorest.WithHeader("If-Match", autorest.String(ifMatch)))
  1019  	}
  1020  	if len(ifNoneMatch) > 0 {
  1021  		preparer = autorest.DecoratePreparer(preparer,
  1022  			autorest.WithHeader("If-None-Match", autorest.String(ifNoneMatch)))
  1023  	}
  1024  	if len(ifModifiedSince) > 0 {
  1025  		preparer = autorest.DecoratePreparer(preparer,
  1026  			autorest.WithHeader("If-Modified-Since", autorest.String(ifModifiedSince)))
  1027  	}
  1028  	if len(ifUnmodifiedSince) > 0 {
  1029  		preparer = autorest.DecoratePreparer(preparer,
  1030  			autorest.WithHeader("If-Unmodified-Since", autorest.String(ifUnmodifiedSince)))
  1031  	}
  1032  	if len(xMsSourceIfMatch) > 0 {
  1033  		preparer = autorest.DecoratePreparer(preparer,
  1034  			autorest.WithHeader("x-ms-source-if-match", autorest.String(xMsSourceIfMatch)))
  1035  	}
  1036  	if len(xMsSourceIfNoneMatch) > 0 {
  1037  		preparer = autorest.DecoratePreparer(preparer,
  1038  			autorest.WithHeader("x-ms-source-if-none-match", autorest.String(xMsSourceIfNoneMatch)))
  1039  	}
  1040  	if len(xMsSourceIfModifiedSince) > 0 {
  1041  		preparer = autorest.DecoratePreparer(preparer,
  1042  			autorest.WithHeader("x-ms-source-if-modified-since", autorest.String(xMsSourceIfModifiedSince)))
  1043  	}
  1044  	if len(xMsSourceIfUnmodifiedSince) > 0 {
  1045  		preparer = autorest.DecoratePreparer(preparer,
  1046  			autorest.WithHeader("x-ms-source-if-unmodified-since", autorest.String(xMsSourceIfUnmodifiedSince)))
  1047  	}
  1048  	if len(xMsClientRequestID) > 0 {
  1049  		preparer = autorest.DecoratePreparer(preparer,
  1050  			autorest.WithHeader("x-ms-client-request-id", autorest.String(xMsClientRequestID)))
  1051  	}
  1052  	if len(xMsDate) > 0 {
  1053  		preparer = autorest.DecoratePreparer(preparer,
  1054  			autorest.WithHeader("x-ms-date", autorest.String(xMsDate)))
  1055  	}
  1056  	if len(client.XMsVersion) > 0 {
  1057  		preparer = autorest.DecoratePreparer(preparer,
  1058  			autorest.WithHeader("x-ms-version", autorest.String(client.XMsVersion)))
  1059  	}
  1060  	return preparer.Prepare((client.defaultRequest()).WithContext(ctx))
  1061  }
  1062  
  1063  // CreateSender sends the Create request. The method will close the
  1064  // http.Response Body if it receives an error.
  1065  func (client adl2PathClient) CreateSender(req *http.Request) (*http.Response, error) {
  1066  	sd := autorest.GetSendDecorators(req.Context(), autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
  1067  	return autorest.SendWithSender(client, req, sd...)
  1068  }
  1069  
  1070  // CreateResponder handles the response to the Create request. The method always
  1071  // closes the http.Response Body.
  1072  func (client adl2PathClient) CreateResponder(resp *http.Response) (result autorest.Response, err error) {
  1073  	err = autorest.Respond(
  1074  		resp,
  1075  		client.ByInspecting(),
  1076  		azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated),
  1077  		autorest.ByClosing())
  1078  	result.Response = resp
  1079  	return
  1080  }
  1081  
  1082  func (client adl2PathClient) Delete(ctx context.Context, filesystem string, pathParameter string, recursive *bool, continuation string, xMsLeaseID string, ifMatch string, ifNoneMatch string, ifModifiedSince string, ifUnmodifiedSince string, xMsClientRequestID string, timeout *int32, xMsDate string) (result autorest.Response, err error) {
  1083  	req, err := client.DeletePreparer(ctx, filesystem, pathParameter, recursive, continuation, xMsLeaseID, ifMatch, ifNoneMatch, ifModifiedSince, ifUnmodifiedSince, xMsClientRequestID, timeout, xMsDate)
  1084  	if err != nil {
  1085  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "Delete", nil, "Failure preparing request")
  1086  		return
  1087  	}
  1088  
  1089  	resp, err := client.DeleteSender(req)
  1090  	if err != nil {
  1091  		result.Response = resp
  1092  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "Delete", resp, "Failure sending request")
  1093  		return
  1094  	}
  1095  
  1096  	result, err = client.DeleteResponder(resp)
  1097  	if err != nil {
  1098  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "Delete", resp, "Failure responding to request")
  1099  	}
  1100  
  1101  	return
  1102  }
  1103  
  1104  // DeletePreparer prepares the Delete request.
  1105  func (client adl2PathClient) DeletePreparer(ctx context.Context, filesystem string, pathParameter string, recursive *bool, continuation string, xMsLeaseID string, ifMatch string, ifNoneMatch string, ifModifiedSince string, ifUnmodifiedSince string, xMsClientRequestID string, timeout *int32, xMsDate string) (*http.Request, error) {
  1106  	urlParameters := map[string]interface{}{
  1107  		"accountName": client.AccountName,
  1108  		"dnsSuffix":   client.DNSSuffix,
  1109  	}
  1110  
  1111  	pathParameters := map[string]interface{}{
  1112  		"filesystem": autorest.Encode("path", filesystem),
  1113  		"path":       autorest.Encode("path", pathParameter),
  1114  	}
  1115  
  1116  	queryParameters := map[string]interface{}{}
  1117  	if recursive != nil {
  1118  		queryParameters["recursive"] = autorest.Encode("query", *recursive)
  1119  	}
  1120  	if len(continuation) > 0 {
  1121  		queryParameters["continuation"] = autorest.Encode("query", continuation)
  1122  	}
  1123  	if timeout != nil {
  1124  		queryParameters["timeout"] = autorest.Encode("query", *timeout)
  1125  	}
  1126  
  1127  	preparer := autorest.CreatePreparer(
  1128  		autorest.AsDelete(),
  1129  		autorest.WithCustomBaseURL("http://{accountName}.{dnsSuffix}", urlParameters),
  1130  		autorest.WithPathParameters("/{filesystem}/{path}", pathParameters),
  1131  		autorest.WithQueryParameters(queryParameters))
  1132  	if len(xMsLeaseID) > 0 {
  1133  		preparer = autorest.DecoratePreparer(preparer,
  1134  			autorest.WithHeader("x-ms-lease-id", autorest.String(xMsLeaseID)))
  1135  	}
  1136  	if len(ifMatch) > 0 {
  1137  		preparer = autorest.DecoratePreparer(preparer,
  1138  			autorest.WithHeader("If-Match", autorest.String(ifMatch)))
  1139  	}
  1140  	if len(ifNoneMatch) > 0 {
  1141  		preparer = autorest.DecoratePreparer(preparer,
  1142  			autorest.WithHeader("If-None-Match", autorest.String(ifNoneMatch)))
  1143  	}
  1144  	if len(ifModifiedSince) > 0 {
  1145  		preparer = autorest.DecoratePreparer(preparer,
  1146  			autorest.WithHeader("If-Modified-Since", autorest.String(ifModifiedSince)))
  1147  	}
  1148  	if len(ifUnmodifiedSince) > 0 {
  1149  		preparer = autorest.DecoratePreparer(preparer,
  1150  			autorest.WithHeader("If-Unmodified-Since", autorest.String(ifUnmodifiedSince)))
  1151  	}
  1152  	if len(xMsClientRequestID) > 0 {
  1153  		preparer = autorest.DecoratePreparer(preparer,
  1154  			autorest.WithHeader("x-ms-client-request-id", autorest.String(xMsClientRequestID)))
  1155  	}
  1156  	if len(xMsDate) > 0 {
  1157  		preparer = autorest.DecoratePreparer(preparer,
  1158  			autorest.WithHeader("x-ms-date", autorest.String(xMsDate)))
  1159  	}
  1160  	if len(client.XMsVersion) > 0 {
  1161  		preparer = autorest.DecoratePreparer(preparer,
  1162  			autorest.WithHeader("x-ms-version", autorest.String(client.XMsVersion)))
  1163  	}
  1164  	return preparer.Prepare((client.defaultRequest()).WithContext(ctx))
  1165  }
  1166  
  1167  // DeleteSender sends the Delete request. The method will close the
  1168  // http.Response Body if it receives an error.
  1169  func (client adl2PathClient) DeleteSender(req *http.Request) (*http.Response, error) {
  1170  	sd := autorest.GetSendDecorators(req.Context(), autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
  1171  	return autorest.SendWithSender(client, req, sd...)
  1172  }
  1173  
  1174  // DeleteResponder handles the response to the Delete request. The method always
  1175  // closes the http.Response Body.
  1176  func (client adl2PathClient) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
  1177  	err = autorest.Respond(
  1178  		resp,
  1179  		client.ByInspecting(),
  1180  		azure.WithErrorUnlessStatusCode(http.StatusOK),
  1181  		autorest.ByClosing())
  1182  	result.Response = resp
  1183  	return
  1184  }
  1185  
  1186  func (client adl2PathClient) GetProperties(ctx context.Context, filesystem string, pathParameter string, action adl2.PathGetPropertiesAction, upn *bool, xMsLeaseID string, ifMatch string, ifNoneMatch string, ifModifiedSince string, ifUnmodifiedSince string, xMsClientRequestID string, timeout *int32, xMsDate string) (result autorest.Response, err error) {
  1187  	req, err := client.GetPropertiesPreparer(ctx, filesystem, pathParameter, action, upn, xMsLeaseID, ifMatch, ifNoneMatch, ifModifiedSince, ifUnmodifiedSince, xMsClientRequestID, timeout, xMsDate)
  1188  	if err != nil {
  1189  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "GetProperties", nil, "Failure preparing request")
  1190  		return
  1191  	}
  1192  
  1193  	resp, err := client.GetPropertiesSender(req)
  1194  	if err != nil {
  1195  		result.Response = resp
  1196  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "GetProperties", resp, "Failure sending request")
  1197  		return
  1198  	}
  1199  
  1200  	result, err = client.GetPropertiesResponder(resp)
  1201  	if err != nil {
  1202  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "GetProperties", resp, "Failure responding to request")
  1203  	}
  1204  
  1205  	return
  1206  }
  1207  
  1208  // GetPropertiesPreparer prepares the GetProperties request.
  1209  func (client adl2PathClient) GetPropertiesPreparer(ctx context.Context, filesystem string, pathParameter string, action adl2.PathGetPropertiesAction, upn *bool, xMsLeaseID string, ifMatch string, ifNoneMatch string, ifModifiedSince string, ifUnmodifiedSince string, xMsClientRequestID string, timeout *int32, xMsDate string) (*http.Request, error) {
  1210  	urlParameters := map[string]interface{}{
  1211  		"accountName": client.AccountName,
  1212  		"dnsSuffix":   client.DNSSuffix,
  1213  	}
  1214  
  1215  	pathParameters := map[string]interface{}{
  1216  		"filesystem": autorest.Encode("path", filesystem),
  1217  		"path":       autorest.Encode("path", pathParameter),
  1218  	}
  1219  
  1220  	queryParameters := map[string]interface{}{}
  1221  	if len(string(action)) > 0 {
  1222  		queryParameters["action"] = autorest.Encode("query", action)
  1223  	}
  1224  	if upn != nil {
  1225  		queryParameters["upn"] = autorest.Encode("query", *upn)
  1226  	}
  1227  	if timeout != nil {
  1228  		queryParameters["timeout"] = autorest.Encode("query", *timeout)
  1229  	}
  1230  
  1231  	preparer := autorest.CreatePreparer(
  1232  		autorest.AsHead(),
  1233  		autorest.WithCustomBaseURL("http://{accountName}.{dnsSuffix}", urlParameters),
  1234  		autorest.WithPathParameters("/{filesystem}/{path}", pathParameters),
  1235  		autorest.WithQueryParameters(queryParameters))
  1236  	if len(xMsLeaseID) > 0 {
  1237  		preparer = autorest.DecoratePreparer(preparer,
  1238  			autorest.WithHeader("x-ms-lease-id", autorest.String(xMsLeaseID)))
  1239  	}
  1240  	if len(ifMatch) > 0 {
  1241  		preparer = autorest.DecoratePreparer(preparer,
  1242  			autorest.WithHeader("If-Match", autorest.String(ifMatch)))
  1243  	}
  1244  	if len(ifNoneMatch) > 0 {
  1245  		preparer = autorest.DecoratePreparer(preparer,
  1246  			autorest.WithHeader("If-None-Match", autorest.String(ifNoneMatch)))
  1247  	}
  1248  	if len(ifModifiedSince) > 0 {
  1249  		preparer = autorest.DecoratePreparer(preparer,
  1250  			autorest.WithHeader("If-Modified-Since", autorest.String(ifModifiedSince)))
  1251  	}
  1252  	if len(ifUnmodifiedSince) > 0 {
  1253  		preparer = autorest.DecoratePreparer(preparer,
  1254  			autorest.WithHeader("If-Unmodified-Since", autorest.String(ifUnmodifiedSince)))
  1255  	}
  1256  	if len(xMsClientRequestID) > 0 {
  1257  		preparer = autorest.DecoratePreparer(preparer,
  1258  			autorest.WithHeader("x-ms-client-request-id", autorest.String(xMsClientRequestID)))
  1259  	}
  1260  	if len(xMsDate) > 0 {
  1261  		preparer = autorest.DecoratePreparer(preparer,
  1262  			autorest.WithHeader("x-ms-date", autorest.String(xMsDate)))
  1263  	}
  1264  	if len(client.XMsVersion) > 0 {
  1265  		preparer = autorest.DecoratePreparer(preparer,
  1266  			autorest.WithHeader("x-ms-version", autorest.String(client.XMsVersion)))
  1267  	}
  1268  	return preparer.Prepare((client.defaultRequest()).WithContext(ctx))
  1269  }
  1270  
  1271  // GetPropertiesSender sends the GetProperties request. The method will close the
  1272  // http.Response Body if it receives an error.
  1273  func (client adl2PathClient) GetPropertiesSender(req *http.Request) (*http.Response, error) {
  1274  	sd := autorest.GetSendDecorators(req.Context(), autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
  1275  	return autorest.SendWithSender(client, req, sd...)
  1276  }
  1277  
  1278  // GetPropertiesResponder handles the response to the GetProperties request. The method always
  1279  // closes the http.Response Body.
  1280  func (client adl2PathClient) GetPropertiesResponder(resp *http.Response) (result autorest.Response, err error) {
  1281  	err = autorest.Respond(
  1282  		resp,
  1283  		client.ByInspecting(),
  1284  		azure.WithErrorUnlessStatusCode(http.StatusOK),
  1285  		autorest.ByClosing())
  1286  	result.Response = resp
  1287  	return
  1288  }
  1289  
  1290  func (client adl2PathClient) Lease(ctx context.Context, xMsLeaseAction adl2.PathLeaseAction, filesystem string, pathParameter string, xMsLeaseDuration *int32, xMsLeaseBreakPeriod *int32, xMsLeaseID string, xMsProposedLeaseID string, ifMatch string, ifNoneMatch string, ifModifiedSince string, ifUnmodifiedSince string, xMsClientRequestID string, timeout *int32, xMsDate string) (result autorest.Response, err error) {
  1291  	req, err := client.LeasePreparer(ctx, xMsLeaseAction, filesystem, pathParameter, xMsLeaseDuration, xMsLeaseBreakPeriod, xMsLeaseID, xMsProposedLeaseID, ifMatch, ifNoneMatch, ifModifiedSince, ifUnmodifiedSince, xMsClientRequestID, timeout, xMsDate)
  1292  	if err != nil {
  1293  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "Lease", nil, "Failure preparing request")
  1294  		return
  1295  	}
  1296  
  1297  	resp, err := client.LeaseSender(req)
  1298  	if err != nil {
  1299  		result.Response = resp
  1300  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "Lease", resp, "Failure sending request")
  1301  		return
  1302  	}
  1303  
  1304  	result, err = client.LeaseResponder(resp)
  1305  	if err != nil {
  1306  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "Lease", resp, "Failure responding to request")
  1307  	}
  1308  
  1309  	return
  1310  }
  1311  
  1312  // LeasePreparer prepares the Lease request.
  1313  func (client adl2PathClient) LeasePreparer(ctx context.Context, xMsLeaseAction adl2.PathLeaseAction, filesystem string, pathParameter string, xMsLeaseDuration *int32, xMsLeaseBreakPeriod *int32, xMsLeaseID string, xMsProposedLeaseID string, ifMatch string, ifNoneMatch string, ifModifiedSince string, ifUnmodifiedSince string, xMsClientRequestID string, timeout *int32, xMsDate string) (*http.Request, error) {
  1314  	urlParameters := map[string]interface{}{
  1315  		"accountName": client.AccountName,
  1316  		"dnsSuffix":   client.DNSSuffix,
  1317  	}
  1318  
  1319  	pathParameters := map[string]interface{}{
  1320  		"filesystem": autorest.Encode("path", filesystem),
  1321  		"path":       autorest.Encode("path", pathParameter),
  1322  	}
  1323  
  1324  	queryParameters := map[string]interface{}{}
  1325  	if timeout != nil {
  1326  		queryParameters["timeout"] = autorest.Encode("query", *timeout)
  1327  	}
  1328  
  1329  	preparer := autorest.CreatePreparer(
  1330  		autorest.AsPost(),
  1331  		autorest.WithCustomBaseURL("http://{accountName}.{dnsSuffix}", urlParameters),
  1332  		autorest.WithPathParameters("/{filesystem}/{path}", pathParameters),
  1333  		autorest.WithQueryParameters(queryParameters),
  1334  		autorest.WithHeader("x-ms-lease-action", autorest.String(xMsLeaseAction)))
  1335  	if xMsLeaseDuration != nil {
  1336  		preparer = autorest.DecoratePreparer(preparer,
  1337  			autorest.WithHeader("x-ms-lease-duration", autorest.String(*xMsLeaseDuration)))
  1338  	}
  1339  	if xMsLeaseBreakPeriod != nil {
  1340  		preparer = autorest.DecoratePreparer(preparer,
  1341  			autorest.WithHeader("x-ms-lease-break-period", autorest.String(*xMsLeaseBreakPeriod)))
  1342  	}
  1343  	if len(xMsLeaseID) > 0 {
  1344  		preparer = autorest.DecoratePreparer(preparer,
  1345  			autorest.WithHeader("x-ms-lease-id", autorest.String(xMsLeaseID)))
  1346  	}
  1347  	if len(xMsProposedLeaseID) > 0 {
  1348  		preparer = autorest.DecoratePreparer(preparer,
  1349  			autorest.WithHeader("x-ms-proposed-lease-id", autorest.String(xMsProposedLeaseID)))
  1350  	}
  1351  	if len(ifMatch) > 0 {
  1352  		preparer = autorest.DecoratePreparer(preparer,
  1353  			autorest.WithHeader("If-Match", autorest.String(ifMatch)))
  1354  	}
  1355  	if len(ifNoneMatch) > 0 {
  1356  		preparer = autorest.DecoratePreparer(preparer,
  1357  			autorest.WithHeader("If-None-Match", autorest.String(ifNoneMatch)))
  1358  	}
  1359  	if len(ifModifiedSince) > 0 {
  1360  		preparer = autorest.DecoratePreparer(preparer,
  1361  			autorest.WithHeader("If-Modified-Since", autorest.String(ifModifiedSince)))
  1362  	}
  1363  	if len(ifUnmodifiedSince) > 0 {
  1364  		preparer = autorest.DecoratePreparer(preparer,
  1365  			autorest.WithHeader("If-Unmodified-Since", autorest.String(ifUnmodifiedSince)))
  1366  	}
  1367  	if len(xMsClientRequestID) > 0 {
  1368  		preparer = autorest.DecoratePreparer(preparer,
  1369  			autorest.WithHeader("x-ms-client-request-id", autorest.String(xMsClientRequestID)))
  1370  	}
  1371  	if len(xMsDate) > 0 {
  1372  		preparer = autorest.DecoratePreparer(preparer,
  1373  			autorest.WithHeader("x-ms-date", autorest.String(xMsDate)))
  1374  	}
  1375  	if len(client.XMsVersion) > 0 {
  1376  		preparer = autorest.DecoratePreparer(preparer,
  1377  			autorest.WithHeader("x-ms-version", autorest.String(client.XMsVersion)))
  1378  	}
  1379  	return preparer.Prepare((client.defaultRequest()).WithContext(ctx))
  1380  }
  1381  
  1382  // LeaseSender sends the Lease request. The method will close the
  1383  // http.Response Body if it receives an error.
  1384  func (client adl2PathClient) LeaseSender(req *http.Request) (*http.Response, error) {
  1385  	sd := autorest.GetSendDecorators(req.Context(), autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
  1386  	return autorest.SendWithSender(client, req, sd...)
  1387  }
  1388  
  1389  // LeaseResponder handles the response to the Lease request. The method always
  1390  // closes the http.Response Body.
  1391  func (client adl2PathClient) LeaseResponder(resp *http.Response) (result autorest.Response, err error) {
  1392  	err = autorest.Respond(
  1393  		resp,
  1394  		client.ByInspecting(),
  1395  		azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated, http.StatusAccepted),
  1396  		autorest.ByClosing())
  1397  	result.Response = resp
  1398  	return
  1399  }
  1400  
  1401  func (client adl2PathClient) List(ctx context.Context, recursive bool, filesystem string, directory string, continuation string, maxResults *int32, upn *bool, xMsClientRequestID string, timeout *int32, xMsDate string) (result adl2PathList, err error) {
  1402  	req, err := client.ListPreparer(ctx, recursive, filesystem, directory, continuation, maxResults, upn, xMsClientRequestID, timeout, xMsDate)
  1403  	if err != nil {
  1404  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "List", nil, "Failure preparing request")
  1405  		return
  1406  	}
  1407  
  1408  	resp, err := client.ListSender(req)
  1409  	if err != nil {
  1410  		result.Response = autorest.Response{Response: resp}
  1411  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "List", resp, "Failure sending request")
  1412  		return
  1413  	}
  1414  
  1415  	result, err = client.ListResponder(resp)
  1416  	if err != nil {
  1417  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "List", resp, "Failure responding to request")
  1418  	}
  1419  
  1420  	return
  1421  }
  1422  
  1423  // ListPreparer prepares the List request.
  1424  func (client adl2PathClient) ListPreparer(ctx context.Context, recursive bool, filesystem string, directory string, continuation string, maxResults *int32, upn *bool, xMsClientRequestID string, timeout *int32, xMsDate string) (*http.Request, error) {
  1425  	urlParameters := map[string]interface{}{
  1426  		"accountName": client.AccountName,
  1427  		"dnsSuffix":   client.DNSSuffix,
  1428  	}
  1429  
  1430  	pathParameters := map[string]interface{}{
  1431  		"filesystem": autorest.Encode("path", filesystem),
  1432  	}
  1433  
  1434  	queryParameters := map[string]interface{}{
  1435  		"recursive": autorest.Encode("query", recursive),
  1436  		"resource":  autorest.Encode("query", "filesystem"),
  1437  	}
  1438  	if len(directory) > 0 {
  1439  		queryParameters["directory"] = autorest.Encode("query", directory)
  1440  	}
  1441  	if len(continuation) > 0 {
  1442  		queryParameters["continuation"] = autorest.Encode("query", continuation)
  1443  	}
  1444  	if maxResults != nil {
  1445  		queryParameters["maxresults"] = autorest.Encode("query", *maxResults)
  1446  	}
  1447  	if upn != nil {
  1448  		queryParameters["upn"] = autorest.Encode("query", *upn)
  1449  	}
  1450  	if timeout != nil {
  1451  		queryParameters["timeout"] = autorest.Encode("query", *timeout)
  1452  	}
  1453  
  1454  	preparer := autorest.CreatePreparer(
  1455  		autorest.AsGet(),
  1456  		autorest.WithCustomBaseURL("http://{accountName}.{dnsSuffix}", urlParameters),
  1457  		autorest.WithPathParameters("/{filesystem}", pathParameters),
  1458  		autorest.WithQueryParameters(queryParameters))
  1459  	if len(xMsClientRequestID) > 0 {
  1460  		preparer = autorest.DecoratePreparer(preparer,
  1461  			autorest.WithHeader("x-ms-client-request-id", autorest.String(xMsClientRequestID)))
  1462  	}
  1463  	if len(xMsDate) > 0 {
  1464  		preparer = autorest.DecoratePreparer(preparer,
  1465  			autorest.WithHeader("x-ms-date", autorest.String(xMsDate)))
  1466  	}
  1467  	if len(client.XMsVersion) > 0 {
  1468  		preparer = autorest.DecoratePreparer(preparer,
  1469  			autorest.WithHeader("x-ms-version", autorest.String(client.XMsVersion)))
  1470  	}
  1471  	return preparer.Prepare((client.defaultRequest()).WithContext(ctx))
  1472  }
  1473  
  1474  // ListSender sends the List request. The method will close the
  1475  // http.Response Body if it receives an error.
  1476  func (client adl2PathClient) ListSender(req *http.Request) (*http.Response, error) {
  1477  	sd := autorest.GetSendDecorators(req.Context(), autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
  1478  	return autorest.SendWithSender(client, req, sd...)
  1479  }
  1480  
  1481  // ListResponder handles the response to the List request. The method always
  1482  // closes the http.Response Body.
  1483  func (client adl2PathClient) ListResponder(resp *http.Response) (result adl2PathList, err error) {
  1484  	err = autorest.Respond(
  1485  		resp,
  1486  		client.ByInspecting(),
  1487  		azure.WithErrorUnlessStatusCode(http.StatusOK),
  1488  		autorest.ByUnmarshallingJSON(&result),
  1489  		autorest.ByClosing())
  1490  	result.Response = autorest.Response{Response: resp}
  1491  	return
  1492  }
  1493  
  1494  func (client adl2PathClient) Read(ctx context.Context, filesystem string, pathParameter string, rangeParameter string, xMsLeaseID string, xMsRangeGetContentMd5 *bool, ifMatch string, ifNoneMatch string, ifModifiedSince string, ifUnmodifiedSince string, xMsClientRequestID string, timeout *int32, xMsDate string) (result adl2.ReadCloser, err error) {
  1495  	req, err := client.ReadPreparer(ctx, filesystem, pathParameter, rangeParameter, xMsLeaseID, xMsRangeGetContentMd5, ifMatch, ifNoneMatch, ifModifiedSince, ifUnmodifiedSince, xMsClientRequestID, timeout, xMsDate)
  1496  	if err != nil {
  1497  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "Read", nil, "Failure preparing request")
  1498  		return
  1499  	}
  1500  
  1501  	resp, err := client.ReadSender(req)
  1502  	if err != nil {
  1503  		result.Response = autorest.Response{Response: resp}
  1504  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "Read", resp, "Failure sending request")
  1505  		return
  1506  	}
  1507  
  1508  	result, err = client.ReadResponder(resp)
  1509  	if err != nil {
  1510  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "Read", resp, "Failure responding to request")
  1511  	}
  1512  
  1513  	return
  1514  }
  1515  
  1516  // ReadPreparer prepares the Read request.
  1517  func (client adl2PathClient) ReadPreparer(ctx context.Context, filesystem string, pathParameter string, rangeParameter string, xMsLeaseID string, xMsRangeGetContentMd5 *bool, ifMatch string, ifNoneMatch string, ifModifiedSince string, ifUnmodifiedSince string, xMsClientRequestID string, timeout *int32, xMsDate string) (*http.Request, error) {
  1518  	urlParameters := map[string]interface{}{
  1519  		"accountName": client.AccountName,
  1520  		"dnsSuffix":   client.DNSSuffix,
  1521  	}
  1522  
  1523  	pathParameters := map[string]interface{}{
  1524  		"filesystem": autorest.Encode("path", filesystem),
  1525  		"path":       autorest.Encode("path", pathParameter),
  1526  	}
  1527  
  1528  	queryParameters := map[string]interface{}{}
  1529  	if timeout != nil {
  1530  		queryParameters["timeout"] = autorest.Encode("query", *timeout)
  1531  	}
  1532  
  1533  	preparer := autorest.CreatePreparer(
  1534  		autorest.AsGet(),
  1535  		autorest.WithCustomBaseURL("http://{accountName}.{dnsSuffix}", urlParameters),
  1536  		autorest.WithPathParameters("/{filesystem}/{path}", pathParameters),
  1537  		autorest.WithQueryParameters(queryParameters))
  1538  	if len(rangeParameter) > 0 {
  1539  		preparer = autorest.DecoratePreparer(preparer,
  1540  			autorest.WithHeader("Range", autorest.String(rangeParameter)))
  1541  	}
  1542  	if len(xMsLeaseID) > 0 {
  1543  		preparer = autorest.DecoratePreparer(preparer,
  1544  			autorest.WithHeader("x-ms-lease-id", autorest.String(xMsLeaseID)))
  1545  	}
  1546  	if xMsRangeGetContentMd5 != nil {
  1547  		preparer = autorest.DecoratePreparer(preparer,
  1548  			autorest.WithHeader("x-ms-range-get-content-md5", autorest.String(*xMsRangeGetContentMd5)))
  1549  	}
  1550  	if len(ifMatch) > 0 {
  1551  		preparer = autorest.DecoratePreparer(preparer,
  1552  			autorest.WithHeader("If-Match", autorest.String(ifMatch)))
  1553  	}
  1554  	if len(ifNoneMatch) > 0 {
  1555  		preparer = autorest.DecoratePreparer(preparer,
  1556  			autorest.WithHeader("If-None-Match", autorest.String(ifNoneMatch)))
  1557  	}
  1558  	if len(ifModifiedSince) > 0 {
  1559  		preparer = autorest.DecoratePreparer(preparer,
  1560  			autorest.WithHeader("If-Modified-Since", autorest.String(ifModifiedSince)))
  1561  	}
  1562  	if len(ifUnmodifiedSince) > 0 {
  1563  		preparer = autorest.DecoratePreparer(preparer,
  1564  			autorest.WithHeader("If-Unmodified-Since", autorest.String(ifUnmodifiedSince)))
  1565  	}
  1566  	if len(xMsClientRequestID) > 0 {
  1567  		preparer = autorest.DecoratePreparer(preparer,
  1568  			autorest.WithHeader("x-ms-client-request-id", autorest.String(xMsClientRequestID)))
  1569  	}
  1570  	if len(xMsDate) > 0 {
  1571  		preparer = autorest.DecoratePreparer(preparer,
  1572  			autorest.WithHeader("x-ms-date", autorest.String(xMsDate)))
  1573  	}
  1574  	if len(client.XMsVersion) > 0 {
  1575  		preparer = autorest.DecoratePreparer(preparer,
  1576  			autorest.WithHeader("x-ms-version", autorest.String(client.XMsVersion)))
  1577  	}
  1578  	return preparer.Prepare((client.defaultRequest()).WithContext(ctx))
  1579  }
  1580  
  1581  // ReadSender sends the Read request. The method will close the
  1582  // http.Response Body if it receives an error.
  1583  func (client adl2PathClient) ReadSender(req *http.Request) (*http.Response, error) {
  1584  	sd := autorest.GetSendDecorators(req.Context(), autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
  1585  	return autorest.SendWithSender(client, req, sd...)
  1586  }
  1587  
  1588  // ReadResponder handles the response to the Read request. The method always
  1589  // closes the http.Response Body.
  1590  func (client adl2PathClient) ReadResponder(resp *http.Response) (result adl2.ReadCloser, err error) {
  1591  	result.Value = &resp.Body
  1592  	err = autorest.Respond(
  1593  		resp,
  1594  		client.ByInspecting(),
  1595  		azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusPartialContent))
  1596  	result.Response = autorest.Response{Response: resp}
  1597  	return
  1598  }
  1599  
  1600  func (client adl2PathClient) Update(ctx context.Context, action adl2.PathUpdateAction, filesystem string, pathParameter string, position *int64, retainUncommittedData *bool, closeParameter *bool, contentLength *int64, contentMD5 string, xMsLeaseID string, xMsCacheControl string, xMsContentType string, xMsContentDisposition string, xMsContentEncoding string, xMsContentLanguage string, xMsContentMd5 string, xMsProperties string, xMsOwner string, xMsGroup string, xMsPermissions string, xMsACL string, ifMatch string, ifNoneMatch string, ifModifiedSince string, ifUnmodifiedSince string, requestBody io.ReadCloser, xMsClientRequestID string, timeout *int32, xMsDate string) (result autorest.Response, err error) {
  1601  	req, err := client.UpdatePreparer(ctx, action, filesystem, pathParameter, position, retainUncommittedData, closeParameter, contentLength, contentMD5, xMsLeaseID, xMsCacheControl, xMsContentType, xMsContentDisposition, xMsContentEncoding, xMsContentLanguage, xMsContentMd5, xMsProperties, xMsOwner, xMsGroup, xMsPermissions, xMsACL, ifMatch, ifNoneMatch, ifModifiedSince, ifUnmodifiedSince, requestBody, xMsClientRequestID, timeout, xMsDate)
  1602  	if err != nil {
  1603  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "Update", nil, "Failure preparing request")
  1604  		return
  1605  	}
  1606  
  1607  	resp, err := client.UpdateSender(req)
  1608  	if err != nil {
  1609  		result.Response = resp
  1610  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "Update", resp, "Failure sending request")
  1611  		return
  1612  	}
  1613  
  1614  	result, err = client.UpdateResponder(resp)
  1615  	if err != nil {
  1616  		err = autorest.NewErrorWithError(err, "storagedatalake.adl2PathClient", "Update", resp, "Failure responding to request")
  1617  	}
  1618  
  1619  	return
  1620  }
  1621  
  1622  // UpdatePreparer prepares the Update request.
  1623  func (client adl2PathClient) UpdatePreparer(ctx context.Context, action adl2.PathUpdateAction, filesystem string, pathParameter string, position *int64, retainUncommittedData *bool, closeParameter *bool, contentLength *int64, contentMD5 string, xMsLeaseID string, xMsCacheControl string, xMsContentType string, xMsContentDisposition string, xMsContentEncoding string, xMsContentLanguage string, xMsContentMd5 string, xMsProperties string, xMsOwner string, xMsGroup string, xMsPermissions string, xMsACL string, ifMatch string, ifNoneMatch string, ifModifiedSince string, ifUnmodifiedSince string, requestBody io.ReadCloser, xMsClientRequestID string, timeout *int32, xMsDate string) (*http.Request, error) {
  1624  	urlParameters := map[string]interface{}{
  1625  		"accountName": client.AccountName,
  1626  		"dnsSuffix":   client.DNSSuffix,
  1627  	}
  1628  
  1629  	pathParameters := map[string]interface{}{
  1630  		"filesystem": autorest.Encode("path", filesystem),
  1631  		"path":       autorest.Encode("path", pathParameter),
  1632  	}
  1633  
  1634  	queryParameters := map[string]interface{}{
  1635  		"action": autorest.Encode("query", action),
  1636  	}
  1637  	if position != nil {
  1638  		queryParameters["position"] = autorest.Encode("query", *position)
  1639  	}
  1640  	if retainUncommittedData != nil {
  1641  		// query params need to be lower case otherwise azure-storage-blob-go's
  1642  		// SharedKeyCredential signing won't work:
  1643  		// https://github.com/Azure/azure-storage-blob-go/issues/146
  1644  		queryParameters["retainuncommitteddata"] = autorest.Encode("query", *retainUncommittedData)
  1645  	}
  1646  	if closeParameter != nil {
  1647  		queryParameters["close"] = autorest.Encode("query", *closeParameter)
  1648  	}
  1649  	if timeout != nil {
  1650  		queryParameters["timeout"] = autorest.Encode("query", *timeout)
  1651  	}
  1652  
  1653  	preparer := autorest.CreatePreparer(
  1654  		autorest.AsContentType("application/octet-stream"),
  1655  		autorest.AsPatch(),
  1656  		autorest.WithCustomBaseURL("http://{accountName}.{dnsSuffix}", urlParameters),
  1657  		autorest.WithPathParameters("/{filesystem}/{path}", pathParameters),
  1658  		autorest.WithQueryParameters(queryParameters))
  1659  	if requestBody != nil {
  1660  		preparer = autorest.DecoratePreparer(preparer,
  1661  			autorest.WithFile(requestBody))
  1662  	}
  1663  	if contentLength != nil {
  1664  		preparer = autorest.DecoratePreparer(preparer,
  1665  			autorest.WithHeader("Content-Length", autorest.String(*contentLength)))
  1666  	}
  1667  	if len(contentMD5) > 0 {
  1668  		preparer = autorest.DecoratePreparer(preparer,
  1669  			autorest.WithHeader("Content-MD5", autorest.String(contentMD5)))
  1670  	}
  1671  	if len(xMsLeaseID) > 0 {
  1672  		preparer = autorest.DecoratePreparer(preparer,
  1673  			autorest.WithHeader("x-ms-lease-id", autorest.String(xMsLeaseID)))
  1674  	}
  1675  	if len(xMsCacheControl) > 0 {
  1676  		preparer = autorest.DecoratePreparer(preparer,
  1677  			autorest.WithHeader("x-ms-cache-control", autorest.String(xMsCacheControl)))
  1678  	}
  1679  	if len(xMsContentType) > 0 {
  1680  		preparer = autorest.DecoratePreparer(preparer,
  1681  			autorest.WithHeader("x-ms-content-type", autorest.String(xMsContentType)))
  1682  	}
  1683  	if len(xMsContentDisposition) > 0 {
  1684  		preparer = autorest.DecoratePreparer(preparer,
  1685  			autorest.WithHeader("x-ms-content-disposition", autorest.String(xMsContentDisposition)))
  1686  	}
  1687  	if len(xMsContentEncoding) > 0 {
  1688  		preparer = autorest.DecoratePreparer(preparer,
  1689  			autorest.WithHeader("x-ms-content-encoding", autorest.String(xMsContentEncoding)))
  1690  	}
  1691  	if len(xMsContentLanguage) > 0 {
  1692  		preparer = autorest.DecoratePreparer(preparer,
  1693  			autorest.WithHeader("x-ms-content-language", autorest.String(xMsContentLanguage)))
  1694  	}
  1695  	if len(xMsContentMd5) > 0 {
  1696  		preparer = autorest.DecoratePreparer(preparer,
  1697  			autorest.WithHeader("x-ms-content-md5", autorest.String(xMsContentMd5)))
  1698  	}
  1699  	if len(xMsProperties) > 0 {
  1700  		preparer = autorest.DecoratePreparer(preparer,
  1701  			autorest.WithHeader("x-ms-properties", autorest.String(xMsProperties)))
  1702  	}
  1703  	if len(xMsOwner) > 0 {
  1704  		preparer = autorest.DecoratePreparer(preparer,
  1705  			autorest.WithHeader("x-ms-owner", autorest.String(xMsOwner)))
  1706  	}
  1707  	if len(xMsGroup) > 0 {
  1708  		preparer = autorest.DecoratePreparer(preparer,
  1709  			autorest.WithHeader("x-ms-group", autorest.String(xMsGroup)))
  1710  	}
  1711  	if len(xMsPermissions) > 0 {
  1712  		preparer = autorest.DecoratePreparer(preparer,
  1713  			autorest.WithHeader("x-ms-permissions", autorest.String(xMsPermissions)))
  1714  	}
  1715  	if len(xMsACL) > 0 {
  1716  		preparer = autorest.DecoratePreparer(preparer,
  1717  			autorest.WithHeader("x-ms-acl", autorest.String(xMsACL)))
  1718  	}
  1719  	if len(ifMatch) > 0 {
  1720  		preparer = autorest.DecoratePreparer(preparer,
  1721  			autorest.WithHeader("If-Match", autorest.String(ifMatch)))
  1722  	}
  1723  	if len(ifNoneMatch) > 0 {
  1724  		preparer = autorest.DecoratePreparer(preparer,
  1725  			autorest.WithHeader("If-None-Match", autorest.String(ifNoneMatch)))
  1726  	}
  1727  	if len(ifModifiedSince) > 0 {
  1728  		preparer = autorest.DecoratePreparer(preparer,
  1729  			autorest.WithHeader("If-Modified-Since", autorest.String(ifModifiedSince)))
  1730  	}
  1731  	if len(ifUnmodifiedSince) > 0 {
  1732  		preparer = autorest.DecoratePreparer(preparer,
  1733  			autorest.WithHeader("If-Unmodified-Since", autorest.String(ifUnmodifiedSince)))
  1734  	}
  1735  	if len(xMsClientRequestID) > 0 {
  1736  		preparer = autorest.DecoratePreparer(preparer,
  1737  			autorest.WithHeader("x-ms-client-request-id", autorest.String(xMsClientRequestID)))
  1738  	}
  1739  	if len(xMsDate) > 0 {
  1740  		preparer = autorest.DecoratePreparer(preparer,
  1741  			autorest.WithHeader("x-ms-date", autorest.String(xMsDate)))
  1742  	}
  1743  	if len(client.XMsVersion) > 0 {
  1744  		preparer = autorest.DecoratePreparer(preparer,
  1745  			autorest.WithHeader("x-ms-version", autorest.String(client.XMsVersion)))
  1746  	}
  1747  	return preparer.Prepare((client.defaultRequest()).WithContext(ctx))
  1748  }
  1749  
  1750  // UpdateSender sends the Update request. The method will close the
  1751  // http.Response Body if it receives an error.
  1752  func (client adl2PathClient) UpdateSender(req *http.Request) (*http.Response, error) {
  1753  
  1754  	sd := autorest.GetSendDecorators(req.Context(), autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
  1755  	return autorest.SendWithSender(client, req, sd...)
  1756  }
  1757  
  1758  // UpdateResponder handles the response to the Update request. The method always
  1759  // closes the http.Response Body.
  1760  func (client adl2PathClient) UpdateResponder(resp *http.Response) (result autorest.Response, err error) {
  1761  	err = autorest.Respond(
  1762  		resp,
  1763  		client.ByInspecting(),
  1764  		azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted),
  1765  		autorest.ByClosing())
  1766  	result.Response = resp
  1767  	return
  1768  }
  1769  
  1770  func (client adl2PathClient) defaultRequest() *http.Request {
  1771  	r := &http.Request{}
  1772  	r.GetBody = func() (io.ReadCloser, error) {
  1773  		if r.Body == nil {
  1774  			return http.NoBody, nil
  1775  		} else if seeker, ok := r.Body.(io.ReadSeeker); ok {
  1776  			// internally goofys always uses seekable
  1777  			// readers, so we can rewind on
  1778  			// retry. autorest makes a copy of the buffer
  1779  			// and this avoids that waste
  1780  			_, err := seeker.Seek(0, 0)
  1781  			return &ReadSeekerCloser{seeker}, err
  1782  		} else {
  1783  			panic(fmt.Sprintf("Wrong type: %T", r.Body))
  1784  		}
  1785  	}
  1786  	return r
  1787  }
  1788  
  1789  type adl2PathList struct {
  1790  	autorest.Response `json:"-"`
  1791  	Paths             *[]adl2Path `json:"paths,omitempty"`
  1792  }
  1793  
  1794  type adl2Path struct {
  1795  	Name          *string    `json:"name,omitempty"`
  1796  	IsDirectory   adl2Bool   `json:"isDirectory,omitempty"`
  1797  	LastModified  *string    `json:"lastModified,omitempty"`
  1798  	ETag          *string    `json:"eTag,omitempty"`
  1799  	ContentLength *adl2Int64 `json:"contentLength,omitempty"`
  1800  	Owner         *string    `json:"owner,omitempty"`
  1801  	Group         *string    `json:"group,omitempty"`
  1802  	Permissions   *string    `json:"permissions,omitempty"`
  1803  }
  1804  
  1805  func (p adl2Path) isDirectory() bool {
  1806  	return p.IsDirectory.boolValue()
  1807  }
  1808  
  1809  func (p adl2Path) contentLength() int64 {
  1810  	if p.ContentLength == nil {
  1811  		return 0
  1812  	} else {
  1813  		return p.ContentLength.intValue()
  1814  	}
  1815  }
  1816  
  1817  type adl2Bool struct {
  1818  	bool
  1819  }
  1820  
  1821  func (b adl2Bool) boolValue() bool {
  1822  	return b.bool
  1823  }
  1824  
  1825  func (b *adl2Bool) UnmarshalJSON(buf []byte) error {
  1826  	v := string(buf)
  1827  	b.bool = v == "true" || v == "\"true\"" || v == "'true'"
  1828  	return nil
  1829  }
  1830  
  1831  type adl2Int64 struct {
  1832  	int64
  1833  }
  1834  
  1835  func (b *adl2Int64) intValue() int64 {
  1836  	return b.int64
  1837  }
  1838  
  1839  func (b *adl2Int64) UnmarshalJSON(buf []byte) error {
  1840  	if len(buf) == 0 {
  1841  		return fmt.Errorf("no input")
  1842  	}
  1843  	if buf[0] == '"' {
  1844  		var v string
  1845  		err := json.Unmarshal(buf, &v)
  1846  		if err != nil {
  1847  			return err
  1848  		}
  1849  		b.int64, err = strconv.ParseInt(v, 10, 64)
  1850  		return err
  1851  	} else {
  1852  		err := json.Unmarshal(buf, &b.int64)
  1853  		return err
  1854  	}
  1855  }