1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.client;
19
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.concurrent.CountDownLatch;
23 import java.util.concurrent.TimeUnit;
24 import java.util.concurrent.atomic.AtomicLong;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hadoop.conf.Configuration;
29 import org.apache.hadoop.hbase.HBaseTestingUtility;
30 import org.apache.hadoop.hbase.HConstants;
31 import org.apache.hadoop.hbase.ServerName;
32 import org.apache.hadoop.hbase.TableName;
33 import org.apache.hadoop.hbase.client.backoff.ClientBackoffPolicy;
34 import org.apache.hadoop.hbase.client.backoff.ExponentialClientBackoffPolicy;
35 import org.apache.hadoop.hbase.client.backoff.ServerStatistics;
36 import org.apache.hadoop.hbase.client.coprocessor.Batch;
37 import org.apache.hadoop.hbase.regionserver.HRegion;
38 import org.apache.hadoop.hbase.regionserver.HRegionServer;
39 import org.apache.hadoop.hbase.testclassification.MediumTests;
40 import org.apache.hadoop.hbase.util.Bytes;
41 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
42 import org.junit.AfterClass;
43 import org.junit.BeforeClass;
44 import org.junit.Test;
45 import org.junit.experimental.categories.Category;
46
47 import static org.junit.Assert.assertEquals;
48 import static org.junit.Assert.assertNotEquals;
49 import static org.junit.Assert.assertNotNull;
50 import static org.junit.Assert.assertTrue;
51
52
53
54
55 @Category(MediumTests.class)
56 public class TestClientPushback {
57
58 private static final Log LOG = LogFactory.getLog(TestClientPushback.class);
59 private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
60
61 private static final byte[] tableName = Bytes.toBytes("client-pushback");
62 private static final byte[] family = Bytes.toBytes("f");
63 private static final byte[] qualifier = Bytes.toBytes("q");
64 private static long flushSizeBytes = 1024;
65
66 @BeforeClass
67 public static void setupCluster() throws Exception{
68 Configuration conf = UTIL.getConfiguration();
69
70 conf.setBoolean(HConstants.ENABLE_CLIENT_BACKPRESSURE, true);
71
72 conf.setClass(ClientBackoffPolicy.BACKOFF_POLICY_CLASS, ExponentialClientBackoffPolicy.class,
73 ClientBackoffPolicy.class);
74
75
76 conf.setLong(HConstants.HREGION_MEMSTORE_FLUSH_SIZE, flushSizeBytes);
77
78 conf.setLong("hbase.hregion.memstore.block.multiplier", 2);
79
80 UTIL.startMiniCluster(1);
81 UTIL.createTable(tableName, family);
82 }
83
84 @AfterClass
85 public static void teardownCluster() throws Exception{
86 UTIL.shutdownMiniCluster();
87 }
88
89 @Test(timeout=60000)
90 public void testClientTracksServerPushback() throws Exception{
91 Configuration conf = UTIL.getConfiguration();
92 TableName tablename = TableName.valueOf(tableName);
93
94
95 HConnection conn = HConnectionManager.createConnection(conf);
96 HTable table = (HTable) conn.getTable(tablename);
97
98 HRegionServer rs = UTIL.getHBaseCluster().getRegionServer(0);
99 HRegion region = rs.getOnlineRegions(tablename).get(0);
100
101 LOG.debug("Writing some data to "+tablename);
102
103 Put p = new Put(Bytes.toBytes("row"));
104 p.add(family, qualifier, Bytes.toBytes("value1"));
105 table.put(p);
106 table.flushCommits();
107
108
109 int load = (int)((region.addAndGetGlobalMemstoreSize(0) * 100) / flushSizeBytes);
110 LOG.debug("Done writing some data to "+tablename);
111
112
113 ClientBackoffPolicy backoffPolicy = conn.getBackoffPolicy();
114 assertTrue("Backoff policy is not correctly configured",
115 backoffPolicy instanceof ExponentialClientBackoffPolicy);
116
117 ServerStatisticTracker stats = conn.getStatisticsTracker();
118 assertNotNull( "No stats configured for the client!", stats);
119
120 ServerName server = rs.getServerName();
121 byte[] regionName = region.getRegionName();
122
123
124 ServerStatistics serverStats = stats.getServerStatsForTesting(server);
125 ServerStatistics.RegionStatistics regionStats = serverStats.getStatsForRegion(regionName);
126 assertEquals("We did not find some load on the memstore", load,
127 regionStats.getMemstoreLoadPercent());
128
129
130 long backoffTime = backoffPolicy.getBackoffTime(server, regionName, serverStats);
131 assertNotEquals("Reported load does not produce a backoff", backoffTime, 0);
132 LOG.debug("Backoff calculated for " + region.getRegionNameAsString() + " @ " + server +
133 " is " + backoffTime);
134
135
136
137 List<Row> ops = new ArrayList<Row>(1);
138 p = new Put(Bytes.toBytes("row"));
139 p.add(family, qualifier, Bytes.toBytes("value2"));
140 ops.add(p);
141 final CountDownLatch latch = new CountDownLatch(1);
142 final AtomicLong endTime = new AtomicLong();
143 long startTime = EnvironmentEdgeManager.currentTimeMillis();
144 table.ap.submit(ops, true, new Batch.Callback<Object>() {
145 @Override
146 public void update(byte[] region, byte[] row, Object result) {
147 endTime.set(EnvironmentEdgeManager.currentTimeMillis());
148 latch.countDown();
149 }
150 });
151
152
153
154
155
156 latch.await(backoffTime * 2, TimeUnit.MILLISECONDS);
157 assertNotEquals("AsyncProcess did not submit the work in time", endTime.get(), 0);
158 assertTrue("AsyncProcess did not delay long enough", endTime.get() - startTime >= backoffTime);
159 }
160 }