Motr  M0
lq.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2016-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * 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  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
29 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_UT
30 #include "lib/trace.h"
31 
32 #include "ha/lq.h"
33 #include "ut/ut.h"
34 
35 #include "lib/memory.h" /* M0_ALLOC_PTR */
36 #include "fid/fid.h" /* M0_FID */
37 #include "ha/msg.h" /* m0_ha_msg */
38 #include "ha/link.h" /* m0_ha_link_tags_initial */
39 
40 void m0_ha_ut_lq(void)
41 {
42  struct m0_ha_link_tags tags;
43  struct m0_ha_lq_cfg lq_cfg;
44  struct m0_ha_msg *msg;
45  struct m0_ha_msg *msg2;
46  struct m0_ha_lq *lq;
47  uint64_t tag;
48  uint64_t tag2;
49  bool success;
50 
51  M0_ALLOC_PTR(lq);
52  M0_UT_ASSERT(lq != NULL);
53  M0_ALLOC_PTR(msg);
54  M0_UT_ASSERT(msg != NULL);
55  lq_cfg = (struct m0_ha_lq_cfg){
56  };
57  m0_ha_lq_init(lq, &lq_cfg);
58  m0_ha_link_tags_initial(&tags, false);
59  m0_ha_lq_tags_set(lq, &tags);
60  *msg = (struct m0_ha_msg){
61  .hm_fid = M0_FID_INIT(1, 2),
62  .hm_source_process = M0_FID_INIT(3, 4),
63  .hm_source_service = M0_FID_INIT(5, 6),
64  .hm_time = 0,
65  .hm_data = {
66  .hed_type = M0_HA_MSG_STOB_IOQ,
67  },
68  };
70  tag = m0_ha_lq_enqueue(lq, msg);
74  msg2 = m0_ha_lq_msg(lq, tag);
75  M0_UT_ASSERT(m0_ha_msg_eq(msg, msg2));
78 
79  msg2 = m0_ha_lq_next(lq);
80  M0_UT_ASSERT(m0_ha_msg_eq(msg, msg2));
86 
87  success = m0_ha_lq_try_unnext(lq);
88  M0_UT_ASSERT(success);
89  success = m0_ha_lq_try_unnext(lq);
90  M0_UT_ASSERT(!success);
91  msg2 = m0_ha_lq_next(lq);
92  M0_UT_ASSERT(m0_ha_msg_eq(msg, msg2));
93 
100 
101  tag2 = m0_ha_lq_dequeue(lq);
102  M0_UT_ASSERT(tag2 == tag);
107 
108  m0_ha_lq_fini(lq);
109  m0_free(msg);
110  m0_free(lq);
111 }
112 
113 /*
114  '.' -- delivered message
115  'x,y,z' -- not delivered
116 
117  1) Construct the following queue:
118  + m0_ha_link_tags::hlt_delivered
119  |
120  V
121  x..yyy....zzzzzz
122  2) Mark 'y'- and 'z'- messages as delivered
123  + m0_ha_link_tags::hlt_delivered
124  |
125  V
126  x...............
127  3) Mark 'x'- messages as delivered and move m0_ha_link_tags::hlt_delivered
128  + m0_ha_link_tags::hlt_delivered
129  |
130  V
131  ................
132  */
134 {
135  enum { MARK_DELIVERED_LQ_SIZE = 100 };
136  struct m0_ha_link_tags link_tags;
137  struct m0_ha_lq_cfg lq_cfg;
138  struct m0_ha_msg *msg;
139  struct m0_ha_lq *lq;
140  uint64_t tag;
141  uint32_t i;
142  uint32_t lq_size = MARK_DELIVERED_LQ_SIZE;
143  uint64_t tags[MARK_DELIVERED_LQ_SIZE];
144  M0_CASSERT(MARK_DELIVERED_LQ_SIZE >= 100);
145  M0_CASSERT(MARK_DELIVERED_LQ_SIZE % 2 == 0);
146 
147 
148  M0_ALLOC_PTR(lq);
149  M0_UT_ASSERT(lq != NULL);
150  M0_ALLOC_PTR(msg);
151  M0_UT_ASSERT(msg != NULL);
152  lq_cfg = (struct m0_ha_lq_cfg){
153  };
154  m0_ha_lq_init(lq, &lq_cfg);
155  m0_ha_link_tags_initial(&link_tags, false);
156  m0_ha_lq_tags_set(lq, &link_tags);
157 
158  /* 1) Construct lq */
159  for (i = 0; i < lq_size; ++i) {
160  *msg = (struct m0_ha_msg){
161  .hm_fid = M0_FID_INIT(i, i + 1),
162  .hm_source_process = M0_FID_INIT(3, 4),
163  .hm_source_service = M0_FID_INIT(5, 6),
164  .hm_time = 0,
165  .hm_data = {
166  .hed_type = M0_HA_MSG_STOB_IOQ,
167  },
168  };
170  tag = m0_ha_lq_enqueue(lq, msg);
176 
177  (void)m0_ha_lq_next(lq);
182 
183  tags[i] = tag;
184  if (!((i >= lq_size/10 && i < lq_size/10 + lq_size/20) ||
185  (i >= lq_size/4 && i < lq_size/4 + lq_size/10) ||
186  (i >= lq_size/2 && i < lq_size/2 + lq_size/5)))
188 
189  M0_ASSERT(ergo(i < lq_size/10,
190  tag == m0_ha_lq_tag_delivered(lq)-2));
191  M0_ASSERT(ergo(i > lq_size/10,
192  tag != m0_ha_lq_tag_delivered(lq)-2));
193  }
194 
195  /* 2) Mark some messages as delivered */
196  for (i = 0; i < lq_size; ++i) {
197  tag = tags[i];
198  M0_UT_ASSERT(m0_ha_lq_tag_delivered(lq) == tags[lq_size/10]);
199 
200  if ((i >= lq_size/4 && i < lq_size/4 + lq_size/10) ||
201  (i >= lq_size/2 && i < lq_size/2 + lq_size/5))
203 
204  M0_UT_ASSERT(m0_ha_lq_tag_delivered(lq) == tags[lq_size/10]);
205  }
206 
207  /* 3) Mark all messages as delivered and move hlt_delivered */
208  for (i = 0; i < lq_size; ++i) {
209  tag = tags[i];
210 
211  M0_ASSERT(ergo(i < lq_size/10, tags[lq_size/10] ==
213  M0_ASSERT(ergo(i >= lq_size/10 && i < lq_size/4 - lq_size/10,
214  m0_ha_lq_tag_delivered(lq) == tags[i]));
215  M0_ASSERT(ergo(i >= lq_size/4 - lq_size/10,
216  m0_ha_lq_tag_delivered(lq)-2 ==
217  tags[lq_size-1]));
218 
219  if ((i >= lq_size/10 && i < lq_size/10 + lq_size/20))
221 
222  M0_ASSERT(ergo(i < lq_size/10, tags[lq_size/10] ==
224  M0_ASSERT(ergo(i >= lq_size/10 && i < lq_size/4 - lq_size/10 - 1,
225  m0_ha_lq_tag_delivered(lq)-2 == tags[i]));
226  M0_ASSERT(ergo(i >= lq_size/4 - lq_size/10 - 1,
227  m0_ha_lq_tag_delivered(lq)-2 ==
228  tags[lq_size-1]));
229  }
230 
231  for (i = 0; i < lq_size; ++i) {
232  tag = m0_ha_lq_dequeue(lq);
236  }
237 
238  m0_ha_lq_fini(lq);
239  m0_free(msg);
240  m0_free(lq);
241 }
242 
243 #undef M0_TRACE_SUBSYSTEM
244 
247 /*
248  * Local variables:
249  * c-indentation-style: "K&R"
250  * c-basic-offset: 8
251  * tab-width: 8
252  * fill-column: 80
253  * scroll-step: 1
254  * End:
255  */
256 /*
257  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
258  */
M0_INTERNAL bool m0_ha_lq_has_tag(const struct m0_ha_lq *lq, uint64_t tag)
Definition: lq.c:101
M0_INTERNAL bool m0_ha_lq_try_unnext(struct m0_ha_lq *lq)
Definition: lq.c:216
M0_INTERNAL uint64_t m0_ha_lq_enqueue(struct m0_ha_lq *lq, const struct m0_ha_msg *msg)
Definition: lq.c:180
struct m0_fid hm_fid
Definition: msg.h:117
M0_INTERNAL void m0_ha_lq_fini(struct m0_ha_lq *lq)
Definition: lq.c:67
#define NULL
Definition: misc.h:38
M0_INTERNAL struct m0_ha_msg * m0_ha_lq_next(struct m0_ha_lq *lq)
Definition: lq.c:203
M0_INTERNAL void m0_ha_lq_tags_set(struct m0_ha_lq *lq, const struct m0_ha_link_tags *tags)
Definition: lq.c:87
#define ergo(a, b)
Definition: misc.h:293
static uint64_t tag(uint8_t code, uint64_t id)
Definition: addb2.c:1047
#define M0_CASSERT(cond)
M0_INTERNAL uint64_t m0_ha_lq_tag_delivered(const struct m0_ha_lq *lq)
Definition: lq.c:168
#define M0_FID_INIT(container, key)
Definition: fid.h:84
M0_INTERNAL uint64_t m0_ha_lq_dequeue(struct m0_ha_lq *lq)
Definition: lq.c:256
void m0_ha_ut_lq_mark_delivered(void)
Definition: lq.c:133
M0_INTERNAL bool m0_ha_lq_has_next(const struct m0_ha_lq *lq)
Definition: lq.c:141
M0_INTERNAL bool m0_ha_lq_is_delivered(const struct m0_ha_lq *lq, uint64_t tag)
Definition: lq.c:148
Definition: lq.h:97
int i
Definition: dir.c:1033
M0_INTERNAL void m0_ha_lq_mark_delivered(struct m0_ha_lq *lq, uint64_t tag)
Definition: lq.c:228
void m0_ha_ut_lq(void)
Definition: lq.c:40
#define M0_ASSERT(cond)
M0_INTERNAL uint64_t m0_ha_lq_tag_confirmed(const struct m0_ha_lq *lq)
Definition: lq.c:174
M0_INTERNAL bool m0_ha_msg_eq(const struct m0_ha_msg *msg1, const struct m0_ha_msg *msg2)
Definition: msg.c:46
Definition: msg.h:115
M0_INTERNAL void m0_ha_link_tags_initial(struct m0_ha_link_tags *tags, bool tag_even)
Definition: link_fops.c:44
M0_INTERNAL void m0_ha_lq_init(struct m0_ha_lq *lq, const struct m0_ha_lq_cfg *lq_cfg)
Definition: lq.c:58
M0_INTERNAL uint64_t m0_ha_lq_tag_assign(const struct m0_ha_lq *lq)
Definition: lq.c:156
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
M0_INTERNAL struct m0_ha_msg * m0_ha_lq_msg(struct m0_ha_lq *lq, uint64_t tag)
Definition: lq.c:109
void m0_free(void *data)
Definition: memory.c:146
M0_INTERNAL uint64_t m0_ha_lq_tag_next(const struct m0_ha_lq *lq)
Definition: lq.c:162
#define M0_UT_ASSERT(a)
Definition: ut.h:46