mirror of
https://github.com/pgsty/minio.git
synced 2026-08-10 16:23:28 +03:00
XL/PutObject: Add single putObject and multipart caching. (#2115)
- Additionally adds test cases as well for object cache. - Adds auto-expiry with expiration and cleanup time interval. Fixes #2080 Fixes #2091
This commit is contained in:
committed by
Anand Babu (AB) Periasamy
parent
b0c180b77c
commit
c0c8a8430e
+41
-9
@@ -114,7 +114,7 @@ func (xl xlObjects) GetObject(bucket, object string, startOffset int64, length i
|
||||
mw := writer
|
||||
|
||||
// Object cache enabled block.
|
||||
if xl.objCacheEnabled {
|
||||
if xlMeta.Stat.Size > 0 && xl.objCacheEnabled {
|
||||
// Validate if we have previous cache.
|
||||
cachedBuffer, err := xl.objCache.Open(path.Join(bucket, object))
|
||||
if err == nil { // Cache hit.
|
||||
@@ -144,9 +144,10 @@ func (xl xlObjects) GetObject(bucket, object string, startOffset int64, length i
|
||||
mw = io.MultiWriter(newBuffer, writer)
|
||||
defer newBuffer.Close()
|
||||
}
|
||||
// Ignore error if cache is full, proceed to write the object.
|
||||
if err != nil && err != objcache.ErrCacheFull {
|
||||
// Perhaps cache is full, returns here.
|
||||
return err
|
||||
// For any other error return here.
|
||||
return toObjectErr(err, bucket, object)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,7 +171,7 @@ func (xl xlObjects) GetObject(bucket, object string, startOffset int64, length i
|
||||
// Start reading the part name.
|
||||
n, err := erasureReadFile(mw, onlineDisks, bucket, pathJoin(object, partName), partName, eInfos, partOffset, readSize, partSize)
|
||||
if err != nil {
|
||||
return err
|
||||
return toObjectErr(err, bucket, object)
|
||||
}
|
||||
|
||||
totalBytesRead += n
|
||||
@@ -340,7 +341,7 @@ func (xl xlObjects) renameObject(srcBucket, srcObject, dstBucket, dstObject stri
|
||||
// until EOF, erasure codes the data across all disk and additionally
|
||||
// writes `xl.json` which carries the necessary metadata for future
|
||||
// object operations.
|
||||
func (xl xlObjects) PutObject(bucket string, object string, size int64, data io.Reader, metadata map[string]string) (string, error) {
|
||||
func (xl xlObjects) PutObject(bucket string, object string, size int64, data io.Reader, metadata map[string]string) (md5Sum string, err error) {
|
||||
// Verify if bucket is valid.
|
||||
if !IsValidBucketName(bucket) {
|
||||
return "", BucketNameInvalid{Bucket: bucket}
|
||||
@@ -359,14 +360,15 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io.
|
||||
if metadata == nil {
|
||||
metadata = make(map[string]string)
|
||||
}
|
||||
nsMutex.Lock(bucket, object)
|
||||
defer nsMutex.Unlock(bucket, object)
|
||||
|
||||
uniqueID := getUUID()
|
||||
tempErasureObj := path.Join(tmpMetaPrefix, uniqueID, "part.1")
|
||||
minioMetaTmpBucket := path.Join(minioMetaBucket, tmpMetaPrefix)
|
||||
tempObj := uniqueID
|
||||
|
||||
// Lock the object.
|
||||
nsMutex.Lock(bucket, object)
|
||||
defer nsMutex.Unlock(bucket, object)
|
||||
|
||||
// Initialize xl meta.
|
||||
xlMeta := newXLMetaV1(object, xl.dataBlocks, xl.parityBlocks)
|
||||
|
||||
@@ -388,9 +390,33 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io.
|
||||
higherVersion++
|
||||
}
|
||||
|
||||
var mw io.Writer
|
||||
// Initialize md5 writer.
|
||||
md5Writer := md5.New()
|
||||
|
||||
// Proceed to set the cache.
|
||||
var newBuffer io.WriteCloser
|
||||
|
||||
// If caching is enabled, proceed to set the cache.
|
||||
if size > 0 && xl.objCacheEnabled {
|
||||
// PutObject invalidates any previously cached object in memory.
|
||||
xl.objCache.Delete(path.Join(bucket, object))
|
||||
|
||||
// Create a new entry in memory of size.
|
||||
newBuffer, err = xl.objCache.Create(path.Join(bucket, object), size)
|
||||
if err == nil {
|
||||
// Create a multi writer to write to both memory and client response.
|
||||
mw = io.MultiWriter(newBuffer, md5Writer)
|
||||
}
|
||||
// Ignore error if cache is full, proceed to write the object.
|
||||
if err != nil && err != objcache.ErrCacheFull {
|
||||
// For any other error return here.
|
||||
return "", toObjectErr(err, bucket, object)
|
||||
}
|
||||
} else {
|
||||
mw = md5Writer
|
||||
}
|
||||
|
||||
// Limit the reader to its provided size if specified.
|
||||
var limitDataReader io.Reader
|
||||
if size > 0 {
|
||||
@@ -403,7 +429,7 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io.
|
||||
}
|
||||
|
||||
// Tee reader combines incoming data stream and md5, data read from input stream is written to md5.
|
||||
teeReader := io.TeeReader(limitDataReader, md5Writer)
|
||||
teeReader := io.TeeReader(limitDataReader, mw)
|
||||
|
||||
// Collect all the previous erasure infos across the disk.
|
||||
var eInfos []erasureInfo
|
||||
@@ -505,6 +531,12 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io.
|
||||
// Delete the temporary object.
|
||||
xl.deleteObject(minioMetaTmpBucket, newUniqueID)
|
||||
|
||||
// Once we have successfully renamed the object, Close the buffer which would
|
||||
// save the object on cache.
|
||||
if size > 0 && xl.objCacheEnabled && newBuffer != nil {
|
||||
newBuffer.Close()
|
||||
}
|
||||
|
||||
// Return md5sum, successfully wrote object.
|
||||
return newMD5Hex, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user