Skip to content

Commit

Permalink
fixed repeat lock in LocksTable
Browse files Browse the repository at this point in the history
fixed: #564

Change-Id: I026e4a6739c7f526c421cbb5c90b48e5ff8de066
  • Loading branch information
zhoney committed Jun 13, 2019
1 parent 88f249a commit 0ced5ec
Show file tree
Hide file tree
Showing 3 changed files with 241 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,13 @@ public void lockReads(String group, Collection<Id> locks) {
}
}
this.locks.lockReads(group, newLocks);
locked.addAll(newLocks);
}

// NOTE: when used in multi-threads, should add `synchronized`
public void unlock() {
this.locks.unlock();
this.table.clear();
}

private Set<Id> locksOfGroup(String group) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.baidu.hugegraph.unit.core.DirectionsTest;
import com.baidu.hugegraph.unit.core.EdgeIdTest;
import com.baidu.hugegraph.unit.core.JsonUtilTest;
import com.baidu.hugegraph.unit.core.LocksTableTest;
import com.baidu.hugegraph.unit.core.SerialEnumTest;
import com.baidu.hugegraph.unit.core.StringUtilTest;
import com.baidu.hugegraph.unit.core.VersionTest;
Expand All @@ -58,6 +59,7 @@
AnalyzerTest.class,
JsonUtilTest.class,
StringUtilTest.class,
LocksTableTest.class,

RocksDBSessionsTest.class,
RocksDBCountersTest.class
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
/*
* Copyright 2017 HugeGraph Authors
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You 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 com.baidu.hugegraph.unit.core;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;

import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.id.IdGenerator;
import com.baidu.hugegraph.concurrent.LockManager;
import com.baidu.hugegraph.testutil.Assert;
import com.baidu.hugegraph.testutil.Whitebox;
import com.baidu.hugegraph.unit.BaseUnitTest;
import com.baidu.hugegraph.util.LockUtil;
import com.google.common.collect.ImmutableSet;

public class LocksTableTest extends BaseUnitTest {

private LockUtil.LocksTable locksTable;
private static String GRAPH = "graph";

@BeforeClass
public static void setup() {
LockManager.instance().create(GRAPH + "_" + "group");
LockManager.instance().create(GRAPH + "_" + "group1");
}

@Before
public void initLockTable() {
this.locksTable = new LockUtil.LocksTable(GRAPH);
}

@AfterClass
public static void teardown() {
LockManager.instance().destroy(GRAPH + "_" + "group");
LockManager.instance().destroy(GRAPH + "_" + "group1");
}

@Test
public void testLocksTable() {
this.locksTable.lockReads("group", IdGenerator.of(1));
LockUtil.Locks locks = Whitebox.getInternalState(this.locksTable,
"locks");
Map<String, Set<Id>> table = Whitebox.getInternalState(this.locksTable,
"table");

Assert.assertEquals(1, table.size());
Assert.assertTrue(table.containsKey("group"));
Set<Id> ids = table.get("group");
Assert.assertEquals(1, ids.size());
Assert.assertTrue(ids.contains(IdGenerator.of(1)));

List<Lock> lockList = Whitebox.getInternalState(locks, "lockList");
Assert.assertEquals(1, lockList.size());

this.locksTable.unlock();

Assert.assertEquals(0, table.size());
Assert.assertEquals(0, lockList.size());
}

@Test
public void testLocksTableSameGroupDifferentLocks() {
Id id1 = IdGenerator.of(1);
Id id2 = IdGenerator.of(2);
Id id3 = IdGenerator.of(3);
Id id4 = IdGenerator.of(4);
this.locksTable.lockReads("group", id1);
this.locksTable.lockReads("group", id2);
this.locksTable.lockReads("group", id3);
this.locksTable.lockReads("group", id4);
this.locksTable.lockReads("group", id1);
this.locksTable.lockReads("group", id3);
this.locksTable.lockReads("group", id1);
LockUtil.Locks locks = Whitebox.getInternalState(this.locksTable,
"locks");
Map<String, Set<Id>> table = Whitebox.getInternalState(this.locksTable,
"table");

Assert.assertEquals(1, table.size());
Assert.assertTrue(table.containsKey("group"));
Set<Id> ids = table.get("group");
Assert.assertEquals(4, ids.size());
Set<Id> expect = ImmutableSet.of(id1, id2, id3, id4);
Assert.assertEquals(expect, ids);

List<Lock> lockList = Whitebox.getInternalState(locks, "lockList");
Assert.assertEquals(4, lockList.size());

this.locksTable.unlock();

Assert.assertEquals(0, table.size());
Assert.assertEquals(0, lockList.size());
}

@Test
public void testLocksTableDifferentGroupDifferentLocks() {
Id id1 = IdGenerator.of(1);
Id id2 = IdGenerator.of(2);
Id id3 = IdGenerator.of(3);
Id id4 = IdGenerator.of(4);
this.locksTable.lockReads("group", id1);
this.locksTable.lockReads("group", id2);
this.locksTable.lockReads("group", id3);
this.locksTable.lockReads("group", id4);
this.locksTable.lockReads("group1", id1);
this.locksTable.lockReads("group1", id2);
this.locksTable.lockReads("group1", id1);
LockUtil.Locks locks = Whitebox.getInternalState(this.locksTable,
"locks");
Map<String, Set<Id>> table = Whitebox.getInternalState(this.locksTable,
"table");

Assert.assertEquals(2, table.size());
Assert.assertTrue(table.containsKey("group"));
Assert.assertTrue(table.containsKey("group1"));
Set<Id> ids = table.get("group");
Assert.assertEquals(4, ids.size());
Set<Id> expect = ImmutableSet.of(id1, id2, id3, id4);
Assert.assertEquals(expect, ids);
ids = table.get("group1");
Assert.assertEquals(2, ids.size());
expect = ImmutableSet.of(id1, id2);
Assert.assertEquals(expect, ids);

List<Lock> lockList = Whitebox.getInternalState(locks, "lockList");
Assert.assertEquals(6, lockList.size());

this.locksTable.unlock();

Assert.assertEquals(0, table.size());
Assert.assertEquals(0, lockList.size());
}

@Test
public void testLockTableSameLock1MillionTimes() {
// ReadLock max lock times is 65535, this test ensures that there is no
// repeated locking in LocksTable
Id id = IdGenerator.of(1);
for (int i = 0; i < 1000000; i++) {
this.locksTable.lockReads("group", id);
}
LockUtil.Locks locks = Whitebox.getInternalState(this.locksTable,
"locks");
Map<String, Set<Id>> table = Whitebox.getInternalState(this.locksTable,
"table");

Assert.assertEquals(1, table.size());
Assert.assertTrue(table.containsKey("group"));
Set<Id> ids = table.get("group");
Assert.assertEquals(1, ids.size());
Set<Id> expect = ImmutableSet.of(id);
Assert.assertEquals(expect, ids);

List<Lock> lockList = Whitebox.getInternalState(locks, "lockList");
Assert.assertEquals(1, lockList.size());

this.locksTable.unlock();

Assert.assertEquals(0, table.size());
Assert.assertEquals(0, lockList.size());
}

@Test
public void testLockWithMultiThreads() {
runWithThreads(10, () -> {
LockUtil.LocksTable locksTable = new LockUtil.LocksTable(GRAPH);
for (int i = 0; i < 10000; i++) {
locksTable.lockReads("group", IdGenerator.of(i));
}
LockUtil.Locks locks = Whitebox.getInternalState(locksTable,
"locks");
Map<String, Set<Id>> table = Whitebox.getInternalState(locksTable,
"table");

Assert.assertEquals(1, table.size());
Assert.assertTrue(table.containsKey("group"));
Set<Id> ids = table.get("group");
Assert.assertEquals(10000, ids.size());

List<Lock> lockList = Whitebox.getInternalState(locks, "lockList");
Assert.assertEquals(10000, lockList.size());

locksTable.unlock();
});
}

@Test
public void testSameLockWithMultiThreads() {
Id id = IdGenerator.of(1);
runWithThreads(10, () -> {
LockUtil.LocksTable locksTable = new LockUtil.LocksTable(GRAPH);
for (int i = 0; i < 10000; i++) {
locksTable.lockReads("group", id);
}
LockUtil.Locks locks = Whitebox.getInternalState(locksTable,
"locks");
Map<String, Set<Id>> table = Whitebox.getInternalState(locksTable,
"table");

Assert.assertEquals(1, table.size());
Assert.assertTrue(table.containsKey("group"));
Set<Id> ids = table.get("group");
Assert.assertEquals(1, ids.size());
Set<Id> expect = ImmutableSet.of(id);
Assert.assertEquals(expect, ids);

List<Lock> lockList = Whitebox.getInternalState(locks, "lockList");
Assert.assertEquals(1, lockList.size());
locksTable.unlock();
});
}
}

0 comments on commit 0ced5ec

Please sign in to comment.