34 | * A message listener should handle different types of {@code Message}.
35 | *
36 | * @param message the received Message object
37 | * @param context the context delivered to the consume thread
38 | */
39 | void onMessage(Message message, OnMessageContext context);
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/observer/Observer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package io.openmessaging.observer;
19 |
20 | import java.util.Observable;
21 |
22 | /**
23 | * @author vintagewang@apache.org
24 | *
25 | * @version OMS 1.0
26 | * @since OMS 1.0
27 | */
28 | public interface Observer
32 | * The {@link Observable} will not call this method if it calls {@link #onError}.
33 | */
34 | void onCompleted();
35 |
36 | /**
37 | * Notifies the Observer that the {@link Observable} has experienced an error condition.
38 | *
39 | * If the {@link Observable} calls this method, it will not thereafter call
40 | * {@link #onCompleted}.
41 | *
42 | * @param e the exception encountered by the Observable
43 | */
44 | void onError(Throwable e);
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/BytesMessage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package io.openmessaging;
19 |
20 | /**
21 | * The {@code BytesMessage} contains a stream of uninterpreted bytes. It inherits from the {@code Message} interface and
22 | * adds a bytes message body.
23 | *
24 | * The {@code BytesMessage} doesn't know the format or encoding Rules of the body, the provider and consumer decide the
25 | * interpretation of the bytes body.
26 | *
27 | * @author vintagewang@apache.org
28 | * @author yukon@apache.org
29 | *
30 | * @version OMS 1.0
31 | * @since OMS 1.0
32 | */
33 | public interface BytesMessage extends Message {
34 | /**
35 | * Returns the bytes message body.
36 | *
37 | * @return the bytes message body
38 | */
39 | byte[] getBody();
40 |
41 | /**
42 | * Sets the bytes message body.
43 | *
44 | * @param body the message body to be set
45 | */
46 | BytesMessage setBody(final byte[] body);
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/demo/MyLogger.java:
--------------------------------------------------------------------------------
1 | package io.openmessaging.demo;
2 |
3 | import java.io.BufferedWriter;
4 | import java.io.File;
5 | import java.io.IOException;
6 | import java.nio.charset.StandardCharsets;
7 | import java.nio.file.Files;
8 | import java.nio.file.Paths;
9 | import java.nio.file.StandardOpenOption;
10 |
11 | public final class MyLogger {
12 | public static final String ERROR_TAG = "ERROR";
13 | public static final String INFO_TAG = "INFO";
14 |
15 | public static final boolean ENABLE = false;
16 | public static final boolean LOCAL_RUN = false;
17 | private static final String fileName = "E:\\Contest\\阿里中间件2017\\log.txt";
18 | // private static final String fileName = "/home/sfc/jenson/alibaba/2017/log.txt";
19 |
20 | static{
21 | if(ENABLE && LOCAL_RUN) {
22 | File file = new File(fileName);
23 | if(file.exists()) {
24 | file.delete();
25 | }
26 | try {
27 | file.createNewFile();
28 | } catch (IOException e) {
29 | // TODO Auto-generated catch block
30 | e.printStackTrace();
31 | }
32 | }
33 | }
34 | public static synchronized void log(final String tag, final String msg) {
35 | if(!ENABLE) return;
36 | if(!LOCAL_RUN) {
37 | System.out.println(tag+" :"+msg);
38 | return;
39 | }
40 | try(BufferedWriter writer =
41 | Files.newBufferedWriter(Paths.get(fileName),
42 | StandardCharsets.UTF_8, StandardOpenOption.APPEND)) {
43 | writer.write(tag+" : " + msg);
44 | writer.newLine();
45 | //writer.write(tag + msg);
46 | } catch (IOException e) {
47 | // TODO Auto-generated catch block
48 | e.printStackTrace();
49 | }
50 | }
51 |
52 | public static void listAllFiles(final String storePath) {
53 | double totalSizeInMB = 0;
54 | final double div = 1024*1024;
55 | File dir = new File(storePath);
56 | for(final File file : dir.listFiles()) {
57 | double size = file.length() / div;
58 | System.out.println("File:"+file.getName()+" Size:" + size);
59 | totalSizeInMB += size;
60 | }
61 | System.out.println("totalSizeInMB:" + totalSizeInMB);
62 |
63 |
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/demo/MyUtil.java:
--------------------------------------------------------------------------------
1 | package io.openmessaging.demo;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileNotFoundException;
6 | import java.io.FileReader;
7 | import java.io.IOException;
8 | import java.nio.file.Paths;
9 | import java.util.concurrent.ConcurrentHashMap;
10 | import java.util.concurrent.atomic.AtomicInteger;
11 |
12 | // 5/27 增加。用于计算topic queue的hash值
13 | public class MyUtil {
14 | // 保存topic字符串-> topic编号的映射
15 | private static ConcurrentHashMap
27 | * If the service endpoint class implements the {@code ServiceLifecycle} interface, most of the containers can manage
28 | * the lifecycle of the corresponding service endpoint objects easily.
29 | *
30 | * Any service endpoint should support repeated restart if it implements the {@code ServiceLifecycle} interface.
31 | *
32 | * @author vintagewang@apache.org
33 | * @author yukon@apache.org
34 | *
35 | * @version OMS 1.0
36 | * @since OMS 1.0
37 | */
38 | public interface ServiceLifecycle {
39 | /**
40 | * Used for start or initialization of a service endpoint. A service endpoint instance will be in a ready state
41 | * after this method has been completed.
42 | */
43 | @PostConstruct
44 | void start();
45 |
46 | /**
47 | * Notify a service instance of the end of its life cycle. Once this method completes, the service endpoint could be
48 | * destroyed and eligible for garbage collection.
49 | */
50 | @PreDestroy
51 | void shutdown();
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/internal/DefaultKeyValue.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package io.openmessaging.internal;
19 |
20 | import io.openmessaging.KeyValue;
21 | import java.util.Set;
22 |
23 | /**
24 | * WARN: The current interface prohibits direct access by the end user
25 | *
26 | * @version OMS 1.0
27 | * @since OMS 1.0
28 | */
29 | public class DefaultKeyValue implements KeyValue {
30 | @Override
31 | public KeyValue put(String key, int value) {
32 | return null;
33 | }
34 |
35 | @Override
36 | public KeyValue put(String key, long value) {
37 | return null;
38 | }
39 |
40 | @Override
41 | public KeyValue put(String key, double value) {
42 | return null;
43 | }
44 |
45 | @Override
46 | public KeyValue put(String key, String value) {
47 | return null;
48 | }
49 |
50 | @Override
51 | public int getInt(String key) {
52 | return 0;
53 | }
54 |
55 | @Override
56 | public long getLong(String key) {
57 | return 0;
58 | }
59 |
60 | @Override
61 | public double getDouble(String key) {
62 | return 0;
63 | }
64 |
65 | @Override
66 | public String getString(String key) {
67 | return null;
68 | }
69 |
70 | @Override
71 | public Set
25 | * A {@code PartitionConsumer} object supports consume messages from all the partitions of a
26 | * specified queue by streaming way.
27 | *
28 | * @author vintagewang@apache.org
29 | * @author yukon@apache.org
30 | * @version OMS 1.0
31 | * @see MessagingAccessPoint#createPartitionConsumer(String)
32 | * @since OMS 1.0
33 | */
34 | public interface PartitionConsumer {
35 | /**
36 | * Returns the properties of this {@code PartitionConsumer} instance.
37 | * Changes to the return {@code KeyValue} are not reflected in physical {@code PartitionConsumer},
38 | * and use {@link ResourceManager#setConsumerProperties(String, KeyValue)} to modify.
39 | *
40 | * @return the properties
41 | */
42 | KeyValue properties();
43 |
44 | /**
45 | * Fetches the partition list of the specified queue, which related to this {@code PartitionConsumer}
46 | *
47 | * @return the partition list of queue
48 | */
49 | List
54 | * If the specified partition doesn't exist, create it automatically.
55 | *
56 | * @param partitionName the specified partition name
57 | * @return the created {@code PartitionIterator}
58 | */
59 | PartitionIterator partitionIterator(String partitionName);
60 | }
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/MessageFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package io.openmessaging;
19 |
20 | import io.openmessaging.exception.OMSRuntimeException;
21 |
22 | /**
23 | * A factory interface for creating {@code Message} objects.
24 | *
25 | * @author vintagewang@apache.org
26 | * @author yukon@apache.org
27 | */
28 | public interface MessageFactory {
29 | /**
30 | * Creates a {@code BytesMessage} object. A {@code BytesMessage} object is used to send a message containing a
31 | * stream of uninterpreted bytes.
32 | *
33 | * The returned {@code BytesMessage} object only can be sent to the specified topic.
34 | *
35 | * @param topic the target topic to send
36 | * @param body the body data for a message
37 | * @return the created {@code BytesMessage} object
38 | * @throws OMSRuntimeException if the OMS provider fails to create this message due to some internal error.
39 | */
40 | BytesMessage createBytesMessageToTopic(String topic, byte[] body);
41 |
42 | /**
43 | * Creates a {@code BytesMessage} object. A {@code BytesMessage} object is used to send a message containing a
44 | * stream of uninterpreted bytes.
45 | *
46 | * The returned {@code BytesMessage} object only can be sent to the specified queue.
47 | *
48 | * @param queue the target queue to send
49 | * @param body the body data for a message
50 | * @return the created {@code BytesMessage} object
51 | * @throws OMSRuntimeException if the OMS provider fails to create this message due to some internal error.
52 | */
53 | BytesMessage createBytesMessageToQueue(String queue, byte[] body);
54 | }
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
38 | * This method resumes the {@code PushConsumer} instance after it was suspended.
39 | * The instance will not receive new messages between the suspend and resume calls.
40 | *
41 | * @throws OMSRuntimeException if the instance has not been suspended.
42 | * @see PushConsumer#suspend()
43 | */
44 | void resume();
45 |
46 | /**
47 | * Suspends the {@code PushConsumer} for later resumption.
48 | *
49 | * This method suspends the {@code PushConsumer} instance until it is resumed.
50 | * The instance will not receive new messages between the suspend and resume calls.
51 | *
52 | * @throws OMSRuntimeException if the instance is not currently running.
53 | * @see PushConsumer#resume()
54 | */
55 | void suspend();
56 |
57 | /**
58 | * This method is used to find out whether the {@code PushConsumer} is suspended.
59 | *
60 | * @return true if this {@code PushConsumer} is suspended, false otherwise
61 | */
62 | boolean isSuspended();
63 |
64 | /**
65 | * Returns the properties of this {@code PushConsumer} instance.
66 | * Changes to the return {@code KeyValue} are not reflected in physical {@code PushConsumer},
67 | * and use {@link ResourceManager#setConsumerProperties(String, KeyValue)} to modify.
68 | *
69 | * @return the properties
70 | */
71 | KeyValue properties();
72 |
73 | /**
74 | * Attaches the {@code PushConsumer} to a specified queue, with a {@code MessageListener}.
75 | * {@link MessageListener#onMessage(Message, OnMessageContext)} will be called when new
76 | * delivered message is coming.
77 | *
78 | * @param queueName a specified queue
79 | * @param listener a specified listener to receive new message
80 | *
81 | * @throws OMSResourceNotExistException if the specified queue is not exists
82 | */
83 | PushConsumer attachQueue(String queueName, MessageListener listener) throws OMSResourceNotExistException;
84 | }
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/demo/DefaultBytesMessage.java:
--------------------------------------------------------------------------------
1 | package io.openmessaging.demo;
2 |
3 | import io.openmessaging.BytesMessage;
4 | import io.openmessaging.KeyValue;
5 | import io.openmessaging.Message;
6 |
7 |
8 | /**
9 | * 6/2 更新:header部分只存messageId的value,key都不用存;Topic也不用存!
10 | * Property的key:PRO_OFFSET 用1byte表示!
11 | * 一条消息编码为:
12 | * 头部:MSG_HEADER_BEGIN + MSG_ID_LEN(Short)+ MSG_ID
13 | * Property: (KEY_LEN(byte) + key_str + VALUE_LEN (Short) + VALUE_STR)
14 | * ....
15 | * MSG_BODY: MSG_BODY_BEGIN (-3) + MSG_BODY_LEN (Short) + MSG_BODY
16 | */
17 | public class DefaultBytesMessage implements BytesMessage {
18 |
19 | private KeyValue headers = new DefaultKeyValue();
20 | private KeyValue properties;
21 | private byte[] body;
22 | // 表示当前消息是不是表示结束的消息
23 | private boolean endMsg;
24 | public void setEndMsg(boolean flag) {
25 | this.endMsg = flag;
26 | }
27 | public boolean getEndMsg() {
28 | return this.endMsg;
29 | }
30 | public DefaultBytesMessage(byte[] body) {
31 | this.body = body;
32 | }
33 | @Override public byte[] getBody() {
34 | return body;
35 | }
36 |
37 | @Override public BytesMessage setBody(byte[] body) {
38 | this.body = body;
39 | return this;
40 | }
41 |
42 | public void setHeader(DefaultKeyValue hkv) {
43 | this.headers = hkv;
44 | }
45 |
46 | public void setProperty(DefaultKeyValue pkv) {
47 | this.properties = pkv;
48 | }
49 |
50 | @Override public KeyValue headers() {
51 | return headers;
52 | }
53 |
54 | @Override public KeyValue properties() {
55 | return properties;
56 | }
57 |
58 | @Override public Message putHeaders(String key, int value) {
59 | headers.put(key, value);
60 | return this;
61 | }
62 |
63 | @Override public Message putHeaders(String key, long value) {
64 | headers.put(key, value);
65 | return this;
66 | }
67 |
68 | @Override public Message putHeaders(String key, double value) {
69 | headers.put(key, value);
70 | return this;
71 | }
72 |
73 | @Override public Message putHeaders(String key, String value) {
74 | headers.put(key, value);
75 | return this;
76 | }
77 |
78 | @Override public Message putProperties(String key, int value) {
79 | if (properties == null) properties = new DefaultKeyValue();
80 | properties.put(key, value);
81 | return this;
82 | }
83 |
84 | @Override public Message putProperties(String key, long value) {
85 | if (properties == null) properties = new DefaultKeyValue();
86 | properties.put(key, value);
87 | return this;
88 | }
89 |
90 | @Override public Message putProperties(String key, double value) {
91 | if (properties == null) properties = new DefaultKeyValue();
92 | properties.put(key, value);
93 | return this;
94 | }
95 |
96 | @Override public Message putProperties(String key, String value) {
97 | if (properties == null) properties = new DefaultKeyValue();
98 | properties.put(key, value);
99 | return this;
100 | }
101 |
102 | public String toString() {
103 | StringBuilder sb = new StringBuilder();
104 | sb.append("{ headers= ").append(headers.toString()).append(", ");
105 | if(properties != null) {
106 | sb.append("properties= ").append(properties.toString()).append(", ");
107 | }
108 | sb.append("body= ").append(new String(body));
109 | sb.append(" }");
110 | return sb.toString();
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/PartitionIterator.java:
--------------------------------------------------------------------------------
1 | package io.openmessaging;
2 |
3 | import io.openmessaging.exception.OMSRuntimeException;
4 |
5 | /**
6 | * A {@code PartitionIterator} over a partition of queue, created by
7 | * {@link PartitionConsumer#partitionIterator(String)}, supports consume
8 | * messages bilaterally.
9 | *
10 | * @author vintagewang@apache.org
11 | * @author yukon@apache.org
12 | * @version OMS 1.0
13 | * @since OMS 1.0
14 | */
15 | public interface PartitionIterator {
16 | /**
17 | * Fetches the current offset of this partition iterator.
18 | *
19 | * @return the current offset, return -1 if the iterator is first created.
20 | */
21 | long currentOffset();
22 |
23 | /**
24 | * Fetches the first offset of this partition iterator.
25 | *
26 | * @return the first offset, return -1 if the partition has no message.
27 | */
28 | long firstOffset();
29 |
30 | /**
31 | * Fetches the last offset of this partition iterator.
32 | *
33 | * @return the last offset, return 0 if the iterator is first created.
34 | */
35 | long lastOffset();
36 |
37 | /**
38 | * Moves the current offset to the specified timestamp.
39 | *
40 | * Moves the current offset to the first offset, if the given timestamp
41 | * is earlier than the first message's store timestamp in this partition iterator.
42 | *
43 | * Moves the current offset to the last offset, if the given timestamp
44 | * is later than the last message's store timestamp in this partition iterator.
45 | *
46 | * @param timestamp the specified timestamp
47 | */
48 | void seekByTime(long timestamp);
49 |
50 | /**
51 | * Moves the current offset to the specified offset.
52 | *
53 | * @param offset the specified offset
54 | */
55 | void seekByOffset(long offset);
56 |
57 | /**
58 | * Persist this iterator to local or remote server, that depends on specified
59 | * implementation of {@link PartitionConsumer}.
60 | */
61 | void persist();
62 |
63 | /**
64 | * Returns {@code true} if this partition iterator has more messages when
65 | * traversing the iterator in the forward direction.
66 | *
67 | * @return {@code true} if the partition iterator has more messages when
68 | * traversing the iterator in the forward direction
69 | */
70 | boolean hasNext();
71 |
72 | /**
73 | * Returns the next message in the iteration and advances the offset position.
74 | *
75 | * This method may be called repeatedly to iterate through the iteration,
76 | * or intermixed with calls to {@link #previous} to go back and forth.
77 | *
78 | * @return the next message in the list
79 | * @throws OMSRuntimeException if the iteration has no more message
80 | */
81 | Message next();
82 |
83 | /**
84 | * Returns {@code true} if this partition iterator has more messages when
85 | * traversing the iterator in the reverse direction.
86 | *
87 | * @return {@code true} if the partition iterator has more messages when
88 | * traversing the iterator in the reverse direction
89 | */
90 | boolean hasPrevious();
91 |
92 | /**
93 | * Returns the previous message in the iteration and moves the offset
94 | * position backwards.
95 | *
96 | * This method may be called repeatedly to iterate through the iteration backwards,
97 | * or intermixed with calls to {@link #next} to go back and forth.
98 | *
99 | * @return the previous message in the list
100 | * @throws OMSRuntimeException if the iteration has no previous message
101 | */
102 | Message previous();
103 | }
104 |
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/PullConsumer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package io.openmessaging;
19 |
20 | import io.openmessaging.exception.OMSRuntimeException;
21 | import java.util.Collection;
22 |
23 | /**
24 | * A {@code PullConsumer} object can poll messages from the specified queue,
25 | * and supports submit the consume result by acknowledgement.
26 | *
27 | * @author vintagewang@apache.org
28 | * @author yukon@apache.org
29 | * @version OMS 1.0
30 | * @see MessagingAccessPoint#createPullConsumer(String)
31 | * @since OMS 1.0
32 | */
33 | public interface PullConsumer {
34 | /**
35 | * Returns the properties of this {@code PullConsumer} instance.
36 | * Changes to the return {@code KeyValue} are not reflected in physical {@code PullConsumer},
37 | * and use {@link ResourceManager#setConsumerProperties(String, KeyValue)} to modify.
38 | *
39 | * @return the properties
40 | */
41 | KeyValue properties();
42 |
43 | /**
44 | * Polls the next message produced for this {@code PullConsumer}.
45 | *
46 | * This call blocks indefinitely until a message is produced or until this {@code PullConsumer} is shut down.
47 | *
48 | * @return the next message produced for this {@code PullConsumer}, or null if this {@code PullConsumer} is
49 | * concurrently shut down
50 | * @throws OMSRuntimeException if this {@code PullConsumer} fails to pull the next message due to some internal
51 | * error.
52 | */
53 | /**
54 | * 规范要求实现阻塞的接口,由properties来设置阻塞时间,但本赛题不需要用到该特性,请实现一个非阻塞(也即阻塞时间为0)调用, 也即没有消息则返回null
55 | * @return
56 | */
57 | Message poll();
58 |
59 | /**
60 | * Polls the next message produced for this {@code PullConsumer}, using the specified properties.
61 | *
62 | * This call blocks indefinitely until a message is produced or until this {@code PullConsumer} is shut down.
63 | *
64 | * @param properties the specified properties
65 | * @return the next message produced for this {@code PullConsumer}, or null if this {@code PullConsumer} is
66 | * concurrently shut down
67 | * @throws OMSRuntimeException if this {@code PullConsumer} fails to pull the next message due to some internal
68 | * error.
69 | */
70 | Message poll(final KeyValue properties);
71 |
72 | /**
73 | * Acknowledges the specified and consumed message, with unique message id.
74 | *
75 | * Messages that have been received but not acknowledged may be redelivered.
76 | *
77 | * @throws OMSRuntimeException if the consumer fails to acknowledge the messages due to some internal error.
78 | */
79 | void ack(String messageId);
80 |
81 | /**
82 | * Acknowledges the specified and consumed message with the specified properties.
83 | *
84 | * Messages that have been received but not acknowledged may be redelivered.
85 | *
86 | * @throws OMSRuntimeException if the consumer fails to acknowledge the messages due to some internal error.
87 | */
88 | void ack(String messageId, final KeyValue properties);
89 |
90 | /**
91 | * 绑定到一个Queue,并订阅topics,即从这些topic读取消息
92 | * @param queueName
93 | * @param topics
94 | */
95 | void attachQueue(String queueName, Collection
88 | * If the given observer has not been previously registered (i.e. it was
89 | * never added) then this method call is a no-op. If it had been previously
90 | * added then it will be removed. If it had been added more than once, then
91 | * only the first occurrence will be removed.
92 | *
93 | * @param observer The observer to remove
94 | */
95 | void deleteObserver(Observer observer);
96 |
97 | /**
98 | * @return
99 | */
100 | InvokeContext invokeContext();
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/demo/DefaultPullConsumer.java:
--------------------------------------------------------------------------------
1 | package io.openmessaging.demo;
2 |
3 | import io.openmessaging.KeyValue;
4 | import io.openmessaging.Message;
5 | import io.openmessaging.PullConsumer;
6 |
7 | import java.nio.file.Paths;
8 | import java.util.ArrayList;
9 | import java.util.Collection;
10 | import java.util.Collections;
11 | import java.util.Comparator;
12 | import java.util.HashSet;
13 | import java.util.Set;
14 | import java.util.concurrent.ConcurrentHashMap;
15 | import java.util.concurrent.ConcurrentLinkedQueue;
16 | import java.util.concurrent.atomic.AtomicInteger;
17 |
18 | /**
19 | * 按照题目描述,每个线程单独起一个consumer,所以每个consumer应该不用考虑并发
20 | * 5/28 重构:采用push架构
21 | */
22 | public class DefaultPullConsumer implements PullConsumer {
23 | private KeyValue properties;
24 | private String queue;
25 | // buckets里面存的是该consumer绑定到的queue_name和订阅的topics
26 | private Set
44 | * After this method returns, subsequent calls to {@link #isDone} will always return {@code true}. Subsequent calls
45 | * to {@link #isCancelled} will always return {@code true} if this method returned {@code true}.
46 | *
47 | * @param mayInterruptIfRunning {@code true} if the thread executing this task should be interrupted; otherwise,
48 | * in-progress tasks are allowed to complete
49 | * @return {@code false} if the task could not be cancelled, typically because it has already completed normally;
50 | * {@code true} otherwise
51 | */
52 | boolean cancel(boolean mayInterruptIfRunning);
53 |
54 | /**
55 | * Returns {@code true} if this task was cancelled before it completed
56 | * normally.
57 | *
58 | * @return {@code true} if this task was cancelled before it completed
59 | */
60 | boolean isCancelled();
61 |
62 | /**
63 | * Returns {@code true} if this task completed.
64 | *
65 | * Completion may be due to normal termination, an exception, or
66 | * cancellation -- in all of these cases, this method will return
67 | * {@code true}.
68 | *
69 | * @return {@code true} if this task completed
70 | */
71 | boolean isDone();
72 |
73 | /**
74 | * Waits if necessary for the computation to complete, and then
75 | * retrieves its result.
76 | *
77 | * @return the computed result
78 | */
79 | V get();
80 |
81 | /**
82 | * Waits if necessary for at most the given time for the computation
83 | * to complete, and then retrieves its result, if available.
84 | *
85 | * @param timeout the maximum time to wait
86 | * @return the computed result if the computation was cancelled
87 | */
88 | V get(long timeout);
89 |
90 | /**
91 | * Set the value to this promise and mark it completed if set successfully.
92 | *
93 | * @param value Value
94 | * @return Whether set is success
95 | */
96 | boolean set(V value);
97 |
98 | /**
99 | * Adds the specified listener to this promise. The specified listener is notified when this promise is done. If this
100 | * promise is already completed, the specified listener is notified immediately.
101 | *
102 | * @param listener PromiseListener
103 | */
104 | void addListener(PromiseListener listener);
105 |
106 | /**
107 | * @return a throwable caught by the promise
108 | */
109 | Throwable getThrowable();
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/demo/MessageLoad.java:
--------------------------------------------------------------------------------
1 | package io.openmessaging.demo;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.BufferedWriter;
5 | import java.io.File;
6 | import java.io.IOException;
7 | import java.nio.charset.StandardCharsets;
8 | import java.nio.file.Files;
9 | import java.nio.file.Path;
10 | import java.nio.file.Paths;
11 | import java.nio.file.StandardOpenOption;
12 | import java.util.ArrayList;
13 | import java.util.HashMap;
14 | import java.util.HashSet;
15 | import java.util.Set;
16 | import java.util.concurrent.ConcurrentHashMap;
17 | import java.util.concurrent.ConcurrentLinkedQueue;
18 | import java.util.concurrent.CountDownLatch;
19 | import java.util.concurrent.ExecutorService;
20 | import java.util.concurrent.Executors;
21 | import java.util.concurrent.atomic.AtomicInteger;
22 |
23 | import io.openmessaging.Message;
24 | import io.openmessaging.MessageHeader;
25 |
26 | /**
27 | * 单例类,给Consumer使用,用于统计每个topic有多少consumer订阅之类。
28 | * 5/28更新:采用push架构
29 | * @author Jenson
30 | */
31 | public final class MessageLoad {
32 |
33 | private static volatile MessageLoad INSTANCE = null;
34 |
35 | public static MessageLoad getInstance() {
36 | if(INSTANCE == null) {
37 | synchronized (MessageStore.class){
38 | if(INSTANCE == null){
39 | INSTANCE = new MessageLoad();
40 | // 5/24 更新 打一个Log说明是最新版本代码
41 | System.out.println("6/4 8:00更新的代码");
42 | }
43 | }
44 | }
45 | return INSTANCE;
46 | }
47 | // 存储文件的路径
48 | private String filePath = null;
49 | // 保存topicNo对应的消费者
50 | private HashMap
24 | * Most message-oriented middleware (MOM) products treat messages as lightweight entities that consist of a header and a
25 | * body, like Apache RocketMQ. The header contains fields used for message
26 | * routing and identification; the body contains the application data being sent.
27 | *
28 | * The {@code Message} is a lightweight entity that only contains the property related information of a specific message
29 | * object, and the {@code Message} is composed of the following parts:
30 | *
31 | * For example:
24 | * A {@code
25 | * KeyValue} object only allows {@code String} keys and can contain four primitive type as values: {@code int}, {@code
26 | * long}, {@code double}, {@code String}. The {@code KeyValue} is a replacement of {@code Properties}, with simpler
27 | * interfaces and reasonable entry limits. A {@code KeyValue} object may be used in concurrent scenarios, so the
28 | * implementation of {@code KeyValue} should consider concurrent related issues. All the existing entries in {@code
29 | * KeyValue} can't be removed but can be replaced by a new value for the specified key.
30 | *
31 | * @author vintagewang@apache.org
32 | * @author yukon@apache.org
33 | * @version OMS 1.0
34 | * @since OMS 1.0
35 | */
36 | public interface KeyValue {
37 | /**
38 | * Inserts or replaces {@code int} value for the specified key.
39 | *
40 | * @param key the key to be placed into this {@code KeyValue} object
41 | * @param value the value corresponding to key
42 | */
43 | KeyValue put(String key, int value);
44 |
45 | /**
46 | * Inserts or replaces {@code long} value for the specified key.
47 | *
48 | * @param key the key to be placed into this {@code KeyValue} object
49 | * @param value the value corresponding to key
50 | */
51 | KeyValue put(String key, long value);
52 |
53 | /**
54 | * Inserts or replaces {@code double} value for the specified key.
55 | *
56 | * @param key the key to be placed into this {@code KeyValue} object
57 | * @param value the value corresponding to key
58 | */
59 | KeyValue put(String key, double value);
60 |
61 | /**
62 | * Inserts or replaces {@code String} value for the specified key.
63 | *
64 | * @param key the key to be placed into this {@code KeyValue} object
65 | * @param value the value corresponding to key
66 | */
67 | KeyValue put(String key, String value);
68 |
69 | /**
70 | * Searches for the {@code int} property with the specified key in this {@code KeyValue} object.
71 | * If the key is not found in this property list, zero is returned.
72 | *
73 | * @param key the property key
74 | * @return the value in this {@code KeyValue} object with the specified key value
75 | * @throws OMSRuntimeException if the specified {@code key} doesn't exist in this object.
76 | * @see #put(String, int)
77 | */
78 | int getInt(String key);
79 |
80 | /**
81 | * Searches for the {@code long} property with the specified key in this {@code KeyValue} object.
82 | * If the key is not found in this property list, zero is returned.
83 | *
84 | * @param key the property key
85 | * @return the value in this {@code KeyValue} object with the specified key value
86 | * @throws OMSRuntimeException if the specified {@code key} doesn't exist in this object.
87 | * @see #put(String, long)
88 | */
89 | long getLong(String key);
90 |
91 | /**
92 | * Searches for the {@code double} property with the specified key in this {@code KeyValue} object.
93 | * If the key is not found in this property list, zero is returned.
94 | *
95 | * @param key the property key
96 | * @return the value in this {@code KeyValue} object with the specified key value
97 | * @throws OMSRuntimeException if the specified {@code key} doesn't exist in this object.
98 | * @see #put(String, double)
99 | */
100 | double getDouble(String key);
101 |
102 | /**
103 | * Searches for the {@code String} property with the specified key in this {@code KeyValue} object.
104 | * If the key is not found in this property list, {@code null} is returned.
105 | *
106 | * @param key the property key
107 | * @return the value in this {@code KeyValue} object with the specified key value
108 | * @throws OMSRuntimeException if the specified {@code key} doesn't exist in this object.
109 | * @see #put(String, String)
110 | */
111 | String getString(String key);
112 |
113 | /**
114 | * Returns a {@link Set} view of the keys contained in this {@code KeyValue} object.
115 | * The set is independent of this {@code KeyValue} object, like a copy, so changes to the set are
116 | * not reflected in the {@code KeyValue} object, and vice-versa.
117 | *
118 | * @return the key set view of this {@code KeyValue} object.
119 | */
120 | Set
29 | *
30 | * {@link Producer#send(Message)} means send a message to destination synchronously,
31 | * the calling thread will block until the send request complete.
32 | *
33 | * {@link Producer#sendAsync(Message)} means send a message to destination asynchronously,
34 | * the calling thread won't block and will return immediately. Since the send call is asynchronous
35 | * it returns a {@link Promise} for the send result.
36 | *
37 | * {@link Producer#sendOneway(Message)} means send a message to destination in one way,
38 | * the calling thread won't block and will return immediately. The caller won't care about
39 | * the send result, while the server has no responsibility for returning the result.
40 | *
41 | * @author vintagewang@apache.org
42 | * @author yukon@apache.org
43 | *
44 | * @version OMS 1.0
45 | * @since OMS 1.0
46 | */
47 | public interface Producer extends MessageFactory, ServiceLifecycle {
48 | /**
49 | * Returns the properties of this {@code Producer} instance.
50 | * Changes to the return {@code KeyValue} are not reflected in physical {@code Producer},
51 | * and use {@link ResourceManager#setProducerProperties(String, KeyValue)} to modify.
52 | *
53 | * @return the properties
54 | */
55 | KeyValue properties();
56 |
57 | /**
58 | * Sends a message to the specified destination synchronously, the destination should be preset to
59 | * {@link MessageHeader}, other header fields as well.
60 | *
61 | * @param message a message will be sent
62 | * @throws OMSRuntimeException if the {@code Producer} fails to send the message due to some internal error.
63 | */
64 | void send(Message message);
65 |
66 | /**
67 | * Sends a message to the specified destination synchronously, using the specified properties, the destination
68 | * should be preset to {@link MessageHeader}, other header fields as well.
69 | *
70 | * @param message a message will be sent
71 | * @param properties the specified properties
72 | * @throws OMSRuntimeException if the {@code Producer} fails to send the message due to some internal error.
73 | */
74 | void send(Message message, KeyValue properties);
75 |
76 | /**
77 | * 为比赛新增的flush接口,评测线程会最后调用该接口;
78 | * 选手在接口里应该把缓存中的数据写入磁盘或者pagecache
79 | * 在规定时间内,该接口没有返回,producer会被强制杀掉,可能会有数据丢失,从而导致数据不正确;
80 | */
81 | void flush();
82 |
83 | /**
84 | * Sends a message to the specified destination asynchronously, the destination should be preset to
85 | * {@link MessageHeader}, other header fields as well.
86 | *
87 | * The returned {@code Promise} will have the result once the operation completes, and the registered
88 | * {@code PromiseListener} will be notified, either because the operation was successful or because of an error.
89 | *
90 | * @param message a message will be sent
91 | * @return the {@code Promise} of an asynchronous message send operation.
92 | * @see Promise
93 | * @see PromiseListener
94 | */
95 | Promise
101 | * The returned {@code Promise} will have the result once the operation completes, and the registered
102 | * {@code PromiseListener} will be notified, either because the operation was successful or because of an error.
103 | *
104 | * @param message a message will be sent
105 | * @param properties the specified properties
106 | * @return the {@code Promise} of an asynchronous message send operation.
107 | * @see Promise
108 | * @see PromiseListener
109 | */
110 | Promise
116 | * There is no {@code Promise} related or {@code RuntimeException} thrown. The calling thread doesn't
117 | * care about the send result and also have no context to get the result.
118 | *
119 | * @param message a message will be sent
120 | */
121 | void sendOneway(Message message);
122 |
123 | /**
124 | * Sends a message to the specified destination in one way, using the specified properties, the destination
125 | * should be preset to {@link MessageHeader}, other header fields as well.
126 | *
127 | * There is no {@code Promise} related or {@code RuntimeException} thrown. The calling thread doesn't
128 | * care about the send result and also have no context to get the result.
129 | *
130 | * @param message a message will be sent
131 | * @param properties the specified properties
132 | */
133 | void sendOneway(Message message, KeyValue properties);
134 |
135 | BatchToPartition createBatchToPartition(String partitionName);
136 |
137 | BatchToPartition createBatchToPartition(String partitionName, KeyValue properties);
138 | }
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/demo/FileReadCache.java:
--------------------------------------------------------------------------------
1 | package io.openmessaging.demo;
2 |
3 | import java.io.ByteArrayOutputStream;
4 |
5 | import java.io.FileNotFoundException;
6 | import java.io.IOException;
7 | import java.io.RandomAccessFile;
8 | import java.nio.ByteBuffer;
9 | import java.nio.MappedByteBuffer;
10 | import java.nio.channels.FileChannel;
11 | import java.util.HashMap;
12 | import java.util.concurrent.atomic.AtomicInteger;
13 | import java.util.concurrent.locks.ReentrantLock;
14 | import java.util.zip.Inflater;
15 |
16 |
17 | //用于给消息编号
18 | class TopicMsgNO {
19 | int no = 0;
20 | }
21 |
22 | /**
23 | * 每个consumer都有一个FileReadCache,
24 | * 每次Consumer对某个topic进行poll消息,都先通过FileReadCache来读消息;
25 | * 如果FileReadCache缓存有消息,则直接返回,否则从硬盘读一块出来
26 | * 某个topic读完后,重新设置FileReadCache打开新的topic文件即可
27 | * 5/28 Update:采用push架构
28 | * @author Jenson
29 | *
30 | */
31 | public final class FileReadCache {
32 | // 使用数字来替换生产者消息编号
33 | private HashMap
36 | * When a message is sent, MESSAGE_ID is ignored.
37 | *
38 | * When the send method returns it contains a producer-assigned value.
39 | */
40 | public static final String MESSAGE_ID = "MessageId";
41 |
42 | /**
43 | * The {@code TOPIC} header field is the destination which the message is being sent.
44 | *
45 | * When a message is sent this value is should be set properly.
46 | *
47 | * When a message is received, its {@code TOPIC} value must be equivalent to the
48 | * value assigned when it was sent.
49 | */
50 | public static final String TOPIC = "Topic";
51 |
52 | /**
53 | * The {@code QUEUE} header field is the destination which the message is being sent.
54 | *
55 | * When a message is sent this value is should be set properly.
56 | *
57 | * When a message is received, its {@code QUEUE} value must be equivalent to the
58 | * value assigned when it was sent.
59 | */
60 | public static final String QUEUE = "Queue";
61 |
62 | /**
63 | * The {@code BORN_TIMESTAMP} header field contains the time a message was handed
64 | * off to a {@code Producer} to be sent.
65 | *
66 | * When a message is sent, BORN_TIMESTAMP will be set with current timestamp as the born
67 | * timestamp of a message in client side, on return from the send method, the message's
68 | * BORN_TIMESTAMP header field contains this value. When a message is received its
69 | * BORN_TIMESTAMP header field contains this same value.
70 | *
71 | * This filed is a {@code long} value, measured in milliseconds.
72 | */
73 | public static final String BORN_TIMESTAMP = "BornTimestamp";
74 |
75 | /**
76 | * The {@code BORN_HOST} header field contains the born host info of a message in client side.
77 | *
78 | * When a message is sent, BORN_HOST will be set with the local host info,
79 | * on return from the send method, the message's BORN_HOST header field contains this value.
80 | * When a message is received its BORN_HOST header field contains this same value.
81 | */
82 | public static final String BORN_HOST = "BornHost";
83 |
84 | /**
85 | * The {@code STORE_TIMESTAMP} header field contains the store timestamp of a message in server side.
86 | *
87 | * When a message is sent, STORE_TIMESTAMP is ignored.
88 | *
89 | * When the send method returns it contains a server-assigned value.
90 | *
91 | * This filed is a {@code long} value, measured in milliseconds.
92 | */
93 | public static final String STORE_TIMESTAMP = "StoreTimestamp";
94 |
95 | /**
96 | * The {@code STORE_HOST} header field contains the store host info of a message in server side.
97 | *
98 | * When a message is sent, STORE_HOST is ignored.
99 | *
100 | * When the send method returns it contains a server-assigned value.
101 | */
102 | public static final String STORE_HOST = "StoreHost";
103 |
104 | /**
105 | * The {@code START_TIME} header field contains the start timestamp that a message
106 | * can be delivered to consumer client.
107 | *
108 | * If START_TIME field isn't set explicitly, use BORN_TIMESTAMP as the start timestamp.
109 | *
110 | * This filed is a {@code long} value, measured in milliseconds.
111 | */
112 | public static final String START_TIME = "StartTime";
113 |
114 | /**
115 | * The {@code STOP_TIME} header field contains the stop timestamp that a message
116 | * should be discarded after this timestamp, and no consumer can consume this message.
117 | *
118 | * {@code (START_TIME ~ STOP_TIME)} represents a absolute valid interval that a message
119 | * can be delivered in it.
120 | *
121 | * If a earlier timestamp is set than START_TIME, that means the message does not expire.
122 | *
123 | * This filed is a {@code long} value, measured in milliseconds.
124 | *
125 | * When an undelivered message's expiration time is reached, the message should be destroyed.
126 | * OMS does not define a notification of message expiration.
127 | */
128 | public static final String STOP_TIME = "StopTime";
129 |
130 | /**
131 | * The {@code TIMEOUT} header field contains the expiration time, it represents a
132 | * time-to-live value.
133 | *
134 | * {@code (BORN_TIMESTAMP ~ BORN_TIMESTAMP + TIMEOUT)} represents a relative valid interval
135 | * that a message can be delivered in it.
136 | * If the TIMEOUT field is specified as zero, that indicates the message does not expire.
137 | *
138 | * The TIMEOUT header field has higher priority than START_TIME/STOP_TIME header fields.
139 | *
140 | * When an undelivered message's expiration time is reached, the message should be destroyed.
141 | * OMS does not define a notification of message expiration.
142 | */
143 | public static final String TIMEOUT = "Timeout";
144 |
145 | /**
146 | * The {@code PRIORITY} header field contains the priority level of a message,
147 | * a message with higher priority values should be delivered preferentially.
148 | *
149 | * OMS defines a ten level priority value with 0 as the lowest priority and 9 as the highest.
150 | * OMS does not require that a provider strictly implement priority ordering of messages;
151 | * however, it should do its best to deliver expedited messages ahead of normal messages.
152 | *
153 | * If PRIORITY field isn't set explicitly, use {@code 4} as the default priority.
154 | */
155 | public static final String PRIORITY = "Priority";
156 |
157 | /**
158 | * The {@code RELIABILITY} header field contains the reliability level of a message.
159 | * A MOM server should guarantee the reliability level for a message.
160 | */
161 | public static final String RELIABILITY = "Reliability";
162 |
163 | /**
164 | * The {@code SEARCH_KEY} header field contains index search key of a message.
165 | * Clients can query similar messages by search key, and have a quick response.
166 | */
167 | public static final String SEARCH_KEY = "SearchKey";
168 |
169 | /**
170 | * The {@code SCHEDULE_EXPRESSION} header field contains schedule expression of a message.
171 | *
172 | * The message will be delivered by the specified SCHEDULE_EXPRESSION, which is a CRON expression.
173 | *
174 | * @see https://en.wikipedia.org/wiki/Cron#CRON_expression
175 | */
176 | public static final String SCHEDULE_EXPRESSION = "ScheduleExpression";
177 |
178 | /**
179 | * The {@code SHARDING_KEY} header field contains the sharding key a message.
180 | */
181 | public static final String SHARDING_KEY = "ShardingKey";
182 |
183 | /**
184 | * The {@code SHARDING_PARTITION} header field contains the sharding partition key a message.
185 | * The messages with same SHARDING_PARTITION should be sent to the same partition of a destination.
186 | */
187 | public static final String SHARDING_PARTITION = "ShardingPartition";
188 |
189 | /**
190 | * The {@code TRACE_ID} header field contains the trace id a message, which represents a global and unique
191 | * identification, and can be used in distributed system to trace the whole call link.
192 | */
193 | public static final String TRACE_ID = "TraceId";
194 | }
195 |
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/ResourceManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package io.openmessaging;
19 |
20 | import io.openmessaging.exception.OMSResourceNotExistException;
21 | import java.util.List;
22 |
23 | /**
24 | * The {@code ResourceManager} is responsible for providing a unified interface of resource management,
25 | * allows the user to manage the topic, queue, namespace resources.
26 | *
27 | * Create, fetch, update and destroy are the four basic functions of {@code ResourceManager}.
28 | *
29 | * And the {@code ResourceManager} also supports fetch and update resource properties dynamically.
30 | *
31 | * The properties of consumer and producer also are treated as {@code Resource}. {@code ResourceManager}
32 | * allows the user to fetch producer and consumer list in a specified topic or queue,
33 | * and update their resource properties dynamically.
34 | *
35 | * {@link MessagingAccessPoint#createResourceManager()} is the unique method to obtain a {@code ResourceManager}
36 | * instance, any changes made by this instance will reflect to the message-oriented middleware (MOM) or
37 | * other product behind the {@code MessagingAccessPoint}.
38 | *
39 | * @author vintagewang@apache.org
40 | * @author yukon@apache.org
41 | *
42 | * @version OMS 1.0
43 | * @since OMS 1.0
44 | */
45 | public interface ResourceManager extends ServiceLifecycle {
46 | /**
47 | * Creates a {@code Namespace} resource for the specified {@code MessagingAccessPoint} with some preset properties,
48 | * updates if it already exists.
49 | *
50 | * Note that this method will simply create the physical Namespace in the specified {@code MessagingAccessPoint}.
51 | *
52 | * @param nsName a namespace name
53 | * @param properties the preset properties
54 | */
55 | void createAndUpdateNamespace(String nsName, KeyValue properties);
56 |
57 | /**
58 | * Creates a {@code Topic} resource for the specified {@code MessagingAccessPoint} with some preset properties,
59 | * updates if it already exists.
60 | *
61 | * Note that this method will simply create the physical topic in the specified {@code MessagingAccessPoint}.
62 | *
63 | * @param topicName a topic name
64 | * @param properties the preset properties
65 | */
66 | void createAndUpdateTopic(String topicName, KeyValue properties);
67 |
68 | /**
69 | * Creates a {@code Queue} resource for the specified {@code MessagingAccessPoint} with some preset properties,
70 | * updates if it already exists.
71 | *
72 | * Note that this method will simply create the physical queue in the specified {@code MessagingAccessPoint}.
73 | *
74 | * @param queueName a queue name
75 | * @param filter a specified filter
76 | * @param properties the preset properties
77 | */
78 | void createAndUpdateQueue(String queueName, Filters filter, KeyValue properties);
79 |
80 | /**
81 | * Destroys a physical namespace in the specified {@code MessagingAccessPoint}.
82 | *
83 | * All this namespace related physical resources may be deleted immediately.
84 | * @param nsName a namespace name to be destroyed
85 | */
86 | void destroyNamespace(String nsName);
87 |
88 | /**
89 | * Destroys a physical topic in the specified {@code MessagingAccessPoint}.
90 | *
91 | * All this topic related physical resources may be deleted immediately.
92 | * @param topicName a namespace name to be destroyed
93 | */
94 | void destroyTopic(String topicName);
95 |
96 | /**
97 | * Destroys a physical queue in the specified {@code MessagingAccessPoint}.
98 | *
99 | * All this queue related physical resources may be deleted immediately.
100 | * @param queueName a namespace name to be destroyed
101 | */
102 | void destroyQueue(String queueName);
103 |
104 | /**
105 | * Fetches the resource properties of a specified namespace.
106 | *
107 | * @param nsName a namespace name
108 | * @return the properties of this specified namespace
109 | * @throws OMSResourceNotExistException if the specified namespace is not exists
110 | */
111 | KeyValue getNamespaceProperties(String nsName) throws OMSResourceNotExistException;
112 |
113 | /**
114 | * Fetches the resource properties of a specified topic.
115 | *
116 | * @param topicName a topic name
117 | * @return the properties of this specified topic
118 | * @throws OMSResourceNotExistException if the specified topic is not exists
119 | */
120 | KeyValue getTopicProperties(String topicName) throws OMSResourceNotExistException;
121 |
122 | /**
123 | * Fetches the resource properties of a specified queue.
124 | *
125 | * @param queueName a queue name
126 | * @return the properties of this specified queue
127 | * @throws OMSResourceNotExistException if the specified queue is not exists
128 | */
129 | KeyValue getQueueProperties(String queueName) throws OMSResourceNotExistException;
130 |
131 | /**
132 | * Each consumer has a unique id, this method is to fetch the consumer id list in a specified queue.
133 | *
134 | * @param queueName a queue name
135 | * @return the consumer id list in this queue
136 | * @throws OMSResourceNotExistException if the specified queue is not exists
137 | */
138 | List
153 | * The new {@code KeyValue} becomes the current set of consumer properties, and the {@link
154 | * ResourceManager#getConsumerProperties(String)} will observe this change soon. If the argument is null, then the
155 | * current set of consumer properties will stay the same.
156 | *
157 | * @param consumerId the specified consumer id
158 | * @param properties the new consumer properties
159 | * @throws OMSResourceNotExistException if the specified consumer is not exists
160 | */
161 | void setConsumerProperties(String consumerId, KeyValue properties) throws OMSResourceNotExistException;
162 |
163 | /**
164 | * Each producer has a unique id, this method is to fetch the producer id list in a specified queue.
165 | *
166 | * @param queueName a queue name
167 | * @return the producer id list in this queue
168 | * @throws OMSResourceNotExistException if the specified queue is not exists
169 | */
170 | List
194 | * The new {@code KeyValue} becomes the current set of producer properties, and the {@link
195 | * ResourceManager#getProducerProperties(String)} will observe this change soon. If the argument is null, then the
196 | * current set of producer properties will stay the same.
197 | *
198 | * @param producerId the specified producer id
199 | * @param properties the new producer properties
200 | * @throws OMSResourceNotExistException if the specified producer is not exists
201 | */
202 | void setProducerProperties(String producerId, KeyValue properties) throws OMSResourceNotExistException;
203 |
204 | }
205 |
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/demo/DefaultProducer.java:
--------------------------------------------------------------------------------
1 | package io.openmessaging.demo;
2 |
3 | import java.io.BufferedWriter;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.File;
6 | import java.io.FileWriter;
7 | import java.io.IOException;
8 | import java.nio.ByteBuffer;
9 | import java.nio.file.Paths;
10 | import java.util.HashMap;
11 | import java.util.Map;
12 | import java.util.concurrent.BrokenBarrierException;
13 | import java.util.concurrent.ConcurrentHashMap;
14 | import java.util.concurrent.CyclicBarrier;
15 | import java.util.concurrent.atomic.AtomicInteger;
16 | import java.util.zip.Deflater;
17 |
18 | import io.openmessaging.BatchToPartition;
19 | import io.openmessaging.BytesMessage;
20 | import io.openmessaging.KeyValue;
21 | import io.openmessaging.Message;
22 | import io.openmessaging.MessageFactory;
23 | import io.openmessaging.MessageHeader;
24 | import io.openmessaging.Producer;
25 | import io.openmessaging.Promise;
26 |
27 | // 保存cache和对应的pos
28 | class CachePos {
29 | byte[] cache;
30 | // 表示该cache当前写到了哪个位置
31 | int pos;
32 | public CachePos(int size) {
33 | this.cache = new byte[size];
34 | this.pos = 0;
35 | }
36 | }
37 |
38 | public class DefaultProducer implements Producer {
39 | /** 6/2 改消息序列化方式:有些固定出现的字符串可以hardcode */
40 | // 用来统计数目
41 | private static AtomicInteger producerCnt = new AtomicInteger(0);
42 | private final int prodNo;
43 | private MessageFactory messageFactory = null;
44 | private KeyValue properties;
45 | // 用来保存编码后的消息
46 | private ByteBuffer encodedMsg;
47 |
48 | /** 5/26 更新:架构更改,每个producer维护对每个topic文件都维护一个
49 | 自己所写消息的cache
50 | */
51 | private static final int KB_2 = (1<<11);
52 | private static final int[] SIZE_ARRAY = {
53 | // // 2KB 4KB 8KB 16KB 32KB 64KB 128KB
54 | // KB_2, KB_2<<1, KB_2<<2, KB_2<<3, KB_2<<4, KB_2<<5, KB_2<<6,
55 | // 64KB 4KB 8KB 16KB 32KB 64KB 128KB
56 | KB_2<<5, KB_2<<1, KB_2<<2, KB_2<<3, KB_2<<4, KB_2<<5, KB_2<<6,
57 | // 256KB 512KB 1024KB
58 | KB_2<<7, KB_2<<8, KB_2<<9
59 | };
60 |
61 | /** 5/31 更新:Chunk大小用8KB */
62 | private final int CACHE_SIZE;
63 | // 保存某个topic或者queue对应的Cache。cache中保存的是已经序列化好的消息byte[]
64 | private HashMap
32 | *
37 | *
38 | * The body part is placed in the implementation classes of {@code Message}.
39 | *
40 | * @author vintagewang@apache.org
41 | * @author yukon@apache.org
42 | *
43 | * @version OMS 1.0
44 | * @since OMS 1.0
45 | */
46 | public interface Message {
47 | /**
48 | * Returns all the header fields of the {@code Message} object as a {@code KeyValue}.
49 | *
50 | * @return the headers of a {@code Message}
51 | * @see MessageHeader
52 | */
53 | KeyValue headers();
54 |
55 | /**
56 | * Returns all the built-in property fields of the {@code Message} object as a {@code KeyValue}.
57 | *
58 | * @return the properties of a {@code Message}
59 | */
60 | KeyValue properties();
61 |
62 | /**
63 | * Puts a {@code String}-{@code int} {@code KeyValue} entry to he headers of a {@code Message}.
64 | *
65 | * @param key the key to be placed into the headers
66 | * @param value the value corresponding to key
67 | */
68 | Message putHeaders(String key, int value);
69 |
70 | /**
71 | * Puts a {@code String}-{@code long} {@code KeyValue} entry to he headers of a {@code Message}.
72 | *
73 | * @param key the key to be placed into the headers
74 | * @param value the value corresponding to key
75 | */
76 | Message putHeaders(String key, long value);
77 |
78 | /**
79 | * Puts a {@code String}-{@code double} {@code KeyValue} entry to he headers of a {@code Message}.
80 | *
81 | * @param key the key to be placed into the headers
82 | * @param value the value corresponding to key
83 | */
84 | Message putHeaders(String key, double value);
85 |
86 | /**
87 | * Puts a {@code String}-{@code String} {@code KeyValue} entry to he headers of a {@code Message}.
88 | *
89 | * @param key the key to be placed into the headers
90 | * @param value the value corresponding to key
91 | */
92 | Message putHeaders(String key, String value);
93 |
94 | /**
95 | * Puts a {@code String}-{@code int} {@code KeyValue} entry to he headers of a {@code Message}.
96 | *
97 | * @param key the key to be placed into the headers
98 | * @param value the value corresponding to key
99 | */
100 | Message putProperties(String key, int value);
101 |
102 | /**
103 | * Puts a {@code String}-{@code long} {@code KeyValue} entry to he headers of a {@code Message}.
104 | *
105 | * @param key the key to be placed into the headers
106 | * @param value the value corresponding to key
107 | */
108 | Message putProperties(String key, long value);
109 |
110 | /**
111 | * Puts a {@code String}-{@code double} {@code KeyValue} entry to he headers of a {@code Message}.
112 | *
113 | * @param key the key to be placed into the headers
114 | * @param value the value corresponding to key
115 | */
116 | Message putProperties(String key, double value);
117 |
118 | /**
119 | * Puts a {@code String}-{@code String} {@code KeyValue} entry to he headers of a {@code Message}.
120 | *
121 | * @param key the key to be placed into the headers
122 | * @param value the value corresponding to key
123 | */
124 | Message putProperties(String key, String value);
125 | }
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/MessagingAccessPoint.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package io.openmessaging;
19 |
20 | /**
21 | * The {@code MessagingAccessPoint} obtained from {@link MessagingAccessPointManager} is capable of creating {@code
22 | * Producer}, {@code Consumer}, {@code ServiceEndPoint}, and so on.
23 | *
25 | * MessagingAccessPoint messagingAccessPoint = MessagingAccessPointManager.getMessagingAccessPoint("openmessaging:rocketmq://localhost:10911/namespace");
26 | * Producer producer = messagingAccessPoint.createProducer();
27 | * producer.send(producer.createBytesMessageToTopic("HELLO_TOPIC", "HELLO_BODY".getBytes(Charset.forName("UTF-8"))));
28 | *
29 | *
30 | * @author vintagewang@apache.org
31 | * @author yukon@apache.org
32 | *
33 | * @version OMS 1.0
34 | * @since OMS 1.0
35 | */
36 | public interface MessagingAccessPoint extends ServiceLifecycle {
37 | /**
38 | * Creates a new {@code Producer} for the specified {@code MessagingAccessPoint}.
39 | *
40 | * @return the created producer
41 | */
42 | Producer createProducer();
43 |
44 | /**
45 | * Creates a new {@code Producer} for the specified {@code MessagingAccessPoint} with some preset properties.
46 | *
47 | * @param properties the preset properties
48 | * @return the created producer
49 | */
50 | Producer createProducer(KeyValue properties);
51 |
52 | /**
53 | * Creates a new {@code PushConsumer} for the specified {@code MessagingAccessPoint}.
54 | * The returned {@code PushConsumer} isn't attached to any queue,
55 | * uses {@link PushConsumer#attachQueue(String, MessageListener)} to attach queues.
56 | *
57 | * @return the created {@code PushConsumer}
58 | */
59 | PushConsumer createPushConsumer();
60 |
61 | /**
62 | * Creates a new {@code PushConsumer} for the specified {@code MessagingAccessPoint} with some preset properties.
63 | *
64 | * @param properties the preset properties
65 | * @return the created {@code PushConsumer}
66 | */
67 | PushConsumer createPushConsumer(KeyValue properties);
68 |
69 | /**
70 | * Creates a new {@code PullConsumer} for the specified {@code MessagingAccessPoint} with the specified queue.
71 | *
72 | * @param queueName the only attached queue for this {@code PullConsumer}
73 | * @return the created {@code PullConsumer}
74 | */
75 | PullConsumer createPullConsumer(String queueName);
76 |
77 | /**
78 | * Creates a new {@code PullConsumer} for the specified {@code MessagingAccessPoint} with some preset properties.
79 | *
80 | * @param queueName the only attached queue for this {@code PullConsumer}
81 | * @param properties the preset properties
82 | * @return the created {@code PullConsumer}
83 | */
84 | PullConsumer createPullConsumer(String queueName, KeyValue properties);
85 |
86 | /**
87 | * Creates a new {@code PartitionConsumer} for the specified {@code MessagingAccessPoint}.
88 | *
89 | * @param queueName the only attached queue for this {@code PartitionConsumer}
90 | * @return the created {@code PartitionConsumer}
91 | */
92 | PartitionConsumer createPartitionConsumer(String queueName);
93 |
94 | /**
95 | * Creates a new {@code PartitionConsumer} for the specified {@code MessagingAccessPoint} with some preset properties.
96 | *
97 | * @param queueName the only attached queue for this {@code PartitionConsumer}
98 | * @param properties the preset properties
99 | * @return the created consumer
100 | */
101 | PartitionConsumer createPartitionConsumer(String queueName, KeyValue properties);
102 |
103 | /**
104 | * Create a new {@code ResourceManager} for the specified {@code MessagingAccessPoint}.
105 | *
106 | * @return the created {@code ResourceManager}
107 | */
108 | ResourceManager createResourceManager();
109 |
110 | /**
111 | * Create a new {@code Filters} for the specified {@code MessagingAccessPoint}.
112 | *
113 | * @return the created {@code Filters}
114 | */
115 | Filters createFilters();
116 |
117 | /**
118 | * Create a new {@code ServiceEndPoint} for the specified {@code MessagingAccessPoint}.
119 | *
120 | * @return the created {@code ServiceEndPoint}
121 | */
122 | ServiceEndPoint createServiceEndPoint();
123 |
124 | /**
125 | * Create a new {@code ServiceEndPoint} for the specified {@code MessagingAccessPoint} with some preset properties.
126 | *
127 | * @param properties the preset properties
128 | * @return the created {@code ServiceEndPoint}
129 | */
130 | ServiceEndPoint createServiceEndPoint(KeyValue properties);
131 | }
132 |
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/KeyValue.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package io.openmessaging;
19 |
20 | import io.openmessaging.exception.OMSRuntimeException;
21 | import java.util.Set;
22 |
23 | /**
24 | * The {@code KeyValue} class represents a persistent set of properties, which supports method chaining. true if and only if the specified key is in this {@code KeyValue}, false
127 | * otherwise.
128 | */
129 | boolean containsKey(String key);
130 | }
131 |
--------------------------------------------------------------------------------
/src/main/java/io/openmessaging/internal/MessagingAccessPointAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package io.openmessaging.internal;
19 |
20 | import io.openmessaging.KeyValue;
21 | import io.openmessaging.ServiceEndPoint;
22 | import java.lang.reflect.Constructor;
23 | import java.lang.reflect.InvocationTargetException;
24 | import java.util.ArrayList;
25 | import java.util.Arrays;
26 | import java.util.Collections;
27 | import java.util.HashMap;
28 | import java.util.List;
29 | import java.util.Map;
30 | import java.util.Properties;
31 |
32 | /**
33 | * WARN: The current interface prohibits direct access by the end user
34 | *
35 | * @version OMS 1.0
36 | * @since OMS 1.0
37 | */
38 | public class MessagingAccessPointAdapter {
39 | private static final String PROTOCOL_NAME = "protocol";
40 | private static final String SPI_NAME = "spi";
41 | private static final String URL_NAME = "urls";
42 | private static final String URL = "url";
43 | private static final String DEFAULT_SERVICE_END_POINT = "rocketmq";
44 | private static final String DEFAULT_SERVICE_IMPL = "org.apache.rocketmq.openrelay.impl.ServiceEndPointStandardImpl";
45 | private static final String URL_SEPARATOR = ":";
46 | private static final String LIST_SEPARATOR = ",";
47 | private static final String PARAM_SEPARATOR = "&";
48 | private static final String KV_SEPARATOR = "=";
49 | private static Map