Skip to content

Commit

Permalink
LIST support
Browse files Browse the repository at this point in the history
Signed-off-by: Shinya Hayashi <[email protected]>
  • Loading branch information
peng225 committed Feb 12, 2023
1 parent 4d36879 commit 0a4f696
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 116 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ test: $(OVAL)

.PHONY: run
run: $(OVAL)
$(OVAL) --size 4k-16k --time $(EXEC_TIME) --num_obj 1024 --num_worker 4 --bucket "test-bucket,test-bucket2" --endpoint http://localhost:9000 --save test.json
$(OVAL) --size 4k-16k --time $(EXEC_TIME) --num_obj 1024 --num_worker 4 --bucket "test-bucket,test-bucket2" --ope_ratio 8,8,8,1 --endpoint http://localhost:9000 --save test.json
$(OVAL) --time 3s --load test.json

.PHONY: run-multi-process
Expand All @@ -30,7 +30,7 @@ run-multi-process: $(OVAL)

.PHONY: run-leader
run-leader: $(OVAL)
$(OVAL) leader --follower_list "http://localhost:8080,http://localhost:8081,http://localhost:8082" --size 4k-16k --time $(EXEC_TIME) --num_obj 1024 --num_worker 4 --bucket "test-bucket,test-bucket2" --endpoint http://localhost:9000
$(OVAL) leader --follower_list "http://localhost:8080,http://localhost:8081,http://localhost:8082" --size 4k-16k --time $(EXEC_TIME) --num_obj 1024 --num_worker 4 --bucket "test-bucket,test-bucket2" --ope_ratio 8,8,8,1 --endpoint http://localhost:9000

.PHONY: run-followers
run-followers: $(OVAL)
Expand Down
156 changes: 88 additions & 68 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,38 +65,47 @@ Just build and run Oval.
#### Example 1: Success case

```
$ ./oval --size 4k-16k --time 5s --num_obj 1024 --num_worker 4 --bucket "test-bucket,test-bucket2" --endpoint http://localhost:9000 --save test.json
2023/02/10 18:16:52 worker.go:33: Worker ID = 0x10a4, Key = [ov0000000000, ov00000000ff]
2023/02/10 18:16:52 worker.go:33: Worker ID = 0x10a5, Key = [ov0001000000, ov00010000ff]
2023/02/10 18:16:52 worker.go:33: Worker ID = 0x10a6, Key = [ov0002000000, ov00020000ff]
2023/02/10 18:16:52 worker.go:33: Worker ID = 0x10a7, Key = [ov0003000000, ov00030000ff]
2023/02/10 18:16:52 runner.go:151: Validation start.
2023/02/10 18:16:57 runner.go:193: Validation finished.
2023/02/10 18:16:57 stat.go:32: Statistics report.
2023/02/10 18:16:57 stat.go:33: put count: 651
2023/02/10 18:16:57 stat.go:34: get count: 554
2023/02/10 18:16:57 stat.go:35: get (for validation) count: 1237
2023/02/10 18:16:57 stat.go:36: delete count: 579
$ ./oval --size 4k-16k --time 5s --num_obj 1024 --num_worker 4 --bucket "test-bucket,test-bucket2" --endpoint http://localhost:9000
2023/02/12 14:32:01 runner.go:108: Clearing bucket 'test-bucket'.
2023/02/12 14:32:02 runner.go:113: Bucket cleared successfully.
2023/02/12 14:32:02 runner.go:108: Clearing bucket 'test-bucket2'.
2023/02/12 14:32:03 runner.go:113: Bucket cleared successfully.
2023/02/12 14:32:03 worker.go:33: Worker ID = 0x3595, Key = [ov0000000000, ov00000000ff]
2023/02/12 14:32:03 worker.go:33: Worker ID = 0x3596, Key = [ov0001000000, ov00010000ff]
2023/02/12 14:32:03 worker.go:33: Worker ID = 0x3597, Key = [ov0002000000, ov00020000ff]
2023/02/12 14:32:03 worker.go:33: Worker ID = 0x3598, Key = [ov0003000000, ov00030000ff]
2023/02/12 14:32:03 runner.go:153: Validation start.
2023/02/12 14:32:08 runner.go:197: Validation finished.
2023/02/12 14:32:08 stat.go:37: Statistics report.
2023/02/12 14:32:08 stat.go:38: put count: 618
2023/02/12 14:32:08 stat.go:39: get count: 483
2023/02/12 14:32:08 stat.go:40: get (for validation) count: 1140
2023/02/12 14:32:08 stat.go:41: list count: 0
2023/02/12 14:32:08 stat.go:42: delete count: 50
```

#### Example 2: Data corruption case

```
$ ./oval --size 4k-16k --time 5s --num_obj 1024 --num_worker 4 --bucket "test-bucket,test-bucket2" --endpoint http://localhost:9000 --save test.json
2023/02/10 18:23:21 worker.go:33: Worker ID = 0x8817, Key = [ov0000000000, ov00000000ff]
2023/02/10 18:23:21 worker.go:33: Worker ID = 0x8818, Key = [ov0001000000, ov00010000ff]
2023/02/10 18:23:21 worker.go:33: Worker ID = 0x8819, Key = [ov0002000000, ov00020000ff]
2023/02/10 18:23:21 worker.go:33: Worker ID = 0x881a, Key = [ov0003000000, ov00030000ff]
2023/02/10 18:23:21 runner.go:151: Validation start.
2023/02/10 18:23:22 worker.go:101: Data validation error occurred after put.
$ ./oval --size 4k-16k --time 5s --num_obj 1024 --num_worker 4 --bucket "test-bucket,test-bucket2" --endpoint http://localhost:9000
2023/02/12 14:43:46 runner.go:108: Clearing bucket 'test-bucket'.
2023/02/12 14:43:47 runner.go:113: Bucket cleared successfully.
2023/02/12 14:43:47 runner.go:108: Clearing bucket 'test-bucket2'.
2023/02/12 14:43:47 runner.go:113: Bucket cleared successfully.
2023/02/12 14:43:47 worker.go:33: Worker ID = 0x8e14, Key = [ov0000000000, ov00000000ff]
2023/02/12 14:43:47 worker.go:33: Worker ID = 0x8e15, Key = [ov0001000000, ov00010000ff]
2023/02/12 14:43:47 worker.go:33: Worker ID = 0x8e16, Key = [ov0002000000, ov00020000ff]
2023/02/12 14:43:47 worker.go:33: Worker ID = 0x8e17, Key = [ov0003000000, ov00030000ff]
2023/02/12 14:43:47 runner.go:153: Validation start.
2023/02/12 14:43:47 worker.go:101: Data validation error occurred after put.
- WriteCount is wrong. (expected = "2", actual = "1")
- OffsetInObject is wrong. (expected = "0", actual = "256")
00000000 74 65 73 74 2d 62 75 63 6b 65 74 20 20 20 20 20 |test-bucket |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bucket name
00000010 6f 76 30 30 30 30 30 30 30 30 36 62 01 00 00 00 |ov000000006b....|
00000010 6f 76 30 30 30 32 30 30 30 30 32 35 01 00 00 00 |ov0002000025....|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ key name
^^^^^^^^^^^ write count
00000020 00 01 00 00 17 88 00 00 02 59 7f 0c 55 f4 05 00 |.........Y..U...|
00000020 00 01 00 00 16 8e 00 00 67 ea e0 36 7a f4 05 00 |........g..6z...|
^^^^^^^^^^^ byte offset in this object
^^^^^^^^^^^ worker ID
^^^^^^^^^^^^^^^^^^^^^^^ unix time (micro sec)
Expand All @@ -114,13 +123,14 @@ $ ./oval --size 4k-16k --time 5s --num_obj 1024 --num_worker 4 --bucket "test-bu
000000e0 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef |................|
000000f0 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff |................|
2023/02/10 18:23:22 runner.go:193: Validation finished.
2023/02/10 18:23:22 stat.go:32: Statistics report.
2023/02/10 18:23:22 stat.go:33: put count: 128
2023/02/10 18:23:22 stat.go:34: get count: 89
2023/02/10 18:23:22 stat.go:35: get (for validation) count: 225
2023/02/10 18:23:22 stat.go:36: delete count: 97
2023/02/10 18:23:22 root.go:66: r.Run() failed.
2023/02/12 14:43:47 runner.go:197: Validation finished.
2023/02/12 14:43:47 stat.go:37: Statistics report.
2023/02/12 14:43:47 stat.go:38: put count: 23
2023/02/12 14:43:47 stat.go:39: get count: 11
2023/02/12 14:43:47 stat.go:40: get (for validation) count: 30
2023/02/12 14:43:47 stat.go:41: list count: 0
2023/02/12 14:43:47 stat.go:42: delete count: 7
2023/02/12 14:43:47 root.go:66: r.Run() failed.
```

### The multi-process mode
Expand All @@ -135,60 +145,70 @@ $ ./oval --size 4k-16k --time 5s --num_obj 1024 --num_worker 4 --bucket "test-bu

```
$ ./oval follower --follower_port 8080
2023/02/10 18:18:31 follower.go:41: Start server. port = 8080
2023/02/10 18:18:54 follower.go:46: Received a init request.
2023/02/10 18:18:54 follower.go:62: Received a start request.
2023/02/10 18:18:54 follower.go:119: ID: 0
2023/02/10 18:18:54 follower.go:120: Context: {http://localhost:9000 [test-bucket test-bucket2] 1024 4 4096 16384 0 []}
2023/02/10 18:18:54 follower.go:121: OpeRatio: [0.3333333333333333 0.3333333333333333 0.3333333333333333]
2023/02/10 18:18:54 follower.go:122: TimeInMs: 5000
2023/02/10 18:18:54 worker.go:33: Worker ID = 0x368a, Key = [ov0000000000, ov00000000ff]
2023/02/10 18:18:54 worker.go:33: Worker ID = 0x368b, Key = [ov0001000000, ov00010000ff]
2023/02/10 18:18:54 worker.go:33: Worker ID = 0x368c, Key = [ov0002000000, ov00020000ff]
2023/02/10 18:18:54 worker.go:33: Worker ID = 0x368d, Key = [ov0003000000, ov00030000ff]
2023/02/10 18:18:54 runner.go:151: Validation start.
2023/02/10 18:18:59 runner.go:193: Validation finished.
2023/02/10 18:18:59 stat.go:32: Statistics report.
2023/02/10 18:18:59 stat.go:33: put count: 471
2023/02/10 18:18:59 stat.go:34: get count: 436
2023/02/10 18:18:59 stat.go:35: get (for validation) count: 908
2023/02/10 18:18:59 stat.go:36: delete count: 434
2023/02/12 14:41:40 follower.go:41: Start server. port = 8080
2023/02/12 14:41:53 follower.go:46: Received a init request.
2023/02/12 14:41:53 follower.go:62: Received a start request.
2023/02/12 14:41:53 follower.go:119: ID: 0
2023/02/12 14:41:53 follower.go:120: Context: {http://localhost:9000 [test-bucket test-bucket2] 1024 4 4096 16384 0 []}
2023/02/12 14:41:53 follower.go:121: OpeRatio: [0.3333333333333333 0.3333333333333333 0.3333333333333333 0]
2023/02/12 14:41:53 follower.go:122: TimeInMs: 5000
2023/02/12 14:41:53 runner.go:108: Clearing bucket 'test-bucket'.
2023/02/12 14:41:53 runner.go:113: Bucket cleared successfully.
2023/02/12 14:41:53 runner.go:108: Clearing bucket 'test-bucket2'.
2023/02/12 14:41:53 runner.go:113: Bucket cleared successfully.
2023/02/12 14:41:53 worker.go:33: Worker ID = 0x7ea7, Key = [ov0000000000, ov00000000ff]
2023/02/12 14:41:53 worker.go:33: Worker ID = 0x7ea8, Key = [ov0001000000, ov00010000ff]
2023/02/12 14:41:53 worker.go:33: Worker ID = 0x7ea9, Key = [ov0002000000, ov00020000ff]
2023/02/12 14:41:53 worker.go:33: Worker ID = 0x7eaa, Key = [ov0003000000, ov00030000ff]
2023/02/12 14:41:53 runner.go:153: Validation start.
2023/02/12 14:41:58 runner.go:197: Validation finished.
2023/02/12 14:41:58 stat.go:37: Statistics report.
2023/02/12 14:41:58 stat.go:38: put count: 479
2023/02/12 14:41:58 stat.go:39: get count: 402
2023/02/12 14:41:58 stat.go:40: get (for validation) count: 872
2023/02/12 14:41:58 stat.go:41: list count: 0
2023/02/12 14:41:58 stat.go:42: delete count: 383
```

##### follower2

```
$ ./oval follower --follower_port 8081
2023/02/10 18:18:41 follower.go:41: Start server. port = 8081
2023/02/10 18:18:54 follower.go:46: Received a init request.
2023/02/10 18:18:54 follower.go:62: Received a start request.
2023/02/10 18:18:54 follower.go:119: ID: 1
2023/02/10 18:18:54 follower.go:120: Context: {http://localhost:9000 [test-bucket test-bucket2] 1024 4 4096 16384 0 []}
2023/02/10 18:18:54 follower.go:121: OpeRatio: [0.3333333333333333 0.3333333333333333 0.3333333333333333]
2023/02/10 18:18:54 follower.go:122: TimeInMs: 5000
2023/02/10 18:18:54 worker.go:33: Worker ID = 0xb236, Key = [ov0100000000, ov01000000ff]
2023/02/10 18:18:54 worker.go:33: Worker ID = 0xb237, Key = [ov0101000000, ov01010000ff]
2023/02/10 18:18:54 worker.go:33: Worker ID = 0xb238, Key = [ov0102000000, ov01020000ff]
2023/02/10 18:18:54 worker.go:33: Worker ID = 0xb239, Key = [ov0103000000, ov01030000ff]
2023/02/10 18:18:54 runner.go:151: Validation start.
2023/02/10 18:18:59 runner.go:193: Validation finished.
2023/02/10 18:18:59 stat.go:32: Statistics report.
2023/02/10 18:18:59 stat.go:33: put count: 463
2023/02/10 18:18:59 stat.go:34: get count: 407
2023/02/10 18:18:59 stat.go:35: get (for validation) count: 896
2023/02/10 18:18:59 stat.go:36: delete count: 431
2023/02/12 14:41:45 follower.go:41: Start server. port = 8081
2023/02/12 14:41:53 follower.go:46: Received a init request.
2023/02/12 14:41:53 follower.go:62: Received a start request.
2023/02/12 14:41:53 follower.go:119: ID: 1
2023/02/12 14:41:53 follower.go:120: Context: {http://localhost:9000 [test-bucket test-bucket2] 1024 4 4096 16384 0 []}
2023/02/12 14:41:53 follower.go:121: OpeRatio: [0.3333333333333333 0.3333333333333333 0.3333333333333333 0]
2023/02/12 14:41:53 follower.go:122: TimeInMs: 5000
2023/02/12 14:41:53 runner.go:108: Clearing bucket 'test-bucket'.
2023/02/12 14:41:53 runner.go:113: Bucket cleared successfully.
2023/02/12 14:41:53 runner.go:108: Clearing bucket 'test-bucket2'.
2023/02/12 14:41:53 runner.go:113: Bucket cleared successfully.
2023/02/12 14:41:53 worker.go:33: Worker ID = 0x5803, Key = [ov0100000000, ov01000000ff]
2023/02/12 14:41:53 worker.go:33: Worker ID = 0x5804, Key = [ov0101000000, ov01010000ff]
2023/02/12 14:41:53 worker.go:33: Worker ID = 0x5805, Key = [ov0102000000, ov01020000ff]
2023/02/12 14:41:53 worker.go:33: Worker ID = 0x5806, Key = [ov0103000000, ov01030000ff]
2023/02/12 14:41:53 runner.go:153: Validation start.
2023/02/12 14:41:58 runner.go:197: Validation finished.
2023/02/12 14:41:58 stat.go:37: Statistics report.
2023/02/12 14:41:58 stat.go:38: put count: 488
2023/02/12 14:41:58 stat.go:39: get count: 430
2023/02/12 14:41:58 stat.go:40: get (for validation) count: 892
2023/02/12 14:41:58 stat.go:41: list count: 0
2023/02/12 14:41:58 stat.go:42: delete count: 392
```

##### leader

```
$ ./oval leader --follower_list "http://localhost:8080,http://localhost:8081" --size 4k-16k --time 5s --num_obj 1024 --num_worker 4 --bucket "test-bucket,test-bucket2" --endpoint http://localhost:9000
2023/02/10 18:18:54 leader.go:31: Sent start requests to all followers.
2023/02/10 18:18:59 leader.go:37: The report from followers:
follower: http://localhost:8081
OK
2023/02/12 14:41:53 leader.go:31: Sent start requests to all followers.
2023/02/12 14:41:58 leader.go:37: The report from followers:
follower: http://localhost:8080
OK
follower: http://localhost:8081
OK
```

## Execution mode
Expand Down
14 changes: 7 additions & 7 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
)

var (
numObj int64
numObj int
numWorker int
sizePattern string
execTime time.Duration
Expand Down Expand Up @@ -122,13 +122,13 @@ func handleCommonFlags() {
log.Fatal("The number of objects must be less than 16777216.")
}

if numObj < int64(numWorker) {
log.Fatal("The number of objects must be larger or equal to the number of workers.")
if numObj < numWorker {
log.Fatal("The number of objects must be larger than or equal to the number of workers.")
}

if numObj%int64(numWorker) != 0 {
if numObj%numWorker != 0 {
log.Printf("warning: The number of objects (%d) is not divisible by the number of workers (%d). Only %d objects will be used.\n",
numObj, numWorker, numObj/int64(numWorker*numWorker))
numObj, numWorker, numObj/numWorker*numWorker)
}

execContext = &runner.ExecutionContext{
Expand All @@ -142,11 +142,11 @@ func handleCommonFlags() {
}

func defineCommonFlags(cmd *cobra.Command) {
cmd.Flags().Int64Var(&numObj, "num_obj", 10, "The maximum number of objects.")
cmd.Flags().IntVar(&numObj, "num_obj", 10, "The maximum number of objects per process.")
cmd.Flags().IntVar(&numWorker, "num_worker", 1, "The number of workers per process.")
cmd.Flags().StringVar(&sizePattern, "size", "4k", "The size of object. Should be in the form like \"8k\" or \"4k-2m\". The unit \"g\" or \"G\" is not allowed.")
cmd.Flags().DurationVar(&execTime, "time", time.Second*3, "Time duration for run the workload.")
cmd.Flags().StringSliceVar(&bucketNames, "bucket", nil, "The name list of the buckets. e.g. \"bucket1,bucket2\"")
cmd.Flags().StringVar(&opeRatioStr, "ope_ratio", "1,1,1", "The ration of put, get and delete operations. e.g. \"2,3,1\"")
cmd.Flags().StringVar(&opeRatioStr, "ope_ratio", "1,1,1,0", "The ration of put, get, delete and list operations. e.g. \"2,3,1,1\"")
cmd.Flags().StringVar(&endpoint, "endpoint", "", "The endpoint URL and TCP port number. e.g. \"http://127.0.0.1:9000\"")
}
16 changes: 10 additions & 6 deletions object/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import (
const (
MaxBucketNameLength = 16
MaxKeyLength = 12
KeyPrefix = "ov"
KeyShortPrefix = "ov"
// len(KeyShortPrefix) + 2 (for process ID) + 2 (for worker ID)
KeyPrefixLength = 6
)

type Object struct {
Expand All @@ -24,6 +26,7 @@ type ObjectMeta struct {
ObjectList []Object `json:"objectList"`
ExistingObjectIDs []int64 `json:"existingObjectIDs"`
KeyIDOffset int64 `json:"keyIDOffset"`
KeyPrefix string
}

func (obj *Object) Clear() {
Expand All @@ -40,17 +43,18 @@ func NewObject(objID int64) *Object {
}

func generateKey(objID int64) string {
return fmt.Sprintf("%s%010x", KeyPrefix, objID)
return fmt.Sprintf("%s%010x", KeyShortPrefix, objID)
}

func NewObjectMeta(numObj, keyIDOffset int64) *ObjectMeta {
func NewObjectMeta(numObj int, keyIDOffset int64) *ObjectMeta {
om := &ObjectMeta{}
om.ObjectList = make([]Object, numObj)
for objID := int64(0); objID < numObj; objID++ {
om.ObjectList[objID] = *NewObject(keyIDOffset + objID)
for objID := 0; objID < numObj; objID++ {
om.ObjectList[objID] = *NewObject(keyIDOffset + int64(objID))
}
om.ExistingObjectIDs = make([]int64, 0, int(math.Sqrt(float64(numObj))))
om.KeyIDOffset = keyIDOffset
om.KeyPrefix = generateKey(keyIDOffset)[:KeyPrefixLength]

return om
}
Expand All @@ -62,7 +66,7 @@ func (om *ObjectMeta) GetRandomObject() *Object {

// Caution: this function should be called while the object lock is acquired.
func (om *ObjectMeta) RegisterToExistingList(key string) {
objID, err := strconv.ParseInt(key[len(KeyPrefix):], 16, 64)
objID, err := strconv.ParseInt(key[len(KeyShortPrefix):], 16, 64)
if err != nil {
log.Fatal(err)
}
Expand Down
13 changes: 9 additions & 4 deletions runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const (
type ExecutionContext struct {
Endpoint string `json:"endpoint"`
BucketNames []string `json:"bucketNames"`
NumObj int64 `json:"numObj"`
NumObj int `json:"numObj"`
NumWorker int `json:"numWorker"`
MinSize int `json:"minSize"`
MaxSize int `json:"maxSize"`
Expand Down Expand Up @@ -129,8 +129,8 @@ func (r *Runner) init() {
r.execContext.Workers[i].BucketsWithObject[j] = &BucketWithObject{
BucketName: bucketName,
ObjectMata: object.NewObjectMeta(
r.execContext.NumObj/int64(r.execContext.NumWorker),
(int64(i)<<24)+(int64(r.processID)<<32)),
r.execContext.NumObj/r.execContext.NumWorker,
(int64(r.processID)<<32)+(int64(i)<<24)),
}
}
r.execContext.Workers[i].client = r.client
Expand Down Expand Up @@ -182,6 +182,8 @@ func (r *Runner) Run(cancel chan struct{}) error {
err = r.execContext.Workers[workerID].Get()
case Delete:
err = r.execContext.Workers[workerID].Delete()
case List:
err = r.execContext.Workers[workerID].List()
}
if err != nil {
errCh <- err
Expand Down Expand Up @@ -211,6 +213,7 @@ const (
Put Operation = iota
Get
Delete
List
NumOperation
)

Expand All @@ -221,8 +224,10 @@ func (r *Runner) selectOperation() Operation {
return Put
} else if randVal < r.opeRatio[0]+r.opeRatio[1] {
return Get
} else {
} else if randVal < r.opeRatio[0]+r.opeRatio[1]+r.opeRatio[2] {
return Delete
} else {
return List
}
}

Expand Down
Loading

0 comments on commit 0a4f696

Please sign in to comment.