| 
									
										
										
										
											2021-04-19 03:41:13 +08:00
										 |  |  | // Copyright (c) 2015-2021 MinIO, Inc.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This file is part of MinIO Object Storage stack
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or
 | 
					
						
							|  |  |  | // (at your option) any later version.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU Affero General Public License for more details.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License
 | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2016-04-22 11:07:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-19 07:23:42 +08:00
										 |  |  | package cmd | 
					
						
							| 
									
										
										
										
											2016-04-08 10:01:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2024-03-01 14:49:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/minio/minio/internal/crypto" | 
					
						
							| 
									
										
										
										
											2024-04-02 07:42:09 +08:00
										 |  |  | 	"github.com/minio/minio/internal/grid" | 
					
						
							|  |  |  | 	xioutil "github.com/minio/minio/internal/ioutil" | 
					
						
							| 
									
										
										
										
											2016-04-08 10:01:15 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-20 06:54:46 +08:00
										 |  |  | //go:generate msgp -file=$GOFILE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-12 00:15:54 +08:00
										 |  |  | // DeleteOptions represents the disk level delete options available for the APIs
 | 
					
						
							|  |  |  | type DeleteOptions struct { | 
					
						
							| 
									
										
										
										
											2023-12-30 07:52:41 +08:00
										 |  |  | 	BaseOptions | 
					
						
							| 
									
										
											  
											
												perf: websocket grid connectivity for all internode communication (#18461)
This PR adds a WebSocket grid feature that allows servers to communicate via 
a single two-way connection.
There are two request types:
* Single requests, which are `[]byte => ([]byte, error)`. This is for efficient small
  roundtrips with small payloads.
* Streaming requests which are `[]byte, chan []byte => chan []byte (and error)`,
  which allows for different combinations of full two-way streams with an initial payload.
Only a single stream is created between two machines - and there is, as such, no
server/client relation since both sides can initiate and handle requests. Which server
initiates the request is decided deterministically on the server names.
Requests are made through a mux client and server, which handles message
passing, congestion, cancelation, timeouts, etc.
If a connection is lost, all requests are canceled, and the calling server will try
to reconnect. Registered handlers can operate directly on byte 
slices or use a higher-level generics abstraction.
There is no versioning of handlers/clients, and incompatible changes should
be handled by adding new handlers.
The request path can be changed to a new one for any protocol changes.
First, all servers create a "Manager." The manager must know its address 
as well as all remote addresses. This will manage all connections.
To get a connection to any remote, ask the manager to provide it given
the remote address using.
```
func (m *Manager) Connection(host string) *Connection
```
All serverside handlers must also be registered on the manager. This will
make sure that all incoming requests are served. The number of in-flight 
requests and responses must also be given for streaming requests.
The "Connection" returned manages the mux-clients. Requests issued
to the connection will be sent to the remote.
* `func (c *Connection) Request(ctx context.Context, h HandlerID, req []byte) ([]byte, error)`
   performs a single request and returns the result. Any deadline provided on the request is
   forwarded to the server, and canceling the context will make the function return at once.
* `func (c *Connection) NewStream(ctx context.Context, h HandlerID, payload []byte) (st *Stream, err error)`
   will initiate a remote call and send the initial payload.
```Go
// A Stream is a two-way stream.
// All responses *must* be read by the caller.
// If the call is canceled through the context,
//The appropriate error will be returned.
type Stream struct {
	// Responses from the remote server.
	// Channel will be closed after an error or when the remote closes.
	// All responses *must* be read by the caller until either an error is returned or the channel is closed.
	// Canceling the context will cause the context cancellation error to be returned.
	Responses <-chan Response
	// Requests sent to the server.
	// If the handler is defined with 0 incoming capacity this will be nil.
	// Channel *must* be closed to signal the end of the stream.
	// If the request context is canceled, the stream will no longer process requests.
	Requests chan<- []byte
}
type Response struct {
	Msg []byte
	Err error
}
```
There are generic versions of the server/client handlers that allow the use of type
safe implementations for data types that support msgpack marshal/unmarshal.
											
										 
											2023-11-21 09:09:35 +08:00
										 |  |  | 	Recursive bool `msg:"r"` | 
					
						
							| 
									
										
										
										
											2023-11-29 14:35:16 +08:00
										 |  |  | 	Immediate bool `msg:"i"` | 
					
						
							| 
									
										
										
										
											2023-12-30 07:52:41 +08:00
										 |  |  | 	UndoWrite bool `msg:"u"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // BaseOptions represents common options for all Storage API calls
 | 
					
						
							|  |  |  | type BaseOptions struct{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RenameOptions represents rename API options, currently its same as BaseOptions
 | 
					
						
							|  |  |  | type RenameOptions struct { | 
					
						
							|  |  |  | 	BaseOptions | 
					
						
							| 
									
										
										
										
											2022-07-12 00:15:54 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-26 04:45:46 +08:00
										 |  |  | // DiskInfoOptions options for requesting custom results.
 | 
					
						
							|  |  |  | type DiskInfoOptions struct { | 
					
						
							|  |  |  | 	DiskID  string `msg:"id"` | 
					
						
							|  |  |  | 	Metrics bool   `msg:"m"` | 
					
						
							|  |  |  | 	NoOp    bool   `msg:"np"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 02:10:54 +08:00
										 |  |  | // DiskInfo is an extended type which returns current
 | 
					
						
							|  |  |  | // disk usage per path.
 | 
					
						
							| 
									
										
										
										
											2021-01-04 03:27:57 +08:00
										 |  |  | // The above means that any added/deleted fields are incompatible.
 | 
					
						
							| 
									
										
										
										
											2022-08-27 03:52:29 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | // The above means that any added/deleted fields are incompatible.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //msgp:tuple DiskInfo
 | 
					
						
							| 
									
										
										
										
											2020-11-05 02:10:54 +08:00
										 |  |  | type DiskInfo struct { | 
					
						
							| 
									
										
										
										
											2020-12-27 14:58:06 +08:00
										 |  |  | 	Total      uint64 | 
					
						
							|  |  |  | 	Free       uint64 | 
					
						
							|  |  |  | 	Used       uint64 | 
					
						
							|  |  |  | 	UsedInodes uint64 | 
					
						
							| 
									
										
										
										
											2021-05-06 14:03:40 +08:00
										 |  |  | 	FreeInodes uint64 | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 	Major      uint32 | 
					
						
							|  |  |  | 	Minor      uint32 | 
					
						
							| 
									
										
										
										
											2023-09-12 05:48:54 +08:00
										 |  |  | 	NRRequests uint64 | 
					
						
							| 
									
										
										
										
											2020-12-27 14:58:06 +08:00
										 |  |  | 	FSType     string | 
					
						
							|  |  |  | 	RootDisk   bool | 
					
						
							|  |  |  | 	Healing    bool | 
					
						
							| 
									
										
										
										
											2022-08-16 22:13:49 +08:00
										 |  |  | 	Scanning   bool | 
					
						
							| 
									
										
										
										
											2020-12-27 14:58:06 +08:00
										 |  |  | 	Endpoint   string | 
					
						
							|  |  |  | 	MountPath  string | 
					
						
							|  |  |  | 	ID         string | 
					
						
							| 
									
										
										
										
											2023-08-01 06:20:48 +08:00
										 |  |  | 	Rotational bool | 
					
						
							| 
									
										
										
										
											2021-03-17 11:06:57 +08:00
										 |  |  | 	Metrics    DiskMetrics | 
					
						
							| 
									
										
										
										
											2020-12-27 14:58:06 +08:00
										 |  |  | 	Error      string // carries the error over the network
 | 
					
						
							| 
									
										
										
										
											2020-11-05 02:10:54 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-17 11:06:57 +08:00
										 |  |  | // DiskMetrics has the information about XL Storage APIs
 | 
					
						
							|  |  |  | // the number of calls of each API and the moving average of
 | 
					
						
							|  |  |  | // the duration of each API.
 | 
					
						
							|  |  |  | type DiskMetrics struct { | 
					
						
							| 
									
										
										
										
											2023-07-30 14:26:26 +08:00
										 |  |  | 	LastMinute              map[string]AccElem `json:"apiLatencies,omitempty"` | 
					
						
							|  |  |  | 	APICalls                map[string]uint64  `json:"apiCalls,omitempty"` | 
					
						
							| 
									
										
										
										
											2024-01-19 03:17:43 +08:00
										 |  |  | 	TotalWaiting            uint32             `json:"totalWaiting,omitempty"` | 
					
						
							| 
									
										
										
										
											2023-07-30 14:26:26 +08:00
										 |  |  | 	TotalErrorsAvailability uint64             `json:"totalErrsAvailability"` | 
					
						
							|  |  |  | 	TotalErrorsTimeout      uint64             `json:"totalErrsTimeout"` | 
					
						
							| 
									
										
										
										
											2023-12-30 07:52:41 +08:00
										 |  |  | 	TotalWrites             uint64             `json:"totalWrites"` | 
					
						
							|  |  |  | 	TotalDeletes            uint64             `json:"totalDeletes"` | 
					
						
							| 
									
										
										
										
											2021-03-17 11:06:57 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 02:10:54 +08:00
										 |  |  | // VolsInfo is a collection of volume(bucket) information
 | 
					
						
							|  |  |  | type VolsInfo []VolInfo | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-09 21:24:11 +08:00
										 |  |  | // VolInfo - represents volume stat information.
 | 
					
						
							| 
									
										
										
										
											2021-01-04 03:27:57 +08:00
										 |  |  | // The above means that any added/deleted fields are incompatible.
 | 
					
						
							| 
									
										
										
										
											2022-08-27 03:52:29 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | // The above means that any added/deleted fields are incompatible.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //msgp:tuple VolInfo
 | 
					
						
							| 
									
										
										
										
											2016-04-09 01:37:38 +08:00
										 |  |  | type VolInfo struct { | 
					
						
							| 
									
										
										
										
											2016-06-09 21:24:11 +08:00
										 |  |  | 	// Name of the volume.
 | 
					
						
							|  |  |  | 	Name string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Date and time when the volume was created.
 | 
					
						
							| 
									
										
										
										
											2016-04-09 01:37:38 +08:00
										 |  |  | 	Created time.Time | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-15 04:49:10 +08:00
										 |  |  | // FilesInfo represent a list of files, additionally
 | 
					
						
							|  |  |  | // indicates if the list is last.
 | 
					
						
							| 
									
										
										
										
											2022-08-27 03:52:29 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | //msgp:tuple FileInfo
 | 
					
						
							| 
									
										
										
										
											2019-05-15 04:49:10 +08:00
										 |  |  | type FilesInfo struct { | 
					
						
							|  |  |  | 	Files       []FileInfo | 
					
						
							|  |  |  | 	IsTruncated bool | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-11 01:07:49 +08:00
										 |  |  | // Size returns size of all versions for the object 'Name'
 | 
					
						
							|  |  |  | func (f FileInfoVersions) Size() (size int64) { | 
					
						
							|  |  |  | 	for _, v := range f.Versions { | 
					
						
							|  |  |  | 		size += v.Size | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return size | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // FileInfoVersions represent a list of versions for a given file.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | // The above means that any added/deleted fields are incompatible.
 | 
					
						
							| 
									
										
										
										
											2022-08-27 03:52:29 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | // The above means that any added/deleted fields are incompatible.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //msgp:tuple FileInfoVersions
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | type FileInfoVersions struct { | 
					
						
							|  |  |  | 	// Name of the volume.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	Volume string `msg:"v,omitempty"` | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Name of the file.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	Name string `msg:"n,omitempty"` | 
					
						
							| 
									
										
										
										
											2021-01-27 18:19:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	// Represents the latest mod time of the
 | 
					
						
							|  |  |  | 	// latest version.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	LatestModTime time.Time `msg:"lm"` | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-20 09:54:10 +08:00
										 |  |  | 	Versions     []FileInfo `msg:"vs"` | 
					
						
							|  |  |  | 	FreeVersions []FileInfo `msg:"fvs"` | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-12 02:22:03 +08:00
										 |  |  | // findVersionIndex will return the version index where the version
 | 
					
						
							|  |  |  | // was found. Returns -1 if not found.
 | 
					
						
							|  |  |  | func (f *FileInfoVersions) findVersionIndex(v string) int { | 
					
						
							|  |  |  | 	if f == nil || v == "" { | 
					
						
							|  |  |  | 		return -1 | 
					
						
							| 
									
										
										
										
											2020-10-29 00:18:35 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	for i, ver := range f.Versions { | 
					
						
							|  |  |  | 		if ver.VersionID == v { | 
					
						
							| 
									
										
										
										
											2021-02-12 02:22:03 +08:00
										 |  |  | 			return i | 
					
						
							| 
									
										
										
										
											2020-10-29 00:18:35 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-12 02:22:03 +08:00
										 |  |  | 	return -1 | 
					
						
							| 
									
										
										
										
											2020-10-29 00:18:35 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-21 03:49:05 +08:00
										 |  |  | // RawFileInfo - represents raw file stat information as byte array.
 | 
					
						
							|  |  |  | // The above means that any added/deleted fields are incompatible.
 | 
					
						
							|  |  |  | // Make sure to bump the internode version at storage-rest-common.go
 | 
					
						
							|  |  |  | type RawFileInfo struct { | 
					
						
							|  |  |  | 	// Content of entire xl.meta (may contain data depending on what was requested by the caller.
 | 
					
						
							| 
									
										
											  
											
												perf: websocket grid connectivity for all internode communication (#18461)
This PR adds a WebSocket grid feature that allows servers to communicate via 
a single two-way connection.
There are two request types:
* Single requests, which are `[]byte => ([]byte, error)`. This is for efficient small
  roundtrips with small payloads.
* Streaming requests which are `[]byte, chan []byte => chan []byte (and error)`,
  which allows for different combinations of full two-way streams with an initial payload.
Only a single stream is created between two machines - and there is, as such, no
server/client relation since both sides can initiate and handle requests. Which server
initiates the request is decided deterministically on the server names.
Requests are made through a mux client and server, which handles message
passing, congestion, cancelation, timeouts, etc.
If a connection is lost, all requests are canceled, and the calling server will try
to reconnect. Registered handlers can operate directly on byte 
slices or use a higher-level generics abstraction.
There is no versioning of handlers/clients, and incompatible changes should
be handled by adding new handlers.
The request path can be changed to a new one for any protocol changes.
First, all servers create a "Manager." The manager must know its address 
as well as all remote addresses. This will manage all connections.
To get a connection to any remote, ask the manager to provide it given
the remote address using.
```
func (m *Manager) Connection(host string) *Connection
```
All serverside handlers must also be registered on the manager. This will
make sure that all incoming requests are served. The number of in-flight 
requests and responses must also be given for streaming requests.
The "Connection" returned manages the mux-clients. Requests issued
to the connection will be sent to the remote.
* `func (c *Connection) Request(ctx context.Context, h HandlerID, req []byte) ([]byte, error)`
   performs a single request and returns the result. Any deadline provided on the request is
   forwarded to the server, and canceling the context will make the function return at once.
* `func (c *Connection) NewStream(ctx context.Context, h HandlerID, payload []byte) (st *Stream, err error)`
   will initiate a remote call and send the initial payload.
```Go
// A Stream is a two-way stream.
// All responses *must* be read by the caller.
// If the call is canceled through the context,
//The appropriate error will be returned.
type Stream struct {
	// Responses from the remote server.
	// Channel will be closed after an error or when the remote closes.
	// All responses *must* be read by the caller until either an error is returned or the channel is closed.
	// Canceling the context will cause the context cancellation error to be returned.
	Responses <-chan Response
	// Requests sent to the server.
	// If the handler is defined with 0 incoming capacity this will be nil.
	// Channel *must* be closed to signal the end of the stream.
	// If the request context is canceled, the stream will no longer process requests.
	Requests chan<- []byte
}
type Response struct {
	Msg []byte
	Err error
}
```
There are generic versions of the server/client handlers that allow the use of type
safe implementations for data types that support msgpack marshal/unmarshal.
											
										 
											2023-11-21 09:09:35 +08:00
										 |  |  | 	Buf []byte `msg:"b,allownil"` | 
					
						
							| 
									
										
										
										
											2022-04-21 03:49:05 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-09 21:24:11 +08:00
										 |  |  | // FileInfo - represents file stat information.
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:07:52 +08:00
										 |  |  | // The above means that any added/deleted fields are incompatible.
 | 
					
						
							| 
									
										
										
										
											2022-04-21 03:49:05 +08:00
										 |  |  | // Make sure to bump the internode version at storage-rest-common.go
 | 
					
						
							| 
									
										
										
										
											2016-04-08 10:01:15 +08:00
										 |  |  | type FileInfo struct { | 
					
						
							| 
									
										
										
										
											2016-06-09 21:24:11 +08:00
										 |  |  | 	// Name of the volume.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	Volume string `msg:"v,omitempty"` | 
					
						
							| 
									
										
										
										
											2016-06-09 21:24:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Name of the file.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	Name string `msg:"n,omitempty"` | 
					
						
							| 
									
										
										
										
											2016-06-09 21:24:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	// Version of the file.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	VersionID string `msg:"vid,omitempty"` | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Indicates if the version is the latest
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	IsLatest bool `msg:"is"` | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Deleted is set when this FileInfo represents
 | 
					
						
							|  |  |  | 	// a deleted marker for a versioned bucket.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	Deleted bool `msg:"del"` | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 04:12:09 +08:00
										 |  |  | 	// TransitionStatus is set to Pending/Complete for transitioned
 | 
					
						
							|  |  |  | 	// entries based on state of transition
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	TransitionStatus string `msg:"ts"` | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | 	// TransitionedObjName is the object name on the remote tier corresponding
 | 
					
						
							|  |  |  | 	// to object (version) on the source tier.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	TransitionedObjName string `msg:"to"` | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | 	// TransitionTier is the storage class label assigned to remote tier.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	TransitionTier string `msg:"tt"` | 
					
						
							| 
									
										
										
										
											2021-06-04 05:26:51 +08:00
										 |  |  | 	// TransitionVersionID stores a version ID of the object associate
 | 
					
						
							|  |  |  | 	// with the remote tier.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	TransitionVersionID string `msg:"tv"` | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | 	// ExpireRestored indicates that the restored object is to be expired.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	ExpireRestored bool `msg:"exp"` | 
					
						
							| 
									
										
										
										
											2020-11-13 04:12:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	// DataDir of the file
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	DataDir string `msg:"dd"` | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-18 08:41:29 +08:00
										 |  |  | 	// Indicates if this object is still in V1 format.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	XLV1 bool `msg:"v1"` | 
					
						
							| 
									
										
										
										
											2020-07-18 08:41:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	// Date and time when the file was last modified, if Deleted
 | 
					
						
							|  |  |  | 	// is 'true' this value represents when while was deleted.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	ModTime time.Time `msg:"mt"` | 
					
						
							| 
									
										
										
										
											2016-06-09 21:24:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Total file size.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	Size int64 `msg:"sz"` | 
					
						
							| 
									
										
										
										
											2016-06-09 21:24:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// File mode bits.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	Mode uint32 `msg:"m"` | 
					
						
							| 
									
										
										
										
											2019-05-15 04:49:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-27 18:59:41 +08:00
										 |  |  | 	// WrittenByVersion is the unix time stamp of the MinIO
 | 
					
						
							|  |  |  | 	// version that created this version of the object.
 | 
					
						
							|  |  |  | 	WrittenByVersion uint64 `msg:"wv"` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-15 04:49:10 +08:00
										 |  |  | 	// File metadata
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	Metadata map[string]string `msg:"meta"` | 
					
						
							| 
									
										
										
										
											2019-05-15 04:49:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// All the parts per object.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	Parts []ObjectPartInfo `msg:"parts"` | 
					
						
							| 
									
										
										
										
											2019-05-15 04:49:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	// Erasure info for all objects.
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	Erasure ErasureInfo `msg:"ei"` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MarkDeleted      bool             `msg:"md"` // mark this version as deleted
 | 
					
						
							|  |  |  | 	ReplicationState ReplicationState `msg:"rs"` // Internal replication state to be passed back in ObjectInfo
 | 
					
						
							| 
									
										
										
										
											2020-11-20 10:43:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	Data []byte `msg:"d,allownil"` // optionally carries object data
 | 
					
						
							| 
									
										
										
										
											2021-01-08 11:27:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	NumVersions      int       `msg:"nv"` | 
					
						
							|  |  |  | 	SuccessorModTime time.Time `msg:"smt"` | 
					
						
							| 
									
										
										
										
											2021-02-02 01:52:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	Fresh bool `msg:"fr"` // indicates this is a first time call to write FileInfo.
 | 
					
						
							| 
									
										
										
										
											2021-08-11 02:12:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-02 01:50:07 +08:00
										 |  |  | 	// Position of this version or object in a multi-object delete call,
 | 
					
						
							|  |  |  | 	// no other caller must set this value other than multi-object delete call.
 | 
					
						
							|  |  |  | 	// usage in other calls in undefined please avoid.
 | 
					
						
							|  |  |  | 	Idx int `msg:"i"` | 
					
						
							| 
									
										
										
										
											2021-12-22 02:08:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-30 07:57:16 +08:00
										 |  |  | 	// Combined checksum when object was uploaded.
 | 
					
						
							| 
									
										
										
										
											2022-08-31 23:13:23 +08:00
										 |  |  | 	Checksum []byte `msg:"cs,allownil"` | 
					
						
							| 
									
										
										
										
											2023-08-28 00:57:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Versioned - indicates if this file is versioned or not.
 | 
					
						
							|  |  |  | 	Versioned bool `msg:"vs"` | 
					
						
							| 
									
										
										
										
											2021-12-22 02:08:26 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-23 05:46:17 +08:00
										 |  |  | // ShallowCopy - copies minimal information for READ MRF checks.
 | 
					
						
							|  |  |  | func (fi FileInfo) ShallowCopy() (n FileInfo) { | 
					
						
							|  |  |  | 	n.Volume = fi.Volume | 
					
						
							|  |  |  | 	n.Name = fi.Name | 
					
						
							|  |  |  | 	n.VersionID = fi.VersionID | 
					
						
							|  |  |  | 	n.Deleted = fi.Deleted | 
					
						
							|  |  |  | 	n.Erasure = fi.Erasure | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-16 03:43:49 +08:00
										 |  |  | // WriteQuorum returns expected write quorum for this FileInfo
 | 
					
						
							|  |  |  | func (fi FileInfo) WriteQuorum(dquorum int) int { | 
					
						
							|  |  |  | 	if fi.Deleted { | 
					
						
							|  |  |  | 		return dquorum | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	quorum := fi.Erasure.DataBlocks | 
					
						
							|  |  |  | 	if fi.Erasure.DataBlocks == fi.Erasure.ParityBlocks { | 
					
						
							|  |  |  | 		quorum++ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return quorum | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ReadQuorum returns expected read quorum for this FileInfo
 | 
					
						
							|  |  |  | func (fi FileInfo) ReadQuorum(dquorum int) int { | 
					
						
							|  |  |  | 	if fi.Deleted { | 
					
						
							|  |  |  | 		return dquorum | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fi.Erasure.DataBlocks | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-22 02:08:26 +08:00
										 |  |  | // Equals checks if fi(FileInfo) matches ofi(FileInfo)
 | 
					
						
							|  |  |  | func (fi FileInfo) Equals(ofi FileInfo) (ok bool) { | 
					
						
							| 
									
										
										
										
											2024-03-01 14:49:01 +08:00
										 |  |  | 	typ1, ok1 := crypto.IsEncrypted(fi.Metadata) | 
					
						
							|  |  |  | 	typ2, ok2 := crypto.IsEncrypted(ofi.Metadata) | 
					
						
							|  |  |  | 	if ok1 != ok2 { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if typ1 != typ2 { | 
					
						
							| 
									
										
										
										
											2021-12-22 02:08:26 +08:00
										 |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-03-01 14:49:01 +08:00
										 |  |  | 	if fi.IsCompressed() != ofi.IsCompressed() { | 
					
						
							| 
									
										
										
										
											2021-12-22 02:08:26 +08:00
										 |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !fi.TransitionInfoEquals(ofi) { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-06-19 09:20:15 +08:00
										 |  |  | 	if !fi.ModTime.Equal(ofi.ModTime) { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fi.Erasure.Equal(ofi.Erasure) | 
					
						
							| 
									
										
										
										
											2020-11-20 10:43:58 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-22 02:41:30 +08:00
										 |  |  | // GetDataDir returns an expected dataDir given FileInfo
 | 
					
						
							| 
									
										
										
										
											2022-08-27 03:52:29 +08:00
										 |  |  | //   - deleteMarker returns "delete-marker"
 | 
					
						
							|  |  |  | //   - returns "legacy" if FileInfo is XLV1 and DataDir is
 | 
					
						
							|  |  |  | //     empty, returns DataDir otherwise
 | 
					
						
							|  |  |  | //   - returns "dataDir"
 | 
					
						
							| 
									
										
										
										
											2021-11-22 02:41:30 +08:00
										 |  |  | func (fi FileInfo) GetDataDir() string { | 
					
						
							|  |  |  | 	if fi.Deleted { | 
					
						
							|  |  |  | 		return "delete-marker" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if fi.XLV1 && fi.DataDir == "" { | 
					
						
							|  |  |  | 		return "legacy" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fi.DataDir | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-01 14:49:01 +08:00
										 |  |  | // IsCompressed returns true if the object is marked as compressed.
 | 
					
						
							|  |  |  | func (fi FileInfo) IsCompressed() bool { | 
					
						
							|  |  |  | 	_, ok := fi.Metadata[ReservedMetadataPrefix+"compression"] | 
					
						
							|  |  |  | 	return ok | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-17 00:38:27 +08:00
										 |  |  | // InlineData returns true if object contents are inlined alongside its metadata.
 | 
					
						
							|  |  |  | func (fi FileInfo) InlineData() bool { | 
					
						
							|  |  |  | 	_, ok := fi.Metadata[ReservedMetadataPrefixLower+"inline-data"] | 
					
						
							| 
									
										
										
										
											2023-11-09 12:00:02 +08:00
										 |  |  | 	// Earlier MinIO versions didn't reset "x-minio-internal-inline-data"
 | 
					
						
							|  |  |  | 	// from fi.Metadata when the object was tiered. So, tiered objects
 | 
					
						
							|  |  |  | 	// would return true for InlineData() in these versions even though the
 | 
					
						
							|  |  |  | 	// object isn't inlined in xl.meta
 | 
					
						
							|  |  |  | 	return ok && !fi.IsRemote() | 
					
						
							| 
									
										
										
										
											2021-07-17 00:38:27 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SetInlineData marks object (version) as inline.
 | 
					
						
							| 
									
										
										
										
											2021-08-13 23:25:54 +08:00
										 |  |  | func (fi *FileInfo) SetInlineData() { | 
					
						
							|  |  |  | 	if fi.Metadata == nil { | 
					
						
							|  |  |  | 		fi.Metadata = make(map[string]string, 1) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-07-17 00:38:27 +08:00
										 |  |  | 	fi.Metadata[ReservedMetadataPrefixLower+"inline-data"] = "true" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 10:43:58 +08:00
										 |  |  | // VersionPurgeStatusKey denotes purge status in metadata
 | 
					
						
							| 
									
										
										
										
											2022-01-11 01:07:49 +08:00
										 |  |  | const ( | 
					
						
							|  |  |  | 	VersionPurgeStatusKey = ReservedMetadataPrefixLower + "purgestatus" | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2020-11-20 10:43:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | // newFileInfo - initializes new FileInfo, allocates a fresh erasure info.
 | 
					
						
							|  |  |  | func newFileInfo(object string, dataBlocks, parityBlocks int) (fi FileInfo) { | 
					
						
							|  |  |  | 	fi.Erasure = ErasureInfo{ | 
					
						
							|  |  |  | 		Algorithm:    erasureAlgorithm, | 
					
						
							|  |  |  | 		DataBlocks:   dataBlocks, | 
					
						
							|  |  |  | 		ParityBlocks: parityBlocks, | 
					
						
							| 
									
										
											  
											
												[feat]: change erasure coding default block size from 10MiB to 1MiB (#11721)
major performance improvements in range GETs to avoid large
read amplification when ranges are tiny and random
```
-------------------
Operation: GET
Operations: 142014 -> 339421
Duration: 4m50s -> 4m56s
* Average: +139.41% (+1177.3 MiB/s) throughput, +139.11% (+658.4) obj/s
* Fastest: +125.24% (+1207.4 MiB/s) throughput, +132.32% (+612.9) obj/s
* 50% Median: +139.06% (+1175.7 MiB/s) throughput, +133.46% (+660.9) obj/s
* Slowest: +203.40% (+1267.9 MiB/s) throughput, +198.59% (+753.5) obj/s
```
TTFB from 10MiB BlockSize
```
* First Access TTFB: Avg: 81ms, Median: 61ms, Best: 20ms, Worst: 2.056s
```
TTFB from 1MiB BlockSize
```
* First Access TTFB: Avg: 22ms, Median: 21ms, Best: 8ms, Worst: 91ms
```
Full object reads however do see a slight change which won't be
noticeable in real world, so not doing any comparisons
TTFB still had improvements with full object reads with 1MiB
```
* First Access TTFB: Avg: 68ms, Median: 35ms, Best: 11ms, Worst: 1.16s
```
v/s
TTFB with 10MiB
```
* First Access TTFB: Avg: 388ms, Median: 98ms, Best: 20ms, Worst: 4.156s
```
This change should affect all new uploads, previous uploads should
continue to work with business as usual. But dramatic improvements can
be seen with these changes.
											
										 
											2021-03-07 06:09:34 +08:00
										 |  |  | 		BlockSize:    blockSizeV2, | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 		Distribution: hashOrder(object, dataBlocks+parityBlocks), | 
					
						
							| 
									
										
										
										
											2020-02-25 23:52:28 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	return fi | 
					
						
							| 
									
										
										
										
											2020-02-25 23:52:28 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-07-19 23:35:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // ReadMultipleReq contains information of multiple files to read from disk.
 | 
					
						
							|  |  |  | type ReadMultipleReq struct { | 
					
						
							|  |  |  | 	Bucket       string   // Bucket. Can be empty if multiple buckets.
 | 
					
						
							|  |  |  | 	Prefix       string   // Shared prefix of all files. Can be empty. Will be joined to filename without modification.
 | 
					
						
							|  |  |  | 	Files        []string // Individual files to read.
 | 
					
						
							|  |  |  | 	MaxSize      int64    // Return error if size is exceed.
 | 
					
						
							|  |  |  | 	MetadataOnly bool     // Read as XL meta and truncate data.
 | 
					
						
							|  |  |  | 	AbortOn404   bool     // Stop reading after first file not found.
 | 
					
						
							| 
									
										
										
										
											2022-07-22 07:47:58 +08:00
										 |  |  | 	MaxResults   int      // Stop after this many successful results. <= 0 means all.
 | 
					
						
							| 
									
										
										
										
											2022-07-19 23:35:29 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ReadMultipleResp contains a single response from a ReadMultipleReq.
 | 
					
						
							|  |  |  | type ReadMultipleResp struct { | 
					
						
							|  |  |  | 	Bucket  string    // Bucket as given by request.
 | 
					
						
							|  |  |  | 	Prefix  string    // Prefix as given by request.
 | 
					
						
							|  |  |  | 	File    string    // File name as given in request.
 | 
					
						
							|  |  |  | 	Exists  bool      // Returns whether the file existed on disk.
 | 
					
						
							|  |  |  | 	Error   string    // Returns any error when reading.
 | 
					
						
							|  |  |  | 	Data    []byte    // Contains all data of file.
 | 
					
						
							|  |  |  | 	Modtime time.Time // Modtime of file on disk.
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
											  
											
												perf: websocket grid connectivity for all internode communication (#18461)
This PR adds a WebSocket grid feature that allows servers to communicate via 
a single two-way connection.
There are two request types:
* Single requests, which are `[]byte => ([]byte, error)`. This is for efficient small
  roundtrips with small payloads.
* Streaming requests which are `[]byte, chan []byte => chan []byte (and error)`,
  which allows for different combinations of full two-way streams with an initial payload.
Only a single stream is created between two machines - and there is, as such, no
server/client relation since both sides can initiate and handle requests. Which server
initiates the request is decided deterministically on the server names.
Requests are made through a mux client and server, which handles message
passing, congestion, cancelation, timeouts, etc.
If a connection is lost, all requests are canceled, and the calling server will try
to reconnect. Registered handlers can operate directly on byte 
slices or use a higher-level generics abstraction.
There is no versioning of handlers/clients, and incompatible changes should
be handled by adding new handlers.
The request path can be changed to a new one for any protocol changes.
First, all servers create a "Manager." The manager must know its address 
as well as all remote addresses. This will manage all connections.
To get a connection to any remote, ask the manager to provide it given
the remote address using.
```
func (m *Manager) Connection(host string) *Connection
```
All serverside handlers must also be registered on the manager. This will
make sure that all incoming requests are served. The number of in-flight 
requests and responses must also be given for streaming requests.
The "Connection" returned manages the mux-clients. Requests issued
to the connection will be sent to the remote.
* `func (c *Connection) Request(ctx context.Context, h HandlerID, req []byte) ([]byte, error)`
   performs a single request and returns the result. Any deadline provided on the request is
   forwarded to the server, and canceling the context will make the function return at once.
* `func (c *Connection) NewStream(ctx context.Context, h HandlerID, payload []byte) (st *Stream, err error)`
   will initiate a remote call and send the initial payload.
```Go
// A Stream is a two-way stream.
// All responses *must* be read by the caller.
// If the call is canceled through the context,
//The appropriate error will be returned.
type Stream struct {
	// Responses from the remote server.
	// Channel will be closed after an error or when the remote closes.
	// All responses *must* be read by the caller until either an error is returned or the channel is closed.
	// Canceling the context will cause the context cancellation error to be returned.
	Responses <-chan Response
	// Requests sent to the server.
	// If the handler is defined with 0 incoming capacity this will be nil.
	// Channel *must* be closed to signal the end of the stream.
	// If the request context is canceled, the stream will no longer process requests.
	Requests chan<- []byte
}
type Response struct {
	Msg []byte
	Err error
}
```
There are generic versions of the server/client handlers that allow the use of type
safe implementations for data types that support msgpack marshal/unmarshal.
											
										 
											2023-11-21 09:09:35 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // DeleteVersionHandlerParams are parameters for DeleteVersionHandler
 | 
					
						
							|  |  |  | type DeleteVersionHandlerParams struct { | 
					
						
							| 
									
										
										
										
											2023-12-30 07:52:41 +08:00
										 |  |  | 	DiskID         string        `msg:"id"` | 
					
						
							|  |  |  | 	Volume         string        `msg:"v"` | 
					
						
							|  |  |  | 	FilePath       string        `msg:"fp"` | 
					
						
							|  |  |  | 	ForceDelMarker bool          `msg:"fdm"` | 
					
						
							|  |  |  | 	Opts           DeleteOptions `msg:"do"` | 
					
						
							|  |  |  | 	FI             FileInfo      `msg:"fi"` | 
					
						
							| 
									
										
											  
											
												perf: websocket grid connectivity for all internode communication (#18461)
This PR adds a WebSocket grid feature that allows servers to communicate via 
a single two-way connection.
There are two request types:
* Single requests, which are `[]byte => ([]byte, error)`. This is for efficient small
  roundtrips with small payloads.
* Streaming requests which are `[]byte, chan []byte => chan []byte (and error)`,
  which allows for different combinations of full two-way streams with an initial payload.
Only a single stream is created between two machines - and there is, as such, no
server/client relation since both sides can initiate and handle requests. Which server
initiates the request is decided deterministically on the server names.
Requests are made through a mux client and server, which handles message
passing, congestion, cancelation, timeouts, etc.
If a connection is lost, all requests are canceled, and the calling server will try
to reconnect. Registered handlers can operate directly on byte 
slices or use a higher-level generics abstraction.
There is no versioning of handlers/clients, and incompatible changes should
be handled by adding new handlers.
The request path can be changed to a new one for any protocol changes.
First, all servers create a "Manager." The manager must know its address 
as well as all remote addresses. This will manage all connections.
To get a connection to any remote, ask the manager to provide it given
the remote address using.
```
func (m *Manager) Connection(host string) *Connection
```
All serverside handlers must also be registered on the manager. This will
make sure that all incoming requests are served. The number of in-flight 
requests and responses must also be given for streaming requests.
The "Connection" returned manages the mux-clients. Requests issued
to the connection will be sent to the remote.
* `func (c *Connection) Request(ctx context.Context, h HandlerID, req []byte) ([]byte, error)`
   performs a single request and returns the result. Any deadline provided on the request is
   forwarded to the server, and canceling the context will make the function return at once.
* `func (c *Connection) NewStream(ctx context.Context, h HandlerID, payload []byte) (st *Stream, err error)`
   will initiate a remote call and send the initial payload.
```Go
// A Stream is a two-way stream.
// All responses *must* be read by the caller.
// If the call is canceled through the context,
//The appropriate error will be returned.
type Stream struct {
	// Responses from the remote server.
	// Channel will be closed after an error or when the remote closes.
	// All responses *must* be read by the caller until either an error is returned or the channel is closed.
	// Canceling the context will cause the context cancellation error to be returned.
	Responses <-chan Response
	// Requests sent to the server.
	// If the handler is defined with 0 incoming capacity this will be nil.
	// Channel *must* be closed to signal the end of the stream.
	// If the request context is canceled, the stream will no longer process requests.
	Requests chan<- []byte
}
type Response struct {
	Msg []byte
	Err error
}
```
There are generic versions of the server/client handlers that allow the use of type
safe implementations for data types that support msgpack marshal/unmarshal.
											
										 
											2023-11-21 09:09:35 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MetadataHandlerParams is request info for UpdateMetadataHandle and WriteMetadataHandler.
 | 
					
						
							|  |  |  | type MetadataHandlerParams struct { | 
					
						
							|  |  |  | 	DiskID     string             `msg:"id"` | 
					
						
							|  |  |  | 	Volume     string             `msg:"v"` | 
					
						
							| 
									
										
										
										
											2024-01-31 04:43:25 +08:00
										 |  |  | 	OrigVolume string             `msg:"ov"` | 
					
						
							| 
									
										
											  
											
												perf: websocket grid connectivity for all internode communication (#18461)
This PR adds a WebSocket grid feature that allows servers to communicate via 
a single two-way connection.
There are two request types:
* Single requests, which are `[]byte => ([]byte, error)`. This is for efficient small
  roundtrips with small payloads.
* Streaming requests which are `[]byte, chan []byte => chan []byte (and error)`,
  which allows for different combinations of full two-way streams with an initial payload.
Only a single stream is created between two machines - and there is, as such, no
server/client relation since both sides can initiate and handle requests. Which server
initiates the request is decided deterministically on the server names.
Requests are made through a mux client and server, which handles message
passing, congestion, cancelation, timeouts, etc.
If a connection is lost, all requests are canceled, and the calling server will try
to reconnect. Registered handlers can operate directly on byte 
slices or use a higher-level generics abstraction.
There is no versioning of handlers/clients, and incompatible changes should
be handled by adding new handlers.
The request path can be changed to a new one for any protocol changes.
First, all servers create a "Manager." The manager must know its address 
as well as all remote addresses. This will manage all connections.
To get a connection to any remote, ask the manager to provide it given
the remote address using.
```
func (m *Manager) Connection(host string) *Connection
```
All serverside handlers must also be registered on the manager. This will
make sure that all incoming requests are served. The number of in-flight 
requests and responses must also be given for streaming requests.
The "Connection" returned manages the mux-clients. Requests issued
to the connection will be sent to the remote.
* `func (c *Connection) Request(ctx context.Context, h HandlerID, req []byte) ([]byte, error)`
   performs a single request and returns the result. Any deadline provided on the request is
   forwarded to the server, and canceling the context will make the function return at once.
* `func (c *Connection) NewStream(ctx context.Context, h HandlerID, payload []byte) (st *Stream, err error)`
   will initiate a remote call and send the initial payload.
```Go
// A Stream is a two-way stream.
// All responses *must* be read by the caller.
// If the call is canceled through the context,
//The appropriate error will be returned.
type Stream struct {
	// Responses from the remote server.
	// Channel will be closed after an error or when the remote closes.
	// All responses *must* be read by the caller until either an error is returned or the channel is closed.
	// Canceling the context will cause the context cancellation error to be returned.
	Responses <-chan Response
	// Requests sent to the server.
	// If the handler is defined with 0 incoming capacity this will be nil.
	// Channel *must* be closed to signal the end of the stream.
	// If the request context is canceled, the stream will no longer process requests.
	Requests chan<- []byte
}
type Response struct {
	Msg []byte
	Err error
}
```
There are generic versions of the server/client handlers that allow the use of type
safe implementations for data types that support msgpack marshal/unmarshal.
											
										 
											2023-11-21 09:09:35 +08:00
										 |  |  | 	FilePath   string             `msg:"fp"` | 
					
						
							|  |  |  | 	UpdateOpts UpdateMetadataOpts `msg:"uo"` | 
					
						
							|  |  |  | 	FI         FileInfo           `msg:"fi"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // UpdateMetadataOpts provides an optional input to indicate if xl.meta updates need to be fully synced to disk.
 | 
					
						
							|  |  |  | type UpdateMetadataOpts struct { | 
					
						
							|  |  |  | 	NoPersistence bool `msg:"np"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // CheckPartsHandlerParams are parameters for CheckPartsHandler
 | 
					
						
							|  |  |  | type CheckPartsHandlerParams struct { | 
					
						
							|  |  |  | 	DiskID   string   `msg:"id"` | 
					
						
							|  |  |  | 	Volume   string   `msg:"v"` | 
					
						
							|  |  |  | 	FilePath string   `msg:"fp"` | 
					
						
							|  |  |  | 	FI       FileInfo `msg:"fi"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // DeleteFileHandlerParams are parameters for DeleteFileHandler
 | 
					
						
							|  |  |  | type DeleteFileHandlerParams struct { | 
					
						
							|  |  |  | 	DiskID   string        `msg:"id"` | 
					
						
							|  |  |  | 	Volume   string        `msg:"v"` | 
					
						
							|  |  |  | 	FilePath string        `msg:"fp"` | 
					
						
							|  |  |  | 	Opts     DeleteOptions `msg:"do"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RenameDataHandlerParams are parameters for RenameDataHandler.
 | 
					
						
							|  |  |  | type RenameDataHandlerParams struct { | 
					
						
							| 
									
										
										
										
											2023-12-30 07:52:41 +08:00
										 |  |  | 	DiskID    string        `msg:"id"` | 
					
						
							|  |  |  | 	SrcVolume string        `msg:"sv"` | 
					
						
							|  |  |  | 	SrcPath   string        `msg:"sp"` | 
					
						
							|  |  |  | 	DstVolume string        `msg:"dv"` | 
					
						
							|  |  |  | 	DstPath   string        `msg:"dp"` | 
					
						
							|  |  |  | 	FI        FileInfo      `msg:"fi"` | 
					
						
							|  |  |  | 	Opts      RenameOptions `msg:"ro"` | 
					
						
							| 
									
										
											  
											
												perf: websocket grid connectivity for all internode communication (#18461)
This PR adds a WebSocket grid feature that allows servers to communicate via 
a single two-way connection.
There are two request types:
* Single requests, which are `[]byte => ([]byte, error)`. This is for efficient small
  roundtrips with small payloads.
* Streaming requests which are `[]byte, chan []byte => chan []byte (and error)`,
  which allows for different combinations of full two-way streams with an initial payload.
Only a single stream is created between two machines - and there is, as such, no
server/client relation since both sides can initiate and handle requests. Which server
initiates the request is decided deterministically on the server names.
Requests are made through a mux client and server, which handles message
passing, congestion, cancelation, timeouts, etc.
If a connection is lost, all requests are canceled, and the calling server will try
to reconnect. Registered handlers can operate directly on byte 
slices or use a higher-level generics abstraction.
There is no versioning of handlers/clients, and incompatible changes should
be handled by adding new handlers.
The request path can be changed to a new one for any protocol changes.
First, all servers create a "Manager." The manager must know its address 
as well as all remote addresses. This will manage all connections.
To get a connection to any remote, ask the manager to provide it given
the remote address using.
```
func (m *Manager) Connection(host string) *Connection
```
All serverside handlers must also be registered on the manager. This will
make sure that all incoming requests are served. The number of in-flight 
requests and responses must also be given for streaming requests.
The "Connection" returned manages the mux-clients. Requests issued
to the connection will be sent to the remote.
* `func (c *Connection) Request(ctx context.Context, h HandlerID, req []byte) ([]byte, error)`
   performs a single request and returns the result. Any deadline provided on the request is
   forwarded to the server, and canceling the context will make the function return at once.
* `func (c *Connection) NewStream(ctx context.Context, h HandlerID, payload []byte) (st *Stream, err error)`
   will initiate a remote call and send the initial payload.
```Go
// A Stream is a two-way stream.
// All responses *must* be read by the caller.
// If the call is canceled through the context,
//The appropriate error will be returned.
type Stream struct {
	// Responses from the remote server.
	// Channel will be closed after an error or when the remote closes.
	// All responses *must* be read by the caller until either an error is returned or the channel is closed.
	// Canceling the context will cause the context cancellation error to be returned.
	Responses <-chan Response
	// Requests sent to the server.
	// If the handler is defined with 0 incoming capacity this will be nil.
	// Channel *must* be closed to signal the end of the stream.
	// If the request context is canceled, the stream will no longer process requests.
	Requests chan<- []byte
}
type Response struct {
	Msg []byte
	Err error
}
```
There are generic versions of the server/client handlers that allow the use of type
safe implementations for data types that support msgpack marshal/unmarshal.
											
										 
											2023-11-21 09:09:35 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-02 07:42:09 +08:00
										 |  |  | // RenameDataInlineHandlerParams are parameters for RenameDataHandler with a buffer for inline data.
 | 
					
						
							|  |  |  | type RenameDataInlineHandlerParams struct { | 
					
						
							|  |  |  | 	RenameDataHandlerParams `msg:"p"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func newRenameDataInlineHandlerParams() *RenameDataInlineHandlerParams { | 
					
						
							|  |  |  | 	buf := grid.GetByteBufferCap(32 + 16<<10) | 
					
						
							|  |  |  | 	return &RenameDataInlineHandlerParams{RenameDataHandlerParams{FI: FileInfo{Data: buf[:0]}}} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Recycle will reuse the memory allocated for the FileInfo data.
 | 
					
						
							|  |  |  | func (r *RenameDataInlineHandlerParams) Recycle() { | 
					
						
							|  |  |  | 	if r == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if cap(r.FI.Data) >= xioutil.BlockSizeSmall { | 
					
						
							|  |  |  | 		grid.PutByteBuffer(r.FI.Data) | 
					
						
							|  |  |  | 		r.FI.Data = nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-26 04:45:46 +08:00
										 |  |  | // RenameFileHandlerParams are parameters for RenameFileHandler.
 | 
					
						
							|  |  |  | type RenameFileHandlerParams struct { | 
					
						
							|  |  |  | 	DiskID      string `msg:"id"` | 
					
						
							|  |  |  | 	SrcVolume   string `msg:"sv"` | 
					
						
							|  |  |  | 	SrcFilePath string `msg:"sp"` | 
					
						
							|  |  |  | 	DstVolume   string `msg:"dv"` | 
					
						
							|  |  |  | 	DstFilePath string `msg:"dp"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ReadAllHandlerParams are parameters for ReadAllHandler.
 | 
					
						
							|  |  |  | type ReadAllHandlerParams struct { | 
					
						
							|  |  |  | 	DiskID   string `msg:"id"` | 
					
						
							|  |  |  | 	Volume   string `msg:"v"` | 
					
						
							|  |  |  | 	FilePath string `msg:"fp"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-29 01:54:52 +08:00
										 |  |  | // WriteAllHandlerParams are parameters for WriteAllHandler.
 | 
					
						
							|  |  |  | type WriteAllHandlerParams struct { | 
					
						
							|  |  |  | 	DiskID   string `msg:"id"` | 
					
						
							|  |  |  | 	Volume   string `msg:"v"` | 
					
						
							|  |  |  | 	FilePath string `msg:"fp"` | 
					
						
							|  |  |  | 	Buf      []byte `msg:"b"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												perf: websocket grid connectivity for all internode communication (#18461)
This PR adds a WebSocket grid feature that allows servers to communicate via 
a single two-way connection.
There are two request types:
* Single requests, which are `[]byte => ([]byte, error)`. This is for efficient small
  roundtrips with small payloads.
* Streaming requests which are `[]byte, chan []byte => chan []byte (and error)`,
  which allows for different combinations of full two-way streams with an initial payload.
Only a single stream is created between two machines - and there is, as such, no
server/client relation since both sides can initiate and handle requests. Which server
initiates the request is decided deterministically on the server names.
Requests are made through a mux client and server, which handles message
passing, congestion, cancelation, timeouts, etc.
If a connection is lost, all requests are canceled, and the calling server will try
to reconnect. Registered handlers can operate directly on byte 
slices or use a higher-level generics abstraction.
There is no versioning of handlers/clients, and incompatible changes should
be handled by adding new handlers.
The request path can be changed to a new one for any protocol changes.
First, all servers create a "Manager." The manager must know its address 
as well as all remote addresses. This will manage all connections.
To get a connection to any remote, ask the manager to provide it given
the remote address using.
```
func (m *Manager) Connection(host string) *Connection
```
All serverside handlers must also be registered on the manager. This will
make sure that all incoming requests are served. The number of in-flight 
requests and responses must also be given for streaming requests.
The "Connection" returned manages the mux-clients. Requests issued
to the connection will be sent to the remote.
* `func (c *Connection) Request(ctx context.Context, h HandlerID, req []byte) ([]byte, error)`
   performs a single request and returns the result. Any deadline provided on the request is
   forwarded to the server, and canceling the context will make the function return at once.
* `func (c *Connection) NewStream(ctx context.Context, h HandlerID, payload []byte) (st *Stream, err error)`
   will initiate a remote call and send the initial payload.
```Go
// A Stream is a two-way stream.
// All responses *must* be read by the caller.
// If the call is canceled through the context,
//The appropriate error will be returned.
type Stream struct {
	// Responses from the remote server.
	// Channel will be closed after an error or when the remote closes.
	// All responses *must* be read by the caller until either an error is returned or the channel is closed.
	// Canceling the context will cause the context cancellation error to be returned.
	Responses <-chan Response
	// Requests sent to the server.
	// If the handler is defined with 0 incoming capacity this will be nil.
	// Channel *must* be closed to signal the end of the stream.
	// If the request context is canceled, the stream will no longer process requests.
	Requests chan<- []byte
}
type Response struct {
	Msg []byte
	Err error
}
```
There are generic versions of the server/client handlers that allow the use of type
safe implementations for data types that support msgpack marshal/unmarshal.
											
										 
											2023-11-21 09:09:35 +08:00
										 |  |  | // RenameDataResp - RenameData()'s response.
 | 
					
						
							|  |  |  | type RenameDataResp struct { | 
					
						
							|  |  |  | 	Signature uint64 `msg:"sig"` | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-02-02 02:47:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // LocalDiskIDs - GetLocalIDs response.
 | 
					
						
							|  |  |  | type LocalDiskIDs struct { | 
					
						
							|  |  |  | 	IDs []string | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-02-20 06:54:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // ListDirResult - ListDir()'s response.
 | 
					
						
							|  |  |  | type ListDirResult struct { | 
					
						
							|  |  |  | 	Entries []string `msg:"e"` | 
					
						
							|  |  |  | } |