MessageAssembler.cpp
Go to the documentation of this file.
1 #include <rms/provider/MessageAssembler.h>
2 
3 #include <iostream>
4 #include <cstring> /* memcpy */
5 
6 namespace gov {
7 
8 namespace fnal {
9 
10 namespace cd {
11 
12 namespace rms {
13 
14 namespace provider {
15 
16 /**
17  * Creates a new assembler instance with the specified initial fragment.
18  *
19  * @param initialFragment The first fragment that has been received for
20  * this message.
21  */
23  _requiredFragmentCount = initialFragment->getFragmentCount();
24 
25  _messageId = new char[16];
26  memcpy(_messageId, initialFragment->getMessageId(), 16);
27 
28  _fragments.push_back(initialFragment);
29 }
30 
31 /**
32  * Destructor, make sure to free up all message
33  * fragments.
34  */
36  for (unsigned int i = 0; i < _fragments.size(); i++) {
37  delete _fragments[i];
38  }
39 
40  if (_messageId) {
41  delete[] _messageId;
42  _messageId = NULL;
43  }
44 }
45 
46 /**
47  * Add a message fragment to the assembler.
48  *
49  * @param fragment The fragment to add
50  *
51  * @return False if the fragment doesn't belong to this message,
52  * or if this fragment has already been received, or any other
53  * information in this fragment conflicts with the initial fragment.
54  * Returns true if a fragment has been successfully added.
55  */
57  int fragmentIndex;
58 
59  if (!fragment) {
60  return false;
61  }
62 
63  /**
64  * The Java version of RMS will only attach UUIDs to messages
65  * that are composed of multiple fragments. If we don't have
66  * a UUID, we just need to check to make sure that the message
67  * only consists of one fragment.
68  */
69  if (_messageId[0] != '\0') {
70  if (memcmp(fragment->getMessageId(), _messageId, 16) != 0) {
71  return false;
72  }
73  }
74  else if (fragment->getFragmentCount() != 1) {
75  return false;
76  }
77 
78  if (fragment->getFragmentCount() != _requiredFragmentCount) {
79  return false;
80  }
81 
82  fragmentIndex = fragment->getFragmentIndex();
83 
84  if (fragmentIndex < 0 || fragmentIndex >= _requiredFragmentCount) {
85  return false;
86  }
87 
88  for (unsigned int i = 0; i < _fragments.size(); i++) {
89  if (_fragments[i]->getFragmentIndex() == fragmentIndex) {
90  return false;
91  }
92  }
93 
94  _fragments.push_back(fragment);
95 
96  return true;
97 }
98 
99 /**
100  * Determine if this assembler has all the fragments
101  * necessary to assemble a complete message.
102  *
103  * @return True if this assembler has a complete message.
104  */
106  return ((unsigned int)_requiredFragmentCount == _fragments.size());
107 }
108 
109 /**
110  * Return a string containing the complete and assembled
111  * message
112  *
113  * @return A string containing the message on success, an
114  * empty string if there are fragments missing.
115  */
118  int fragmentsAssembled = 0;
119 
120  if (!hasCompleteMessage()) {
121  return std::string("");
122  }
123 
124  while (fragmentsAssembled < _requiredFragmentCount) {
125  for (int i = 0; i < _requiredFragmentCount; i++) {
126  if (_fragments[i]->getFragmentIndex() == fragmentsAssembled) {
127  message.append(_fragments[i]->getPayload());
128  fragmentsAssembled++;
129  }
130  }
131  }
132 
133  return message;
134 }
135 
136 } // end of namespace provider
137 
138 } // end of namespace rms
139 
140 } // end of namespace cd
141 
142 } // end of namespace fnal
143 
144 } // end of namespace gov
bool addFragment(MessageFragment *fragment)
Definition: fnal.py:1
std::vector< MessageFragment * > _fragments
MessageAssembler(MessageFragment *initialFragment)
c cd(1)
enum BeamMode string