| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2017-01-19 04:24:34 +08:00
										 |  |  |  * Minio Cloud Storage, (C) 2016, 2017 Minio, Inc. | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2017-08-13 10:25:43 +08:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2016-10-11 15:50:27 +08:00
										 |  |  | 	"runtime" | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 	"sync" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							| 
									
										
										
										
											2016-12-23 23:12:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/minio/dsync" | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Helper function to test equality of locks (without taking timing info into account)
 | 
					
						
							|  |  |  | func testLockEquality(lriLeft, lriRight []lockRequesterInfo) bool { | 
					
						
							|  |  |  | 	if len(lriLeft) != len(lriRight) { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < len(lriLeft); i++ { | 
					
						
							|  |  |  | 		if lriLeft[i].writer != lriRight[i].writer || | 
					
						
							|  |  |  | 			lriLeft[i].node != lriRight[i].node || | 
					
						
							| 
									
										
										
										
											2017-04-12 01:25:21 +08:00
										 |  |  | 			lriLeft[i].serviceEndpoint != lriRight[i].serviceEndpoint || | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 			lriLeft[i].uid != lriRight[i].uid { | 
					
						
							|  |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Helper function to create a lock server for testing
 | 
					
						
							| 
									
										
										
										
											2018-06-06 16:51:56 +08:00
										 |  |  | func createLockTestServer(t *testing.T) (string, *lockRPCReceiver, string) { | 
					
						
							| 
									
										
										
										
											2018-08-15 12:41:47 +08:00
										 |  |  | 	obj, fsDir, err := prepareFS() | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2018-08-15 12:41:47 +08:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err = newTestConfig(globalMinioDefaultRegion, obj); err != nil { | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 		t.Fatalf("unable initialize config file, %s", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 16:51:56 +08:00
										 |  |  | 	locker := &lockRPCReceiver{ | 
					
						
							| 
									
										
										
										
											2017-06-06 03:25:04 +08:00
										 |  |  | 		ll: localLocker{ | 
					
						
							|  |  |  | 			mutex:           sync.Mutex{}, | 
					
						
							|  |  |  | 			serviceEndpoint: "rpc-path", | 
					
						
							|  |  |  | 			lockMap:         make(map[string][]lockRequesterInfo), | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-30 05:12:47 +08:00
										 |  |  | 	creds := globalServerConfig.GetCredential() | 
					
						
							| 
									
										
										
										
											2017-09-20 03:37:56 +08:00
										 |  |  | 	token, err := authenticateNode(creds.AccessKey, creds.SecretKey) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-08-15 12:41:47 +08:00
										 |  |  | 	return fsDir, locker, token | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Test Lock functionality
 | 
					
						
							|  |  |  | func TestLockRpcServerLock(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-10-11 15:50:27 +08:00
										 |  |  | 	testPath, locker, token := createLockTestServer(t) | 
					
						
							| 
									
										
										
										
											2017-08-13 10:25:43 +08:00
										 |  |  | 	defer os.RemoveAll(testPath) | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 16:51:56 +08:00
										 |  |  | 	la := LockArgs{ | 
					
						
							|  |  |  | 		AuthArgs: AuthArgs{ | 
					
						
							|  |  |  | 			Token:       token, | 
					
						
							|  |  |  | 			RPCVersion:  globalRPCAPIVersion, | 
					
						
							|  |  |  | 			RequestTime: UTCNow(), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		LockArgs: dsync.LockArgs{ | 
					
						
							|  |  |  | 			UID:             "0123-4567", | 
					
						
							|  |  |  | 			Resource:        "name", | 
					
						
							|  |  |  | 			ServerAddr:      "node", | 
					
						
							|  |  |  | 			ServiceEndpoint: "rpc-path", | 
					
						
							|  |  |  | 		}} | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Claim a lock
 | 
					
						
							|  |  |  | 	var result bool | 
					
						
							|  |  |  | 	err := locker.Lock(&la, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", nil, err) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if !result { | 
					
						
							|  |  |  | 			t.Errorf("Expected %#v, got %#v", true, result) | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2017-06-06 03:25:04 +08:00
										 |  |  | 			gotLri, _ := locker.ll.lockMap["name"] | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 			expectedLri := []lockRequesterInfo{ | 
					
						
							| 
									
										
										
										
											2016-10-11 15:50:27 +08:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2017-04-12 01:25:21 +08:00
										 |  |  | 					writer:          true, | 
					
						
							|  |  |  | 					node:            "node", | 
					
						
							|  |  |  | 					serviceEndpoint: "rpc-path", | 
					
						
							|  |  |  | 					uid:             "0123-4567", | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 				}, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if !testLockEquality(expectedLri, gotLri) { | 
					
						
							|  |  |  | 				t.Errorf("Expected %#v, got %#v", expectedLri, gotLri) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Try to claim same lock again (will fail)
 | 
					
						
							| 
									
										
										
										
											2018-06-06 16:51:56 +08:00
										 |  |  | 	la2 := LockArgs{ | 
					
						
							|  |  |  | 		AuthArgs: AuthArgs{ | 
					
						
							|  |  |  | 			Token:       token, | 
					
						
							|  |  |  | 			RPCVersion:  globalRPCAPIVersion, | 
					
						
							|  |  |  | 			RequestTime: UTCNow(), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		LockArgs: dsync.LockArgs{ | 
					
						
							|  |  |  | 			UID:             "89ab-cdef", | 
					
						
							|  |  |  | 			Resource:        "name", | 
					
						
							|  |  |  | 			ServerAddr:      "node", | 
					
						
							|  |  |  | 			ServiceEndpoint: "rpc-path", | 
					
						
							|  |  |  | 		}} | 
					
						
							| 
									
										
										
										
											2016-12-23 23:12:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 	err = locker.Lock(&la2, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", nil, err) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if result { | 
					
						
							|  |  |  | 			t.Errorf("Expected %#v, got %#v", false, result) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Test Unlock functionality
 | 
					
						
							|  |  |  | func TestLockRpcServerUnlock(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-10-11 15:50:27 +08:00
										 |  |  | 	testPath, locker, token := createLockTestServer(t) | 
					
						
							| 
									
										
										
										
											2017-08-13 10:25:43 +08:00
										 |  |  | 	defer os.RemoveAll(testPath) | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 16:51:56 +08:00
										 |  |  | 	la := LockArgs{ | 
					
						
							|  |  |  | 		AuthArgs: AuthArgs{ | 
					
						
							|  |  |  | 			Token:       token, | 
					
						
							|  |  |  | 			RPCVersion:  globalRPCAPIVersion, | 
					
						
							|  |  |  | 			RequestTime: UTCNow(), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		LockArgs: dsync.LockArgs{ | 
					
						
							|  |  |  | 			UID:             "0123-4567", | 
					
						
							|  |  |  | 			Resource:        "name", | 
					
						
							|  |  |  | 			ServerAddr:      "node", | 
					
						
							|  |  |  | 			ServiceEndpoint: "rpc-path", | 
					
						
							|  |  |  | 		}} | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// First test return of error when attempting to unlock a lock that does not exist
 | 
					
						
							|  |  |  | 	var result bool | 
					
						
							|  |  |  | 	err := locker.Unlock(&la, &result) | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected error, got %#v", nil) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create lock (so that we can release)
 | 
					
						
							|  |  |  | 	err = locker.Lock(&la, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", nil, err) | 
					
						
							|  |  |  | 	} else if !result { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", true, result) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Finally test successful release of lock
 | 
					
						
							|  |  |  | 	err = locker.Unlock(&la, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", nil, err) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if !result { | 
					
						
							|  |  |  | 			t.Errorf("Expected %#v, got %#v", true, result) | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2017-06-06 03:25:04 +08:00
										 |  |  | 			gotLri, _ := locker.ll.lockMap["name"] | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 			expectedLri := []lockRequesterInfo(nil) | 
					
						
							|  |  |  | 			if !testLockEquality(expectedLri, gotLri) { | 
					
						
							|  |  |  | 				t.Errorf("Expected %#v, got %#v", expectedLri, gotLri) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Test RLock functionality
 | 
					
						
							|  |  |  | func TestLockRpcServerRLock(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-10-11 15:50:27 +08:00
										 |  |  | 	testPath, locker, token := createLockTestServer(t) | 
					
						
							| 
									
										
										
										
											2017-08-13 10:25:43 +08:00
										 |  |  | 	defer os.RemoveAll(testPath) | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 16:51:56 +08:00
										 |  |  | 	la := LockArgs{ | 
					
						
							|  |  |  | 		AuthArgs: AuthArgs{ | 
					
						
							|  |  |  | 			Token:       token, | 
					
						
							|  |  |  | 			RPCVersion:  globalRPCAPIVersion, | 
					
						
							|  |  |  | 			RequestTime: UTCNow(), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		LockArgs: dsync.LockArgs{ | 
					
						
							|  |  |  | 			UID:             "0123-4567", | 
					
						
							|  |  |  | 			Resource:        "name", | 
					
						
							|  |  |  | 			ServerAddr:      "node", | 
					
						
							|  |  |  | 			ServiceEndpoint: "rpc-path", | 
					
						
							|  |  |  | 		}} | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Claim a lock
 | 
					
						
							|  |  |  | 	var result bool | 
					
						
							|  |  |  | 	err := locker.RLock(&la, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", nil, err) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if !result { | 
					
						
							|  |  |  | 			t.Errorf("Expected %#v, got %#v", true, result) | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2017-06-06 03:25:04 +08:00
										 |  |  | 			gotLri, _ := locker.ll.lockMap["name"] | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 			expectedLri := []lockRequesterInfo{ | 
					
						
							| 
									
										
										
										
											2016-10-11 15:50:27 +08:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2017-04-12 01:25:21 +08:00
										 |  |  | 					writer:          false, | 
					
						
							|  |  |  | 					node:            "node", | 
					
						
							|  |  |  | 					serviceEndpoint: "rpc-path", | 
					
						
							|  |  |  | 					uid:             "0123-4567", | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 				}, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if !testLockEquality(expectedLri, gotLri) { | 
					
						
							|  |  |  | 				t.Errorf("Expected %#v, got %#v", expectedLri, gotLri) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Try to claim same again (will succeed)
 | 
					
						
							| 
									
										
										
										
											2018-06-06 16:51:56 +08:00
										 |  |  | 	la2 := LockArgs{ | 
					
						
							|  |  |  | 		AuthArgs: AuthArgs{ | 
					
						
							|  |  |  | 			Token:       token, | 
					
						
							|  |  |  | 			RPCVersion:  globalRPCAPIVersion, | 
					
						
							|  |  |  | 			RequestTime: UTCNow(), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		LockArgs: dsync.LockArgs{ | 
					
						
							|  |  |  | 			UID:             "89ab-cdef", | 
					
						
							|  |  |  | 			Resource:        "name", | 
					
						
							|  |  |  | 			ServerAddr:      "node", | 
					
						
							|  |  |  | 			ServiceEndpoint: "rpc-path", | 
					
						
							|  |  |  | 		}} | 
					
						
							| 
									
										
										
										
											2016-12-23 23:12:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 	err = locker.RLock(&la2, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", nil, err) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if !result { | 
					
						
							|  |  |  | 			t.Errorf("Expected %#v, got %#v", true, result) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Test RUnlock functionality
 | 
					
						
							|  |  |  | func TestLockRpcServerRUnlock(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-10-11 15:50:27 +08:00
										 |  |  | 	testPath, locker, token := createLockTestServer(t) | 
					
						
							| 
									
										
										
										
											2017-08-13 10:25:43 +08:00
										 |  |  | 	defer os.RemoveAll(testPath) | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 16:51:56 +08:00
										 |  |  | 	la := LockArgs{ | 
					
						
							|  |  |  | 		AuthArgs: AuthArgs{ | 
					
						
							|  |  |  | 			Token:       token, | 
					
						
							|  |  |  | 			RPCVersion:  globalRPCAPIVersion, | 
					
						
							|  |  |  | 			RequestTime: UTCNow(), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		LockArgs: dsync.LockArgs{ | 
					
						
							|  |  |  | 			UID:             "0123-4567", | 
					
						
							|  |  |  | 			Resource:        "name", | 
					
						
							|  |  |  | 			ServerAddr:      "node", | 
					
						
							|  |  |  | 			ServiceEndpoint: "rpc-path", | 
					
						
							|  |  |  | 		}} | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// First test return of error when attempting to unlock a read-lock that does not exist
 | 
					
						
							|  |  |  | 	var result bool | 
					
						
							|  |  |  | 	err := locker.Unlock(&la, &result) | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected error, got %#v", nil) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create first lock ... (so that we can release)
 | 
					
						
							|  |  |  | 	err = locker.RLock(&la, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", nil, err) | 
					
						
							|  |  |  | 	} else if !result { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", true, result) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-23 23:12:19 +08:00
										 |  |  | 	// Try to claim same again (will succeed)
 | 
					
						
							| 
									
										
										
										
											2018-06-06 16:51:56 +08:00
										 |  |  | 	la2 := LockArgs{ | 
					
						
							|  |  |  | 		AuthArgs: AuthArgs{ | 
					
						
							|  |  |  | 			Token:       token, | 
					
						
							|  |  |  | 			RPCVersion:  globalRPCAPIVersion, | 
					
						
							|  |  |  | 			RequestTime: UTCNow(), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		LockArgs: dsync.LockArgs{ | 
					
						
							|  |  |  | 			UID:             "89ab-cdef", | 
					
						
							|  |  |  | 			Resource:        "name", | 
					
						
							|  |  |  | 			ServerAddr:      "node", | 
					
						
							|  |  |  | 			ServiceEndpoint: "rpc-path", | 
					
						
							|  |  |  | 		}} | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// ... and create a second lock on same resource
 | 
					
						
							|  |  |  | 	err = locker.RLock(&la2, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", nil, err) | 
					
						
							|  |  |  | 	} else if !result { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", true, result) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Test successful release of first read lock
 | 
					
						
							|  |  |  | 	err = locker.RUnlock(&la, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", nil, err) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if !result { | 
					
						
							|  |  |  | 			t.Errorf("Expected %#v, got %#v", true, result) | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2017-06-06 03:25:04 +08:00
										 |  |  | 			gotLri, _ := locker.ll.lockMap["name"] | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 			expectedLri := []lockRequesterInfo{ | 
					
						
							| 
									
										
										
										
											2016-10-11 15:50:27 +08:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2017-04-12 01:25:21 +08:00
										 |  |  | 					writer:          false, | 
					
						
							|  |  |  | 					node:            "node", | 
					
						
							|  |  |  | 					serviceEndpoint: "rpc-path", | 
					
						
							|  |  |  | 					uid:             "89ab-cdef", | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 				}, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if !testLockEquality(expectedLri, gotLri) { | 
					
						
							|  |  |  | 				t.Errorf("Expected %#v, got %#v", expectedLri, gotLri) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Finally test successful release of second (and last) read lock
 | 
					
						
							|  |  |  | 	err = locker.RUnlock(&la2, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", nil, err) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if !result { | 
					
						
							|  |  |  | 			t.Errorf("Expected %#v, got %#v", true, result) | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2017-06-06 03:25:04 +08:00
										 |  |  | 			gotLri, _ := locker.ll.lockMap["name"] | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 			expectedLri := []lockRequesterInfo(nil) | 
					
						
							|  |  |  | 			if !testLockEquality(expectedLri, gotLri) { | 
					
						
							|  |  |  | 				t.Errorf("Expected %#v, got %#v", expectedLri, gotLri) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-17 16:53:29 +08:00
										 |  |  | // Test ForceUnlock functionality
 | 
					
						
							|  |  |  | func TestLockRpcServerForceUnlock(t *testing.T) { | 
					
						
							|  |  |  | 	testPath, locker, token := createLockTestServer(t) | 
					
						
							| 
									
										
										
										
											2017-08-13 10:25:43 +08:00
										 |  |  | 	defer os.RemoveAll(testPath) | 
					
						
							| 
									
										
										
										
											2016-10-17 16:53:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 16:51:56 +08:00
										 |  |  | 	laForce := LockArgs{ | 
					
						
							|  |  |  | 		AuthArgs: AuthArgs{ | 
					
						
							|  |  |  | 			Token:       token, | 
					
						
							|  |  |  | 			RPCVersion:  globalRPCAPIVersion, | 
					
						
							|  |  |  | 			RequestTime: UTCNow(), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		LockArgs: dsync.LockArgs{ | 
					
						
							|  |  |  | 			UID:             "1234-5678", | 
					
						
							|  |  |  | 			Resource:        "name", | 
					
						
							|  |  |  | 			ServerAddr:      "node", | 
					
						
							|  |  |  | 			ServiceEndpoint: "rpc-path", | 
					
						
							|  |  |  | 		}} | 
					
						
							| 
									
										
										
										
											2016-10-17 16:53:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// First test that UID should be empty
 | 
					
						
							|  |  |  | 	var result bool | 
					
						
							|  |  |  | 	err := locker.ForceUnlock(&laForce, &result) | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected error, got %#v", nil) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Then test force unlock of a lock that does not exist (not returning an error)
 | 
					
						
							| 
									
										
										
										
											2017-01-09 12:37:53 +08:00
										 |  |  | 	laForce.LockArgs.UID = "" | 
					
						
							| 
									
										
										
										
											2016-10-17 16:53:29 +08:00
										 |  |  | 	err = locker.ForceUnlock(&laForce, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected no error, got %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 16:51:56 +08:00
										 |  |  | 	la := LockArgs{ | 
					
						
							|  |  |  | 		AuthArgs: AuthArgs{ | 
					
						
							|  |  |  | 			Token:       token, | 
					
						
							|  |  |  | 			RPCVersion:  globalRPCAPIVersion, | 
					
						
							|  |  |  | 			RequestTime: UTCNow(), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		LockArgs: dsync.LockArgs{ | 
					
						
							|  |  |  | 			UID:             "0123-4567", | 
					
						
							|  |  |  | 			Resource:        "name", | 
					
						
							|  |  |  | 			ServerAddr:      "node", | 
					
						
							|  |  |  | 			ServiceEndpoint: "rpc-path", | 
					
						
							|  |  |  | 		}} | 
					
						
							| 
									
										
										
										
											2016-10-17 16:53:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Create lock ... (so that we can force unlock)
 | 
					
						
							|  |  |  | 	err = locker.Lock(&la, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", nil, err) | 
					
						
							|  |  |  | 	} else if !result { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", true, result) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Forcefully unlock the lock (not returning an error)
 | 
					
						
							|  |  |  | 	err = locker.ForceUnlock(&laForce, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected no error, got %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Try to get lock again (should be granted)
 | 
					
						
							|  |  |  | 	err = locker.Lock(&la, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", nil, err) | 
					
						
							|  |  |  | 	} else if !result { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", true, result) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Finally forcefully unlock the lock once again
 | 
					
						
							|  |  |  | 	err = locker.ForceUnlock(&laForce, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected no error, got %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | // Test Expired functionality
 | 
					
						
							|  |  |  | func TestLockRpcServerExpired(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-10-11 15:50:27 +08:00
										 |  |  | 	testPath, locker, token := createLockTestServer(t) | 
					
						
							| 
									
										
										
										
											2017-08-13 10:25:43 +08:00
										 |  |  | 	defer os.RemoveAll(testPath) | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 16:51:56 +08:00
										 |  |  | 	la := LockArgs{ | 
					
						
							|  |  |  | 		AuthArgs: AuthArgs{ | 
					
						
							|  |  |  | 			Token:       token, | 
					
						
							|  |  |  | 			RPCVersion:  globalRPCAPIVersion, | 
					
						
							|  |  |  | 			RequestTime: UTCNow(), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		LockArgs: dsync.LockArgs{ | 
					
						
							|  |  |  | 			UID:             "0123-4567", | 
					
						
							|  |  |  | 			Resource:        "name", | 
					
						
							|  |  |  | 			ServerAddr:      "node", | 
					
						
							|  |  |  | 			ServiceEndpoint: "rpc-path", | 
					
						
							|  |  |  | 		}} | 
					
						
							| 
									
										
										
										
											2016-10-11 01:11:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Unknown lock at server will return expired = true
 | 
					
						
							|  |  |  | 	var expired bool | 
					
						
							|  |  |  | 	err := locker.Expired(&la, &expired) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected no error, got %#v", err) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if !expired { | 
					
						
							|  |  |  | 			t.Errorf("Expected %#v, got %#v", true, expired) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create lock (so that we can test that it is not expired)
 | 
					
						
							|  |  |  | 	var result bool | 
					
						
							|  |  |  | 	err = locker.Lock(&la, &result) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", nil, err) | 
					
						
							|  |  |  | 	} else if !result { | 
					
						
							|  |  |  | 		t.Errorf("Expected %#v, got %#v", true, result) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = locker.Expired(&la, &expired) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Errorf("Expected no error, got %#v", err) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if expired { | 
					
						
							|  |  |  | 			t.Errorf("Expected %#v, got %#v", false, expired) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-10-11 15:50:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-23 02:25:10 +08:00
										 |  |  | // Test initialization of lock server.
 | 
					
						
							|  |  |  | func TestLockServerInit(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2017-01-19 04:24:34 +08:00
										 |  |  | 	if runtime.GOOS == globalWindowsOSName { | 
					
						
							| 
									
										
										
										
											2016-10-11 15:50:27 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-23 23:12:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-15 12:41:47 +08:00
										 |  |  | 	obj, fsDir, err := prepareFS() | 
					
						
							| 
									
										
										
										
											2017-06-06 03:25:04 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2018-08-15 12:41:47 +08:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer os.RemoveAll(fsDir) | 
					
						
							|  |  |  | 	if err = newTestConfig(globalMinioDefaultRegion, obj); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("unable initialize config file, %s", err) | 
					
						
							| 
									
										
										
										
											2017-06-06 03:25:04 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-23 23:12:19 +08:00
										 |  |  | 	currentIsDistXL := globalIsDistXL | 
					
						
							| 
									
										
										
										
											2018-01-23 02:25:10 +08:00
										 |  |  | 	currentLockServer := globalLockServer | 
					
						
							| 
									
										
										
										
											2016-12-23 23:12:19 +08:00
										 |  |  | 	defer func() { | 
					
						
							|  |  |  | 		globalIsDistXL = currentIsDistXL | 
					
						
							| 
									
										
										
										
											2018-01-23 02:25:10 +08:00
										 |  |  | 		globalLockServer = currentLockServer | 
					
						
							| 
									
										
										
										
											2016-12-23 23:12:19 +08:00
										 |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-12 06:44:27 +08:00
										 |  |  | 	case1Endpoints := mustGetNewEndpointList( | 
					
						
							|  |  |  | 		"http://localhost:9000/mnt/disk1", | 
					
						
							|  |  |  | 		"http://1.1.1.2:9000/mnt/disk2", | 
					
						
							|  |  |  | 		"http://1.1.2.1:9000/mnt/disk3", | 
					
						
							|  |  |  | 		"http://1.1.2.2:9000/mnt/disk4", | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	for i := range case1Endpoints { | 
					
						
							|  |  |  | 		if case1Endpoints[i].Host == "localhost:9000" { | 
					
						
							|  |  |  | 			case1Endpoints[i].IsLocal = true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case2Endpoints := mustGetNewEndpointList( | 
					
						
							|  |  |  | 		"http://localhost:9000/mnt/disk1", | 
					
						
							|  |  |  | 		"http://localhost:9000/mnt/disk2", | 
					
						
							|  |  |  | 		"http://1.1.2.1:9000/mnt/disk3", | 
					
						
							|  |  |  | 		"http://1.1.2.2:9000/mnt/disk4", | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	for i := range case2Endpoints { | 
					
						
							|  |  |  | 		if case2Endpoints[i].Host == "localhost:9000" { | 
					
						
							|  |  |  | 			case2Endpoints[i].IsLocal = true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-27 18:30:52 +08:00
										 |  |  | 	globalMinioHost = "" | 
					
						
							| 
									
										
										
										
											2016-10-11 15:50:27 +08:00
										 |  |  | 	testCases := []struct { | 
					
						
							| 
									
										
										
										
											2018-01-23 02:25:10 +08:00
										 |  |  | 		isDistXL  bool | 
					
						
							|  |  |  | 		endpoints EndpointList | 
					
						
							| 
									
										
										
										
											2016-10-11 15:50:27 +08:00
										 |  |  | 	}{ | 
					
						
							|  |  |  | 		// Test - 1 one lock server initialized.
 | 
					
						
							| 
									
										
										
										
											2018-01-23 02:25:10 +08:00
										 |  |  | 		{true, case1Endpoints}, | 
					
						
							|  |  |  | 		// Test - similar endpoint hosts should
 | 
					
						
							|  |  |  | 		// converge to single lock server
 | 
					
						
							|  |  |  | 		// initialized.
 | 
					
						
							|  |  |  | 		{true, case2Endpoints}, | 
					
						
							| 
									
										
										
										
											2016-10-11 15:50:27 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validates lock server initialization.
 | 
					
						
							|  |  |  | 	for i, testCase := range testCases { | 
					
						
							| 
									
										
										
										
											2016-11-08 04:09:24 +08:00
										 |  |  | 		globalIsDistXL = testCase.isDistXL | 
					
						
							| 
									
										
										
										
											2018-01-23 02:25:10 +08:00
										 |  |  | 		globalLockServer = nil | 
					
						
							| 
									
										
										
										
											2017-06-06 03:25:04 +08:00
										 |  |  | 		_, _ = newDsyncNodes(testCase.endpoints) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatalf("Got unexpected error initializing lock servers: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-01-23 02:25:10 +08:00
										 |  |  | 		if globalLockServer == nil && testCase.isDistXL { | 
					
						
							| 
									
										
										
										
											2018-06-06 16:51:56 +08:00
										 |  |  | 			t.Errorf("Test %d: Expected initialized lock RPC receiver, but got uninitialized", i+1) | 
					
						
							| 
									
										
										
										
											2016-10-11 15:50:27 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |