|
18 | 18 | package org.apache.rocketmq.store;
|
19 | 19 |
|
20 | 20 | import java.io.File;
|
| 21 | +import java.io.RandomAccessFile; |
21 | 22 | import java.net.InetAddress;
|
22 | 23 | import java.net.InetSocketAddress;
|
23 | 24 | import java.net.SocketAddress;
|
| 25 | +import java.nio.MappedByteBuffer; |
| 26 | +import java.nio.channels.FileChannel; |
24 | 27 | import java.nio.channels.OverlappingFileLockException;
|
25 | 28 | import java.util.Map;
|
26 | 29 | import java.util.concurrent.atomic.AtomicInteger;
|
|
29 | 32 | import org.apache.rocketmq.common.UtilAll;
|
30 | 33 | import org.apache.rocketmq.store.config.FlushDiskType;
|
31 | 34 | import org.apache.rocketmq.store.config.MessageStoreConfig;
|
| 35 | +import org.apache.rocketmq.store.config.StorePathConfigHelper; |
32 | 36 | import org.junit.After;
|
33 | 37 | import org.apache.rocketmq.store.stats.BrokerStatsManager;
|
34 | 38 | import org.junit.Before;
|
@@ -171,6 +175,120 @@ public void testPullSize() throws Exception {
|
171 | 175 | assertThat(getMessageResult45.getMessageBufferList().size()).isEqualTo(10);
|
172 | 176 | }
|
173 | 177 |
|
| 178 | + @Test |
| 179 | + public void testRecover() throws Exception { |
| 180 | + String topic = "recoverTopic"; |
| 181 | + MessageBody = StoreMessage.getBytes(); |
| 182 | + for (int i = 0; i < 100; i++) { |
| 183 | + MessageExtBrokerInner messageExtBrokerInner = buildMessage(); |
| 184 | + messageExtBrokerInner.setTopic(topic); |
| 185 | + messageExtBrokerInner.setQueueId(0); |
| 186 | + messageStore.putMessage(messageExtBrokerInner); |
| 187 | + } |
| 188 | + |
| 189 | + Thread.sleep(100);//wait for build consumer queue |
| 190 | + long maxPhyOffset = messageStore.getMaxPhyOffset(); |
| 191 | + long maxCqOffset = messageStore.getMaxOffsetInQueue(topic, 0); |
| 192 | + |
| 193 | + //1.just reboot |
| 194 | + messageStore.shutdown(); |
| 195 | + messageStore = buildMessageStore(); |
| 196 | + boolean load = messageStore.load(); |
| 197 | + assertTrue(load); |
| 198 | + messageStore.start(); |
| 199 | + assertTrue(maxPhyOffset == messageStore.getMaxPhyOffset()); |
| 200 | + assertTrue(maxCqOffset == messageStore.getMaxOffsetInQueue(topic, 0)); |
| 201 | + |
| 202 | + //2.damage commitlog and reboot normal |
| 203 | + for (int i = 0; i < 100; i++) { |
| 204 | + MessageExtBrokerInner messageExtBrokerInner = buildMessage(); |
| 205 | + messageExtBrokerInner.setTopic(topic); |
| 206 | + messageExtBrokerInner.setQueueId(0); |
| 207 | + messageStore.putMessage(messageExtBrokerInner); |
| 208 | + } |
| 209 | + Thread.sleep(100); |
| 210 | + long secondLastPhyOffset = messageStore.getMaxPhyOffset(); |
| 211 | + long secondLastCqOffset = messageStore.getMaxOffsetInQueue(topic, 0); |
| 212 | + |
| 213 | + MessageExtBrokerInner messageExtBrokerInner = buildMessage(); |
| 214 | + messageExtBrokerInner.setTopic(topic); |
| 215 | + messageExtBrokerInner.setQueueId(0); |
| 216 | + messageStore.putMessage(messageExtBrokerInner); |
| 217 | + |
| 218 | + messageStore.shutdown(); |
| 219 | + |
| 220 | + //damage last message |
| 221 | + damageCommitlog(secondLastPhyOffset); |
| 222 | + |
| 223 | + //reboot |
| 224 | + messageStore = buildMessageStore(); |
| 225 | + load = messageStore.load(); |
| 226 | + assertTrue(load); |
| 227 | + messageStore.start(); |
| 228 | + assertTrue(secondLastPhyOffset == messageStore.getMaxPhyOffset()); |
| 229 | + assertTrue(secondLastCqOffset == messageStore.getMaxOffsetInQueue(topic, 0)); |
| 230 | + |
| 231 | + //3.damage commitlog and reboot abnormal |
| 232 | + for (int i = 0; i < 100; i++) { |
| 233 | + messageExtBrokerInner = buildMessage(); |
| 234 | + messageExtBrokerInner.setTopic(topic); |
| 235 | + messageExtBrokerInner.setQueueId(0); |
| 236 | + messageStore.putMessage(messageExtBrokerInner); |
| 237 | + } |
| 238 | + Thread.sleep(100); |
| 239 | + secondLastPhyOffset = messageStore.getMaxPhyOffset(); |
| 240 | + secondLastCqOffset = messageStore.getMaxOffsetInQueue(topic, 0); |
| 241 | + |
| 242 | + messageExtBrokerInner = buildMessage(); |
| 243 | + messageExtBrokerInner.setTopic(topic); |
| 244 | + messageExtBrokerInner.setQueueId(0); |
| 245 | + messageStore.putMessage(messageExtBrokerInner); |
| 246 | + messageStore.shutdown(); |
| 247 | + |
| 248 | + //damage last message |
| 249 | + damageCommitlog(secondLastPhyOffset); |
| 250 | + //add abort file |
| 251 | + String fileName = StorePathConfigHelper.getAbortFile(((DefaultMessageStore) messageStore).getMessageStoreConfig().getStorePathRootDir()); |
| 252 | + File file = new File(fileName); |
| 253 | + MappedFile.ensureDirOK(file.getParent()); |
| 254 | + file.createNewFile(); |
| 255 | + |
| 256 | + messageStore = buildMessageStore(); |
| 257 | + load = messageStore.load(); |
| 258 | + assertTrue(load); |
| 259 | + messageStore.start(); |
| 260 | + assertTrue(secondLastPhyOffset == messageStore.getMaxPhyOffset()); |
| 261 | + assertTrue(secondLastCqOffset == messageStore.getMaxOffsetInQueue(topic, 0)); |
| 262 | + |
| 263 | + //message write again |
| 264 | + for (int i = 0; i < 100; i++) { |
| 265 | + messageExtBrokerInner = buildMessage(); |
| 266 | + messageExtBrokerInner.setTopic(topic); |
| 267 | + messageExtBrokerInner.setQueueId(0); |
| 268 | + messageStore.putMessage(messageExtBrokerInner); |
| 269 | + } |
| 270 | + } |
| 271 | + |
| 272 | + private void damageCommitlog(long offset) throws Exception { |
| 273 | + MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); |
| 274 | + File file = new File(messageStoreConfig.getStorePathCommitLog() + File.separator + "00000000000000000000"); |
| 275 | + |
| 276 | + FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel(); |
| 277 | + MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 1024 * 1024 * 10); |
| 278 | + |
| 279 | + int bodyLen = mappedByteBuffer.getInt((int) offset + 84); |
| 280 | + int topicLenIndex = (int) offset + 84 + bodyLen + 4; |
| 281 | + mappedByteBuffer.position(topicLenIndex); |
| 282 | + mappedByteBuffer.putInt(0); |
| 283 | + mappedByteBuffer.putInt(0); |
| 284 | + mappedByteBuffer.putInt(0); |
| 285 | + mappedByteBuffer.putInt(0); |
| 286 | + |
| 287 | + mappedByteBuffer.force(); |
| 288 | + fileChannel.force(true); |
| 289 | + fileChannel.close(); |
| 290 | + } |
| 291 | + |
174 | 292 | private class MyMessageArrivingListener implements MessageArrivingListener {
|
175 | 293 | @Override
|
176 | 294 | public void arriving(String topic, int queueId, long logicOffset, long tagsCode, long msgStoreTime,
|
|
0 commit comments