2016-06-02 07:43:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/ *  
						 
					
						
							
								
									
										
										
										
											2018-03-28 07:44:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Minio  Cloud  Storage ,  ( C )  2016 ,  2017 ,  2018  Minio ,  Inc . 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:43:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Licensed  under  the  Apache  License ,  Version  2.0  ( the  "License" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  you  may  not  use  this  file  except  in  compliance  with  the  License . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  You  may  obtain  a  copy  of  the  License  at 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *      http : //www.apache.org/licenses/LICENSE-2.0
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Unless  required  by  applicable  law  or  agreed  to  in  writing ,  software 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  distributed  under  the  License  is  distributed  on  an  "AS IS"  BASIS , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  WITHOUT  WARRANTIES  OR  CONDITIONS  OF  ANY  KIND ,  either  express  or  implied . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  See  the  License  for  the  specific  language  governing  permissions  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  limitations  under  the  License . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-19 07:23:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  cmd  
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
									
										
										
										
											2018-09-21 10:22:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"bytes" 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-15 03:01:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"io" 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-21 10:22:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"net/http" 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"path" 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"strconv" 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-17 06:49:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"sync" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio/cmd/logger" 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-22 13:30:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio/pkg/hash" 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/minio/minio/pkg/mimedb" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-11-21 08:57:12 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// list all errors which can be ignored in object operations.
  
						 
					
						
							
								
									
										
										
										
											2017-02-02 03:16:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								var  objectOpIgnoredErrs  =  append ( baseIgnoredErrs ,  errDiskAccessDenied )  
						 
					
						
							
								
									
										
										
										
											2016-11-21 08:57:12 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// putObjectDir hints the bottom layer to create a new directory.
  
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( xl  xlObjects )  putObjectDir ( ctx  context . Context ,  bucket ,  object  string ,  writeQuorum  int )  error  {  
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  wg  =  & sync . WaitGroup { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									errs  :=  make ( [ ] error ,  len ( xl . getDisks ( ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Prepare object creation in all disks
 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  index ,  disk  :=  range  xl . getDisks ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  disk  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										wg . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										go  func ( index  int ,  disk  StorageAPI )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											defer  wg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  :=  disk . MakeVol ( pathJoin ( bucket ,  object ) ) ;  err  !=  nil  &&  err  !=  errVolumeExists  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												errs [ index ]  =  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ( index ,  disk ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									wg . Wait ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  reduceWriteQuorumErrs ( ctx ,  errs ,  objectOpIgnoredErrs ,  writeQuorum ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/// Object Operations
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// CopyObject - copy object source object to destination object.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// if source object and destination object are same we only
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// update metadata.
  
						 
					
						
							
								
									
										
										
										
											2018-09-11 00:42:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( xl  xlObjects )  CopyObject ( ctx  context . Context ,  srcBucket ,  srcObject ,  dstBucket ,  dstObject  string ,  srcInfo  ObjectInfo ,  srcOpts ,  dstOpts  ObjectOptions )  ( oi  ObjectInfo ,  e  error )  {  
						 
					
						
							
								
									
										
										
										
											2018-02-24 07:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cpSrcDstSame  :=  isStringEqual ( pathJoin ( srcBucket ,  srcObject ) ,  pathJoin ( dstBucket ,  dstObject ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-13 12:34:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Read metadata associated with the object from all disks.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-03 09:24:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									storageDisks  :=  xl . getDisks ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									metaArr ,  errs  :=  readAllXLMetadata ( ctx ,  storageDisks ,  srcBucket ,  srcObject ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-22 19:28:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// get Quorum for this object
 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-31 15:23:29 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									readQuorum ,  writeQuorum ,  err  :=  objectQuorumFromMeta ( ctx ,  xl ,  metaArr ,  errs ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-22 19:28:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  oi ,  toObjectErr ( err ,  srcBucket ,  srcObject ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  reducedErr  :=  reduceReadQuorumErrs ( ctx ,  errs ,  objectOpIgnoredErrs ,  readQuorum ) ;  reducedErr  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-22 10:53:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  oi ,  toObjectErr ( reducedErr ,  srcBucket ,  srcObject ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// List all online disks.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-03 09:24:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_ ,  modTime  :=  listOnlineDisks ( storageDisks ,  metaArr ,  errs ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Pick latest valid metadata.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-18 05:42:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									xlMeta ,  err  :=  pickValidXLMeta ( ctx ,  metaArr ,  modTime ,  readQuorum ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-22 10:53:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  oi ,  toObjectErr ( err ,  srcBucket ,  srcObject ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Length of the file to read.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									length  :=  xlMeta . Stat . Size 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Check if this request is only metadata update.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-24 07:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  cpSrcDstSame  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Update `xl.json` content on each disks.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-03 09:24:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  index  :=  range  metaArr  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											metaArr [ index ] . Meta  =  srcInfo . UserDefined 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-10 02:50:39 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											metaArr [ index ] . Meta [ "etag" ]  =  srcInfo . ETag 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-03 09:24:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										var  onlineDisks  [ ] StorageAPI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										tempObj  :=  mustGetUUID ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Write unique `xl.json` for each disk.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  onlineDisks ,  err  =  writeUniqueXLMetadata ( ctx ,  storageDisks ,  minioMetaTmpBucket ,  tempObj ,  metaArr ,  writeQuorum ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-22 10:53:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  oi ,  toObjectErr ( err ,  srcBucket ,  srcObject ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Rename atomically `xl.json` from tmp location to destination for each disk.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  _ ,  err  =  renameXLMetadata ( ctx ,  onlineDisks ,  minioMetaTmpBucket ,  tempObj ,  srcBucket ,  srcObject ,  writeQuorum ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-22 10:53:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  oi ,  toObjectErr ( err ,  srcBucket ,  srcObject ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-15 03:05:51 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  xlMeta . ToObjectInfo ( srcBucket ,  srcObject ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Initialize pipe.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pipeReader ,  pipeWriter  :=  io . Pipe ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									go  func ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-25 01:20:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										var  startOffset  int64  // Read the whole file.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-11 00:42:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  gerr  :=  xl . getObject ( ctx ,  srcBucket ,  srcObject ,  startOffset ,  length ,  pipeWriter ,  srcInfo . ETag ,  srcOpts ) ;  gerr  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											pipeWriter . CloseWithError ( toObjectErr ( gerr ,  srcBucket ,  srcObject ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-06-29 07:02:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pipeWriter . Close ( )  // Close writer explicitly signaling we wrote all data.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:36:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									hashReader ,  err  :=  hash . NewReader ( pipeReader ,  length ,  "" ,  "" ,  length ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-22 13:30:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										logger . LogIf ( ctx ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  oi ,  toObjectErr ( err ,  dstBucket ,  dstObject ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-22 13:30:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-11-15 09:36:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									objInfo ,  err  :=  xl . putObject ( ctx ,  dstBucket ,  dstObject ,  NewPutObjReader ( hashReader ,  nil ,  nil ) ,  srcInfo . UserDefined ,  dstOpts ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-22 10:53:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  oi ,  toObjectErr ( err ,  dstBucket ,  dstObject ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Explicitly close the reader.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pipeReader . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  objInfo ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-21 10:22:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// GetObjectNInfo - returns object info and an object
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Read(Closer). When err != nil, the returned reader is always nil.
  
						 
					
						
							
								
									
										
										
										
											2018-09-27 18:06:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( xl  xlObjects )  GetObjectNInfo ( ctx  context . Context ,  bucket ,  object  string ,  rs  * HTTPRangeSpec ,  h  http . Header ,  lockType  LockType ,  opts  ObjectOptions )  ( gr  * GetObjectReader ,  err  error )  {  
						 
					
						
							
								
									
										
										
										
											2018-09-26 03:39:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  nsUnlocker  =  func ( )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-21 10:22:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Acquire lock
 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-26 03:39:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  lockType  !=  noLock  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										lock  :=  xl . nsMutex . NewNSLock ( bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  lockType  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  writeLock : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  =  lock . GetLock ( globalObjectTimeout ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											nsUnlocker  =  lock . Unlock 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  readLock : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  =  lock . GetRLock ( globalObjectTimeout ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											nsUnlocker  =  lock . RUnlock 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-21 10:22:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  =  checkGetObjArgs ( ctx ,  bucket ,  object ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										nsUnlocker ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Handler directory request by returning a reader that
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// returns no bytes.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  hasSuffix ( object ,  slashSeparator )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! xl . isObjectDir ( bucket ,  object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											nsUnlocker ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  toObjectErr ( errFileNotFound ,  bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  objInfo  ObjectInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  objInfo ,  err  =  xl . getObjectInfoDir ( ctx ,  bucket ,  object ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											nsUnlocker ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NewGetObjectReaderFromReader ( bytes . NewBuffer ( nil ) ,  objInfo ,  nsUnlocker ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  objInfo  ObjectInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objInfo ,  err  =  xl . getObjectInfo ( ctx ,  bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										nsUnlocker ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fn ,  off ,  length ,  nErr  :=  NewGetObjectReader ( rs ,  objInfo ,  nsUnlocker ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  nErr  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  nErr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pr ,  pw  :=  io . Pipe ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									go  func ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-27 18:06:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										err  :=  xl . getObject ( ctx ,  bucket ,  object ,  off ,  length ,  pw ,  "" ,  opts ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-21 10:22:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pw . CloseWithError ( err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-22 02:42:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Cleanup function to cause the go routine above to exit, in
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// case of incomplete read.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pipeCloser  :=  func ( )  {  pr . Close ( )  } 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-21 10:22:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-22 02:42:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  fn ( pr ,  h ,  pipeCloser ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-21 10:22:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:43:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// GetObject - reads an object erasured coded across multiple
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// disks. Supports additional parameters like offset and length
  
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// which are synonymous with HTTP Range requests.
  
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:43:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// startOffset indicates the starting read location of the object.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// length indicates the total length of the object.
  
						 
					
						
							
								
									
										
										
										
											2018-09-11 00:42:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( xl  xlObjects )  GetObject ( ctx  context . Context ,  bucket ,  object  string ,  startOffset  int64 ,  length  int64 ,  writer  io . Writer ,  etag  string ,  opts  ObjectOptions )  error  {  
						 
					
						
							
								
									
										
										
										
											2018-01-13 12:34:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Lock the object before reading.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objectLock  :=  xl . nsMutex . NewNSLock ( bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  objectLock . GetRLock ( globalObjectTimeout ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  objectLock . RUnlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-11 00:42:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  xl . getObject ( ctx ,  bucket ,  object ,  startOffset ,  length ,  writer ,  etag ,  opts ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-13 12:34:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// getObject wrapper for xl GetObject
  
						 
					
						
							
								
									
										
										
										
											2018-09-11 00:42:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( xl  xlObjects )  getObject ( ctx  context . Context ,  bucket ,  object  string ,  startOffset  int64 ,  length  int64 ,  writer  io . Writer ,  etag  string ,  opts  ObjectOptions )  error  {  
						 
					
						
							
								
									
										
										
										
											2018-01-13 12:34:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  :=  checkGetObjArgs ( ctx ,  bucket ,  object ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-02 15:15:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-22 03:29:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Start offset cannot be negative.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  startOffset  <  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										logger . LogIf ( ctx ,  errUnexpected ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  errUnexpected 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-07 16:30:34 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-22 03:29:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-07-08 22:46:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Writer cannot be nil.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  writer  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										logger . LogIf ( ctx ,  errUnexpected ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  errUnexpected 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-08 22:46:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-01 02:39:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// If its a directory request, we return an empty body.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  hasSuffix ( object ,  slashSeparator )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										_ ,  err  :=  writer . Write ( [ ] byte ( "" ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										logger . LogIf ( ctx ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-01 11:23:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Read metadata associated with the object from all disks.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									metaArr ,  errs  :=  readAllXLMetadata ( ctx ,  xl . getDisks ( ) ,  bucket ,  object ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-22 19:28:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// get Quorum for this object
 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-31 15:23:29 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									readQuorum ,  _ ,  err  :=  objectQuorumFromMeta ( ctx ,  xl ,  metaArr ,  errs ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-22 19:28:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  reducedErr  :=  reduceReadQuorumErrs ( ctx ,  errs ,  objectOpIgnoredErrs ,  readQuorum ) ;  reducedErr  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-20 10:24:32 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  toObjectErr ( reducedErr ,  bucket ,  object ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-10 04:01:32 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-05-26 07:42:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// List all online disks.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									onlineDisks ,  modTime  :=  listOnlineDisks ( xl . getDisks ( ) ,  metaArr ,  errs ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-27 10:55:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-17 13:26:18 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Pick latest valid metadata.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-18 05:42:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									xlMeta ,  err  :=  pickValidXLMeta ( ctx ,  metaArr ,  modTime ,  readQuorum ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-21 12:56:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-25 13:49:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Reorder online disks based on erasure distribution order.
 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-25 01:20:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									onlineDisks  =  shuffleDisks ( onlineDisks ,  xlMeta . Erasure . Distribution ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-25 13:49:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Reorder parts metadata based on erasure distribution order.
 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-25 01:20:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									metaArr  =  shufflePartsMetadata ( metaArr ,  xlMeta . Erasure . Distribution ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-26 07:42:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-12-22 03:29:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// For negative length read everything.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  length  <  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										length  =  xlMeta . Stat . Size  -  startOffset 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-08 22:46:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-12-22 03:29:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Reply back invalid range if the input offset and length fall out of range.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  startOffset  >  xlMeta . Stat . Size  ||  startOffset + length  >  xlMeta . Stat . Size  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										logger . LogIf ( ctx ,  InvalidRange { startOffset ,  length ,  xlMeta . Stat . Size } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  InvalidRange { startOffset ,  length ,  xlMeta . Stat . Size } 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-08 22:46:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-20 04:35:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Get start part index and offset.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									partIndex ,  partOffset ,  err  :=  xlMeta . ObjectToPartOffset ( ctx ,  startOffset ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  InvalidRange { startOffset ,  length ,  xlMeta . Stat . Size } 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-01 11:23:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-28 02:51:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Calculate endOffset according to length
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									endOffset  :=  startOffset 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  length  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										endOffset  +=  length  -  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-20 04:35:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Get last part index to read given length.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									lastPartIndex ,  _ ,  err  :=  xlMeta . ObjectToPartOffset ( ctx ,  endOffset ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-20 04:35:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  InvalidRange { startOffset ,  length ,  xlMeta . Stat . Size } 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-20 04:35:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-25 01:20:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  totalBytesRead  int64 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-24 14:35:37 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									erasure ,  err  :=  NewErasure ( ctx ,  xlMeta . Erasure . DataBlocks ,  xlMeta . Erasure . ParityBlocks ,  xlMeta . Erasure . BlockSize ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 09:08:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-07 06:14:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-20 04:35:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									for  ;  partIndex  <=  lastPartIndex ;  partIndex ++  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-22 05:34:11 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  length  ==  totalBytesRead  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-01 11:23:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										// Save the current part name and size.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										partName  :=  xlMeta . Parts [ partIndex ] . Name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										partSize  :=  xlMeta . Parts [ partIndex ] . Size 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-23 00:05:03 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-07 06:14:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										partLength  :=  partSize  -  partOffset 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// partLength should be adjusted so that we don't write more data than what was requested.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  partLength  >  ( length  -  totalBytesRead )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											partLength  =  length  -  totalBytesRead 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-20 04:35:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-01 11:23:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 20:58:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										tillOffset  :=  erasure . ShardFileTillOffset ( partOffset ,  partLength ,  partSize ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-16 23:35:30 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										// Get the checksums of the current part.
 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 20:58:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										readers  :=  make ( [ ] io . ReaderAt ,  len ( onlineDisks ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-07 06:14:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  index ,  disk  :=  range  onlineDisks  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 09:08:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  disk  ==  OfflineDisk  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-25 13:49:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 09:08:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											checksumInfo  :=  metaArr [ index ] . Erasure . GetChecksumInfo ( partName ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 20:58:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											readers [ index ]  =  newBitrotReader ( disk ,  bucket ,  pathJoin ( object ,  partName ) ,  tillOffset ,  checksumInfo . Algorithm ,  checksumInfo . Hash ,  erasure . ShardSize ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-16 23:35:30 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 20:58:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										err  :=  erasure . Decode ( ctx ,  writer ,  readers ,  partOffset ,  partLength ,  partSize ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Note: we should not be defer'ing the following closeBitrotReaders() call as we are inside a for loop i.e if we use defer, we would accumulate a lot of open files by the time
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// we return from this function.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										closeBitrotReaders ( readers ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-01 11:23:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-09 11:34:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											return  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-01 11:23:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 20:58:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  i ,  r  :=  range  readers  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-07 06:14:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  r  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												onlineDisks [ i ]  =  OfflineDisk 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-28 17:20:34 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										// Track total bytes read from disk and written to the client.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-07 06:14:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										totalBytesRead  +=  partLength 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-01 11:23:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-23 00:05:03 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										// partOffset will be valid only for the first part, hence reset it to 0 for
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// the remaining parts.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-01 11:23:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										partOffset  =  0 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:43:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									}  // End of read all parts loop.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-01 11:23:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Return success.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-29 06:13:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// getObjectInfoDir - This getObjectInfo is specific to object directory lookup.
  
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( xl  xlObjects )  getObjectInfoDir ( ctx  context . Context ,  bucket ,  object  string )  ( oi  ObjectInfo ,  err  error )  {  
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  wg  =  & sync . WaitGroup { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									errs  :=  make ( [ ] error ,  len ( xl . getDisks ( ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Prepare object creation in a all disks
 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  index ,  disk  :=  range  xl . getDisks ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  disk  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										wg . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										go  func ( index  int ,  disk  StorageAPI )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											defer  wg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  _ ,  err  :=  disk . StatVol ( pathJoin ( bucket ,  object ) ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// Since we are re-purposing StatVol, an object which
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// is a directory if it doesn't exist should be
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// returned as errFileNotFound instead, convert
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// the error right here accordingly.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  err  ==  errVolumeNotFound  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													err  =  errFileNotFound 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												}  else  if  err  ==  errVolumeAccessDenied  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													err  =  errFileAccessDenied 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// Save error to reduce it later
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												errs [ index ]  =  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ( index ,  disk ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									wg . Wait ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									readQuorum  :=  len ( xl . getDisks ( ) )  /  2 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  dirObjectInfo ( bucket ,  object ,  0 ,  map [ string ] string { } ) ,  reduceReadQuorumErrs ( ctx ,  errs ,  objectOpIgnoredErrs ,  readQuorum ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:43:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// GetObjectInfo - reads object metadata and replies back ObjectInfo.
  
						 
					
						
							
								
									
										
										
										
											2018-09-11 00:42:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( xl  xlObjects )  GetObjectInfo ( ctx  context . Context ,  bucket ,  object  string ,  opts  ObjectOptions )  ( oi  ObjectInfo ,  e  error )  {  
						 
					
						
							
								
									
										
										
										
											2018-01-13 12:34:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Lock the object before reading.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objectLock  :=  xl . nsMutex . NewNSLock ( bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  objectLock . GetRLock ( globalObjectTimeout ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  oi ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  objectLock . RUnlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  :=  checkGetObjArgs ( ctx ,  bucket ,  object ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-22 10:53:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  oi ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-01 02:39:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  hasSuffix ( object ,  slashSeparator )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 10:08:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ! xl . isObjectDir ( bucket ,  object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  oi ,  toObjectErr ( errFileNotFound ,  bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  oi ,  e  =  xl . getObjectInfoDir ( ctx ,  bucket ,  object ) ;  e  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-02 16:34:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  oi ,  toObjectErr ( e ,  bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  oi ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									info ,  err  :=  xl . getObjectInfo ( ctx ,  bucket ,  object ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-22 10:53:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  oi ,  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  info ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-20 02:00:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( xl  xlObjects )  isObjectCorrupted ( metaArr  [ ] xlMetaV1 ,  errs  [ ] error )  ( validMeta  xlMetaV1 ,  ok  bool )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// We can consider an object data not reliable
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// when xl.json is not found in read quorum disks.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-27 05:20:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  notFoundXLJSON ,  corruptedXLJSON  int 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-20 02:00:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  _ ,  readErr  :=  range  errs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  readErr  ==  errFileNotFound  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											notFoundXLJSON ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-27 05:20:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  _ ,  readErr  :=  range  errs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  readErr  ==  errCorruptedFormat  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											corruptedXLJSON ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-02 02:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-20 02:00:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  _ ,  m  :=  range  metaArr  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! m . IsValid ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										validMeta  =  m 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Return if the object is indeed corrupted.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-27 05:20:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  validMeta ,  len ( xl . getDisks ( ) ) - notFoundXLJSON  <  validMeta . Erasure . DataBlocks  ||  len ( xl . getDisks ( ) )  ==  corruptedXLJSON 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-20 02:00:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  xlCorruptedSuffix  =  ".CORRUPTED"  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Renames the corrupted object and makes it visible.
  
						 
					
						
							
								
									
										
										
										
											2018-11-27 05:20:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( xl  xlObjects )  renameCorruptedObject ( ctx  context . Context ,  bucket ,  object  string ,  validMeta  xlMetaV1 ,  disks  [ ] StorageAPI ,  errs  [ ] error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// if errs returned are corrupted
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  validMeta . Erasure . DataBlocks  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										validMeta  =  newXLMetaV1 ( object ,  len ( disks ) / 2 ,  len ( disks ) / 2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-20 02:00:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									writeQuorum  :=  validMeta . Erasure . DataBlocks  +  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Move all existing objects into corrupted suffix.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-27 05:20:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									oldObj  :=  mustGetUUID ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									rename ( ctx ,  disks ,  bucket ,  object ,  minioMetaTmpBucket ,  oldObj ,  true ,  writeQuorum ,  [ ] error { errFileNotFound } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Delete temporary object in the event of failure.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// If PutObject succeeded there would be no temporary
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// object to delete.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  xl . deleteObject ( ctx ,  minioMetaTmpBucket ,  oldObj ,  writeQuorum ,  false ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-20 02:00:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tempObj  :=  mustGetUUID ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Get all the disks which do not have the file.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  cdisks  =  make ( [ ] StorageAPI ,  len ( disks ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i ,  merr  :=  range  errs  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-27 05:20:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  merr  ==  errFileNotFound  ||  merr  ==  errCorruptedFormat  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-20 02:00:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											cdisks [ i ]  =  disks [ i ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-02 02:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-20 02:00:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  _ ,  disk  :=  range  cdisks  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  disk  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-17 06:49:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-20 02:00:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Write empty part file on missing disks.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										disk . AppendFile ( minioMetaTmpBucket ,  pathJoin ( tempObj ,  "part.1" ) ,  [ ] byte { } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Write algorithm hash for empty part file.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-27 05:20:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										var  algorithm  =  DefaultBitrotAlgorithm 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										h  :=  algorithm . New ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										h . Write ( [ ] byte { } ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-20 02:00:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Update the checksums and part info.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-27 05:20:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										validMeta . Erasure . Checksums  =  [ ] ChecksumInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Name :       "part.1" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Algorithm :  algorithm , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Hash :       h . Sum ( nil ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} , 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-20 02:00:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-27 05:20:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-06 06:16:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										validMeta . Parts  =  [ ] ObjectPartInfo { 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-27 05:20:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Number :  1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Name :    "part.1" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} , 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-20 02:00:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Write the `xl.json` with the newly calculated metadata.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeXLMetadata ( ctx ,  disk ,  minioMetaTmpBucket ,  tempObj ,  validMeta ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Finally rename all the parts into their respective locations.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									rename ( ctx ,  cdisks ,  minioMetaTmpBucket ,  tempObj ,  bucket ,  object + xlCorruptedSuffix ,  true ,  writeQuorum ,  [ ] error { errFileNotFound } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// getObjectInfo - wrapper for reading object metadata and constructs ObjectInfo.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( xl  xlObjects )  getObjectInfo ( ctx  context . Context ,  bucket ,  object  string )  ( objInfo  ObjectInfo ,  err  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									disks  :=  xl . getDisks ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Read metadata associated with the object from all disks.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									metaArr ,  errs  :=  readAllXLMetadata ( ctx ,  disks ,  bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  readQuorum  int 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-17 06:49:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Having read quorum means we have xl.json in at least N/2 disks.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! strings . HasSuffix ( object ,  xlCorruptedSuffix )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-20 02:00:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  validMeta ,  ok  :=  xl . isObjectCorrupted ( metaArr ,  errs ) ;  ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-27 05:20:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											xl . renameCorruptedObject ( ctx ,  bucket ,  object ,  validMeta ,  disks ,  errs ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-17 06:49:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// Return err file not found since we renamed now the corrupted object
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  objInfo ,  errFileNotFound 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-20 02:00:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Not a corrupted object, attempt to get readquorum properly.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										readQuorum ,  _ ,  err  =  objectQuorumFromMeta ( ctx ,  xl ,  metaArr ,  errs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  objInfo ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-17 06:49:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-20 02:00:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-17 06:49:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// If this is a corrupted object, change read quorum to N/2 disks
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// so it will be visible to users, so they can delete it.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										readQuorum  =  len ( xl . getDisks ( ) )  /  2 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-02 02:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// List all the file commit ids from parts metadata.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									modTimes  :=  listObjectModtimes ( metaArr ,  errs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Reduce list of UUIDs to a single common value.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									modTime ,  _  :=  commonTime ( modTimes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Pick latest valid metadata.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-18 05:42:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									xlMeta ,  err  :=  pickValidXLMeta ( ctx ,  metaArr ,  modTime ,  readQuorum ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-25 16:33:39 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-02 02:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  objInfo ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-09 13:38:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-02 03:37:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  xlMeta . ToObjectInfo ( bucket ,  object ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  undoRename ( disks  [ ] StorageAPI ,  srcBucket ,  srcEntry ,  dstBucket ,  dstEntry  string ,  isDir  bool ,  errs  [ ] error )  {  
						 
					
						
							
								
									
										
										
										
											2016-06-18 02:57:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									var  wg  =  & sync . WaitGroup { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Undo rename object on disks where RenameFile succeeded.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-21 10:11:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// If srcEntry/dstEntry are objects then add a trailing slash to copy
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// over all the parts inside the object directory
 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  isDir  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-21 10:11:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										srcEntry  =  retainSlash ( srcEntry ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dstEntry  =  retainSlash ( dstEntry ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-12 13:53:54 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									for  index ,  disk  :=  range  disks  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-18 02:57:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  disk  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Undo rename object in parallel.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										wg . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										go  func ( index  int ,  disk  StorageAPI )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											defer  wg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  errs [ index ]  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-21 10:11:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											_  =  disk . RenameFile ( dstBucket ,  dstEntry ,  srcBucket ,  srcEntry ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-18 02:57:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} ( index ,  disk ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									wg . Wait ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-21 10:11:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// rename - common function that renamePart and renameObject use to rename
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// the respective underlying storage layer representations.
  
						 
					
						
							
								
									
										
										
										
											2018-04-12 08:15:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  rename ( ctx  context . Context ,  disks  [ ] StorageAPI ,  srcBucket ,  srcEntry ,  dstBucket ,  dstEntry  string ,  isDir  bool ,  writeQuorum  int ,  ignoredErr  [ ] error )  ( [ ] StorageAPI ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Initialize sync waitgroup.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  wg  =  & sync . WaitGroup { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Initialize list of errors.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-12 13:53:54 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									var  errs  =  make ( [ ] error ,  len ( disks ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  isDir  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-21 10:11:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										dstEntry  =  retainSlash ( dstEntry ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										srcEntry  =  retainSlash ( srcEntry ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Rename file on all underlying storage disks.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-12 13:53:54 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									for  index ,  disk  :=  range  disks  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  disk  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											errs [ index ]  =  errDiskNotFound 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										wg . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										go  func ( index  int ,  disk  StorageAPI )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											defer  wg . Done ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-12 08:15:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  :=  disk . RenameFile ( srcBucket ,  srcEntry ,  dstBucket ,  dstEntry ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ! IsErrIgnored ( err ,  ignoredErr ... )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													errs [ index ]  =  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ( index ,  disk ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:43:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Wait for all renames to finish.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									wg . Wait ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// We can safely allow RenameFile errors up to len(xl.getDisks()) - writeQuorum
 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// otherwise return failure. Cleanup successful renames.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									err  :=  reduceWriteQuorumErrs ( ctx ,  errs ,  objectOpIgnoredErrs ,  writeQuorum ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-11 00:36:37 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  ==  errXLWriteQuorum  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-18 02:57:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										// Undo all the partial rename operations.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-27 08:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										undoRename ( disks ,  srcBucket ,  srcEntry ,  dstBucket ,  dstEntry ,  isDir ,  errs ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-15 08:14:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  evalDisks ( disks ,  errs ) ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:43:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// PutObject - creates an object upon reading from the input stream
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// until EOF, erasure codes the data across all disk and additionally
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// writes `xl.json` which carries the necessary metadata for future
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// object operations.
  
						 
					
						
							
								
									
										
										
										
											2018-11-15 09:36:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( xl  xlObjects )  PutObject ( ctx  context . Context ,  bucket  string ,  object  string ,  data  * PutObjReader ,  metadata  map [ string ] string ,  opts  ObjectOptions )  ( objInfo  ObjectInfo ,  err  error )  {  
						 
					
						
							
								
									
										
										
										
											2018-02-10 07:19:30 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Validate put object input args.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  =  checkPutObjectArgs ( ctx ,  bucket ,  object ,  xl ,  data . Size ( ) ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-10 07:19:30 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  ObjectInfo { } ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-21 10:22:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-13 12:34:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Lock the object.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objectLock  :=  xl . nsMutex . NewNSLock ( bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  objectLock . GetLock ( globalObjectTimeout ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  objInfo ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  objectLock . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-11 00:42:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  xl . putObject ( ctx ,  bucket ,  object ,  data ,  metadata ,  opts ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-13 12:34:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// putObject wrapper for xl PutObject
  
						 
					
						
							
								
									
										
										
										
											2018-11-15 09:36:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( xl  xlObjects )  putObject ( ctx  context . Context ,  bucket  string ,  object  string ,  r  * PutObjReader ,  metadata  map [ string ] string ,  opts  ObjectOptions )  ( objInfo  ObjectInfo ,  err  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									data  :=  r . Reader 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									uniqueID  :=  mustGetUUID ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tempObj  :=  uniqueID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// No metadata is set, allocate a new one.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  metadata  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										metadata  =  make ( map [ string ] string ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Get parity and data drive count based on storage class metadata
 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									dataDrives ,  parityDrives  :=  getRedundancyCount ( metadata [ amzStorageClass ] ,  len ( xl . getDisks ( ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// we now know the number of blocks this object needs for data and parity.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// writeQuorum is dataBlocks + 1
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									writeQuorum  :=  dataDrives  +  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Delete temporary object in the event of failure.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// If PutObject succeeded there would be no temporary
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// object to delete.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-30 04:36:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									defer  xl . deleteObject ( ctx ,  minioMetaTmpBucket ,  tempObj ,  writeQuorum ,  false ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-21 08:33:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// This is a special case with size as '0' and object ends with
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// a slash separator, we treat it like a valid operation and
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// return success.
 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-20 03:40:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  isObjectDir ( object ,  data . Size ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-22 11:43:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Check if an object is present as one of the parent dir.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// -- FIXME. (needs a new kind of lock).
 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-10 05:32:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// -- FIXME (this also causes performance issue when disks are down).
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  xl . parentDirIsObject ( ctx ,  bucket ,  path . Dir ( object ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  ObjectInfo { } ,  toObjectErr ( errFileAccessDenied ,  bucket ,  object ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-22 11:43:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  =  xl . putObjectDir ( ctx ,  minioMetaTmpBucket ,  tempObj ,  writeQuorum ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  ObjectInfo { } ,  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-18 07:37:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Rename the successfully written temporary object to final location. Ignore errFileAccessDenied
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// error because it means that the target object dir exists and we want to be close to S3 specification.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  _ ,  err  =  rename ( ctx ,  xl . getDisks ( ) ,  minioMetaTmpBucket ,  tempObj ,  bucket ,  object ,  true ,  writeQuorum ,  [ ] error { errFileAccessDenied } ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  ObjectInfo { } ,  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-09-20 03:40:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  dirObjectInfo ( bucket ,  object ,  data . Size ( ) ,  metadata ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-21 08:33:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-22 11:43:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Validate put object input args.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  =  checkPutObjectArgs ( ctx ,  bucket ,  object ,  xl ,  data . Size ( ) ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-02 15:15:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  ObjectInfo { } ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-22 11:43:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-07 00:38:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Validate input data size and it can never be less than zero.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:36:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  data . Size ( )  <  - 1  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										logger . LogIf ( ctx ,  errInvalidArgument ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ObjectInfo { } ,  toObjectErr ( errInvalidArgument ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-07 00:38:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-22 11:43:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Check if an object is present as one of the parent dir.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// -- FIXME. (needs a new kind of lock).
 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-10 05:32:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// -- FIXME (this also causes performance issue when disks are down).
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  xl . parentDirIsObject ( ctx ,  bucket ,  path . Dir ( object ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ObjectInfo { } ,  toObjectErr ( errFileAccessDenied ,  bucket ,  object ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-22 11:43:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-09-20 03:40:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Limit the reader to its provided size if specified.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  reader  io . Reader  =  data 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-03 06:51:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Initialize parts metadata
 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									partsMetadata  :=  make ( [ ] xlMetaV1 ,  len ( xl . getDisks ( ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-22 19:28:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									xlMeta  :=  newXLMetaV1 ( object ,  dataDrives ,  parityDrives ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-14 02:56:25 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Initialize xl meta.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  index  :=  range  partsMetadata  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										partsMetadata [ index ]  =  xlMeta 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Order disks according to erasure distribution
 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									onlineDisks  :=  shuffleDisks ( xl . getDisks ( ) ,  partsMetadata [ 0 ] . Erasure . Distribution ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:43:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Total size of the written object
 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-25 01:20:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  sizeWritten  int64 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-24 14:35:37 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									erasure ,  err  :=  NewErasure ( ctx ,  xlMeta . Erasure . DataBlocks ,  xlMeta . Erasure . ParityBlocks ,  xlMeta . Erasure . BlockSize ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 09:08:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ObjectInfo { } ,  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-07 00:38:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Fetch buffer for I/O, returns from the pool if not allocates a new one and returns.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-06-14 02:55:12 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  buffer  [ ] byte 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  size  :=  data . Size ( ) ;  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  size  ==  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										buffer  =  make ( [ ] byte ,  1 )  // Allocate atleast a byte to reach EOF
 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-05 06:37:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  size  ==  - 1  ||  size  >=  blockSizeV1 : 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:36:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										buffer  =  xl . bp . Get ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										defer  xl . bp . Put ( buffer ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-06-14 02:55:12 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  size  <  blockSizeV1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// No need to allocate fully blockSizeV1 buffer if the incoming data is smaller.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										buffer  =  make ( [ ] byte ,  size ,  2 * size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-07 00:38:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-07 06:14:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  len ( buffer )  >  int ( xlMeta . Erasure . BlockSize )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										buffer  =  buffer [ : xlMeta . Erasure . BlockSize ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Read data and split into parts - similar to multipart mechanism
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  partIdx  :=  1 ;  ;  partIdx ++  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Compute part name
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										partName  :=  "part."  +  strconv . Itoa ( partIdx ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Compute the path of current part
 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-22 11:43:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										tempErasureObj  :=  pathJoin ( uniqueID ,  partName ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-22 13:30:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Calculate the size of the current part.
 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-01 07:34:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										var  curPartSize  int64 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										curPartSize ,  err  =  calculatePartSizeFromIdx ( ctx ,  data . Size ( ) ,  globalPutPartSize ,  partIdx ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-01 07:34:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 20:58:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											logger . LogIf ( ctx ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-01 07:34:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  ObjectInfo { } ,  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-25 01:20:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Hint the filesystem to pre-allocate one continuous large block.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// This is only an optimization.
 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-22 13:30:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										var  curPartReader  io . Reader 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:36:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-22 13:30:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  curPartSize  <  data . Size ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											curPartReader  =  io . LimitReader ( reader ,  curPartSize ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											curPartReader  =  reader 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 20:58:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writers  :=  make ( [ ] io . Writer ,  len ( onlineDisks ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-07 06:14:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  i ,  disk  :=  range  onlineDisks  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  disk  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 20:58:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											writers [ i ]  =  newBitrotWriter ( disk ,  minioMetaTmpBucket ,  tempErasureObj ,  erasure . ShardFileSize ( curPartSize ) ,  DefaultBitrotAlgorithm ,  erasure . ShardSize ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-07 06:14:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 20:58:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-24 14:35:37 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										n ,  erasureErr  :=  erasure . Encode ( ctx ,  curPartReader ,  writers ,  buffer ,  erasure . dataBlocks + 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 20:58:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Note: we should not be defer'ing the following closeBitrotWriters() call as we are inside a for loop i.e if we use defer, we would accumulate a lot of open files by the time
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// we return from this function.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										closeBitrotWriters ( writers ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  erasureErr  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  ObjectInfo { } ,  toObjectErr ( erasureErr ,  minioMetaTmpBucket ,  tempErasureObj ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Should return IncompleteBody{} error when reader has fewer bytes
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// than specified in request header.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:36:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  n  <  curPartSize  &&  data . Size ( )  >  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											logger . LogIf ( ctx ,  IncompleteBody { } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  ObjectInfo { } ,  IncompleteBody { } 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:36:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  n  ==  0  &&  data . Size ( )  ==  - 1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// The last part of a compressed object will always be empty
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Since the compressed size is unpredictable.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Hence removing the last (empty) part from all `xl.disks`.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											dErr  :=  xl . deleteObject ( ctx ,  minioMetaTmpBucket ,  tempErasureObj ,  writeQuorum ,  true ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  dErr  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  ObjectInfo { } ,  toObjectErr ( dErr ,  minioMetaTmpBucket ,  tempErasureObj ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Update the total written size
 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-07 06:14:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										sizeWritten  +=  n 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-15 09:08:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-07 06:14:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  i ,  w  :=  range  writers  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  w  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												onlineDisks [ i ]  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:36:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											partsMetadata [ i ] . AddObjectPart ( partIdx ,  partName ,  "" ,  n ,  data . ActualSize ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 20:58:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											partsMetadata [ i ] . Erasure . AddChecksumInfo ( ChecksumInfo { partName ,  DefaultBitrotAlgorithm ,  bitrotWriterSum ( w ) } ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-01 07:34:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-22 13:30:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// We wrote everything, break out.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  sizeWritten  ==  data . Size ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-19 10:06:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-02 05:33:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Save additional erasureMetadata.
 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-19 02:28:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									modTime  :=  UTCNow ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-15 09:36:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									metadata [ "etag" ]  =  r . MD5CurrentHexString ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:43:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-17 12:42:02 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Guess content-type from the extension if possible.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  metadata [ "content-type" ]  ==  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-02 14:18:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										metadata [ "content-type" ]  =  mimedb . TypeByExtension ( path . Ext ( object ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-20 21:18:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  xl . isObject ( bucket ,  object )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-04 11:39:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Deny if WORM is enabled
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  globalWORMEnabled  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  ObjectInfo { } ,  ObjectAlreadyExists { Bucket :  bucket ,  Object :  object } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-22 11:43:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Rename if an object already exists to temporary location.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										newUniqueID  :=  mustGetUUID ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Delete successfully renamed object.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-30 04:36:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										defer  xl . deleteObject ( ctx ,  minioMetaTmpBucket ,  newUniqueID ,  writeQuorum ,  false ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-20 13:52:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-05 08:22:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// NOTE: Do not use online disks slice here: the reason is that existing object should be purged
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// regardless of `xl.json` status and rolled back in case of errors. Also allow renaming the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// existing object if it is not present in quorum disks so users can overwrite stale objects.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										_ ,  err  =  rename ( ctx ,  xl . getDisks ( ) ,  bucket ,  object ,  minioMetaTmpBucket ,  newUniqueID ,  true ,  writeQuorum ,  [ ] error { errFileNotFound } ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-20 21:18:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-03 03:18:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  ObjectInfo { } ,  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-20 21:18:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-05-27 10:55:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Fill all the necessary metadata.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:43:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Update `xl.json` content on each disks.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-01 11:23:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									for  index  :=  range  partsMetadata  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										partsMetadata [ index ] . Meta  =  metadata 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-20 03:40:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										partsMetadata [ index ] . Stat . Size  =  sizeWritten 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										partsMetadata [ index ] . Stat . ModTime  =  modTime 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-01 11:23:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Write unique `xl.json` for each disk.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  onlineDisks ,  err  =  writeUniqueXLMetadata ( ctx ,  onlineDisks ,  minioMetaTmpBucket ,  tempObj ,  partsMetadata ,  writeQuorum ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-03 03:18:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  ObjectInfo { } ,  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-29 15:42:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:43:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Rename the successfully written temporary object to final location.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-05 08:22:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  _ ,  err  =  rename ( ctx ,  onlineDisks ,  minioMetaTmpBucket ,  tempObj ,  bucket ,  object ,  true ,  writeQuorum ,  nil ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-03 03:18:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  ObjectInfo { } ,  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-29 06:13:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-29 15:42:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-31 07:44:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Object info is the same in all disks, so we can pick the first meta
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// of the first disk
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									xlMeta  =  partsMetadata [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-09-03 03:18:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									objInfo  =  ObjectInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										IsDir :            false , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Bucket :           bucket , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Name :             object , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Size :             xlMeta . Stat . Size , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ModTime :          xlMeta . Stat . ModTime , 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-15 03:05:51 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ETag :             xlMeta . Meta [ "etag" ] , 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-03 03:18:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ContentType :      xlMeta . Meta [ "content-type" ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ContentEncoding :  xlMeta . Meta [ "content-encoding" ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										UserDefined :      xlMeta . Meta , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-17 11:23:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Success, return object info.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-03 03:18:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  objInfo ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:43:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// deleteObject - wrapper for delete object, deletes an object from
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// all the disks in parallel, including `xl.json` associated with the
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// object.
  
						 
					
						
							
								
									
										
										
										
											2018-08-30 04:36:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( xl  xlObjects )  deleteObject ( ctx  context . Context ,  bucket ,  object  string ,  writeQuorum  int ,  isDir  bool )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  disks  [ ] StorageAPI 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  err  error 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-21 07:33:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-30 04:36:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									tmpObj  :=  mustGetUUID ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  bucket  ==  minioMetaTmpBucket  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tmpObj  =  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										disks  =  xl . getDisks ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-05 08:22:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Rename the current object while requiring write quorum, but also consider
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// that a non found object in a given disk as a success since it already
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// confirms that the object doesn't have a part in that disk (already removed)
 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-30 04:36:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  isDir  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-05 08:22:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											disks ,  err  =  rename ( ctx ,  xl . getDisks ( ) ,  bucket ,  object ,  minioMetaTmpBucket ,  tmpObj ,  true ,  writeQuorum , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												[ ] error { errFileNotFound ,  errFileAccessDenied } ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-30 04:36:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-05 08:22:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											disks ,  err  =  rename ( ctx ,  xl . getDisks ( ) ,  bucket ,  object ,  minioMetaTmpBucket ,  tmpObj ,  true ,  writeQuorum , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												[ ] error { errFileNotFound } ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 10:43:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-27 07:39:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-30 04:36:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-27 07:39:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-22 19:28:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-30 04:36:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Initialize sync waitgroup.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  wg  =  & sync . WaitGroup { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Initialize list of errors.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-30 04:36:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  dErrs  =  make ( [ ] error ,  len ( disks ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-30 04:36:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  index ,  disk  :=  range  disks  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  disk  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											dErrs [ index ]  =  errDiskNotFound 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										wg . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-21 07:33:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										go  func ( index  int ,  disk  StorageAPI ,  isDir  bool )  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											defer  wg . Done ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-27 07:39:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											var  e  error 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-21 07:33:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  isDir  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// DeleteFile() simply tries to remove a directory
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// and will succeed only if that directory is empty.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-30 04:36:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												e  =  disk . DeleteFile ( minioMetaTmpBucket ,  tmpObj ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-21 07:33:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-30 04:36:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												e  =  cleanupDir ( ctx ,  disk ,  minioMetaTmpBucket ,  tmpObj ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-21 07:33:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-11 00:36:37 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  e  !=  nil  &&  e  !=  errVolumeNotFound  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-27 07:39:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												dErrs [ index ]  =  e 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-26 05:32:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-21 07:33:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} ( index ,  disk ,  isDir ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Wait for all routines to finish.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									wg . Wait ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-27 07:39:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// return errors if any during deletion
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  reduceWriteQuorumErrs ( ctx ,  dErrs ,  objectOpIgnoredErrs ,  writeQuorum ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:43:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// DeleteObject - deletes an object, this call doesn't necessary reply
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// any error as it is not necessary for the handler to reply back a
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// response to the client request.
  
						 
					
						
							
								
									
										
										
										
											2018-03-15 03:01:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( xl  xlObjects )  DeleteObject ( ctx  context . Context ,  bucket ,  object  string )  ( err  error )  {  
						 
					
						
							
								
									
										
										
										
											2018-01-13 12:34:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Acquire a write lock before deleting the object.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objectLock  :=  xl . nsMutex . NewNSLock ( bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  perr  :=  objectLock . GetLock ( globalOperationTimeout ) ;  perr  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  perr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  objectLock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  =  checkDelObjArgs ( ctx ,  bucket ,  object ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-02 15:15:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-01 02:39:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-01 04:16:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  writeQuorum  int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  isObjectDir  =  hasSuffix ( object ,  slashSeparator ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-30 04:36:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-31 07:07:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  isObjectDir  &&  ! xl . isObjectDir ( bucket ,  object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  toObjectErr ( errFileNotFound ,  bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-01 04:16:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  isObjectDir  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeQuorum  =  len ( xl . getDisks ( ) ) / 2  +  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Read metadata associated with the object from all disks.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										partsMetadata ,  errs  :=  readAllXLMetadata ( ctx ,  xl . getDisks ( ) ,  bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// get Quorum for this object
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										_ ,  writeQuorum ,  err  =  objectQuorumFromMeta ( ctx ,  xl ,  partsMetadata ,  errs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-30 04:36:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-17 13:18:43 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-18 02:57:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Delete the object on all disks.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-01 04:16:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  =  xl . deleteObject ( ctx ,  bucket ,  object ,  writeQuorum ,  isObjectDir ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-18 02:57:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  toObjectErr ( err ,  bucket ,  object ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-08 02:35:03 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-06-18 02:57:51 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Success.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-21 11:48:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2018-02-10 07:19:30 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ListObjectsV2 lists all blobs in bucket filtered by prefix
  
						 
					
						
							
								
									
										
										
										
											2018-03-15 03:01:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( xl  xlObjects )  ListObjectsV2 ( ctx  context . Context ,  bucket ,  prefix ,  continuationToken ,  delimiter  string ,  maxKeys  int ,  fetchOwner  bool ,  startAfter  string )  ( result  ListObjectsV2Info ,  err  error )  {  
						 
					
						
							
								
									
										
										
										
											2018-07-01 12:22:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									marker  :=  continuationToken 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  marker  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										marker  =  startAfter 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									loi ,  err  :=  xl . ListObjects ( ctx ,  bucket ,  prefix ,  marker ,  delimiter ,  maxKeys ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-10 07:19:30 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  result ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									listObjectsV2Info  :=  ListObjectsV2Info { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										IsTruncated :            loi . IsTruncated , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ContinuationToken :      continuationToken , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										NextContinuationToken :  loi . NextMarker , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Objects :                loi . Objects , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Prefixes :               loi . Prefixes , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  listObjectsV2Info ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}