1 #include "example/example.hpp"
2
3 #include <phosphor-logging/log.hpp>
4
5 #include <algorithm>
6 #include <cstring>
7 #include <memory>
8 #include <string>
9 #include <vector>
10
11 namespace blobs
12 {
13
14 using namespace phosphor::logging;
15
16 constexpr char ExampleBlobHandler::supportedPath[];
17
getSession(uint16_t id)18 ExampleBlob* ExampleBlobHandler::getSession(uint16_t id)
19 {
20 auto search = sessions.find(id);
21 if (search == sessions.end())
22 {
23 return nullptr;
24 }
25 /* Not thread-safe, however, the blob handler deliberately assumes serial
26 * execution. */
27 return &search->second;
28 }
29
canHandleBlob(const std::string & path)30 bool ExampleBlobHandler::canHandleBlob(const std::string& path)
31 {
32 return (path == supportedPath);
33 }
34
getBlobIds()35 std::vector<std::string> ExampleBlobHandler::getBlobIds()
36 {
37 return {supportedPath};
38 }
39
deleteBlob(const std::string &)40 bool ExampleBlobHandler::deleteBlob(const std::string&)
41 {
42 return false;
43 }
44
stat(const std::string &,BlobMeta *)45 bool ExampleBlobHandler::stat(const std::string&, BlobMeta*)
46 {
47 return false;
48 }
49
open(uint16_t session,uint16_t flags,const std::string & path)50 bool ExampleBlobHandler::open(uint16_t session, uint16_t flags,
51 const std::string& path)
52 {
53 if (!canHandleBlob(path))
54 {
55 return false;
56 }
57
58 auto findSess = sessions.find(session);
59 if (findSess != sessions.end())
60 {
61 /* This session is already active. */
62 return false;
63 }
64 sessions[session] = ExampleBlob(session, flags);
65 return true;
66 }
67
read(uint16_t session,uint32_t offset,uint32_t requestedSize)68 std::vector<uint8_t> ExampleBlobHandler::read(uint16_t session, uint32_t offset,
69 uint32_t requestedSize)
70 {
71 ExampleBlob* sess = getSession(session);
72 if (!sess)
73 {
74 return std::vector<uint8_t>();
75 }
76
77 /* Is the offset beyond the array? */
78 if (offset >= sizeof(sess->buffer))
79 {
80 return std::vector<uint8_t>();
81 }
82
83 /* Determine how many bytes we can read from the offset.
84 * In this case, if they read beyond "size" we allow it.
85 */
86 uint32_t remain = sizeof(sess->buffer) - offset;
87 uint32_t numBytes = std::min(remain, requestedSize);
88 /* Copy the bytes! */
89 std::vector<uint8_t> result(numBytes);
90 std::memcpy(result.data(), &sess->buffer[offset], numBytes);
91 return result;
92 }
93
write(uint16_t session,uint32_t offset,const std::vector<uint8_t> & data)94 bool ExampleBlobHandler::write(uint16_t session, uint32_t offset,
95 const std::vector<uint8_t>& data)
96 {
97 ExampleBlob* sess = getSession(session);
98 if (!sess)
99 {
100 return false;
101 }
102 /* Is the offset beyond the array? */
103 if (offset >= sizeof(sess->buffer))
104 {
105 return false;
106 }
107 /* Determine whether all their bytes will fit. */
108 uint32_t remain = sizeof(sess->buffer) - offset;
109 if (data.size() > remain)
110 {
111 return false;
112 }
113 sess->length =
114 std::max(offset + data.size(),
115 static_cast<std::vector<uint8_t>::size_type>(sess->length));
116 std::memcpy(&sess->buffer[offset], data.data(), data.size());
117 return true;
118 }
119
writeMeta(uint16_t,uint32_t,const std::vector<uint8_t> &)120 bool ExampleBlobHandler::writeMeta(uint16_t, uint32_t,
121 const std::vector<uint8_t>&)
122 {
123 /* Not supported. */
124 return false;
125 }
126
commit(uint16_t session,const std::vector<uint8_t> &)127 bool ExampleBlobHandler::commit(uint16_t session, const std::vector<uint8_t>&)
128 {
129 ExampleBlob* sess = getSession(session);
130 if (!sess)
131 {
132 return false;
133 }
134
135 /* Do something with the staged data!. */
136
137 return false;
138 }
139
close(uint16_t session)140 bool ExampleBlobHandler::close(uint16_t session)
141 {
142 ExampleBlob* sess = getSession(session);
143 if (!sess)
144 {
145 return false;
146 }
147
148 sessions.erase(session);
149 return true;
150 }
151
stat(uint16_t session,BlobMeta * meta)152 bool ExampleBlobHandler::stat(uint16_t session, BlobMeta* meta)
153 {
154 ExampleBlob* sess = getSession(session);
155 if (!sess)
156 {
157 return false;
158 }
159 if (!meta)
160 {
161 return false;
162 }
163 meta->size = sess->length;
164 meta->blobState = sess->state;
165 return true;
166 }
167
expire(uint16_t session)168 bool ExampleBlobHandler::expire(uint16_t session)
169 {
170 ExampleBlob* sess = getSession(session);
171 if (!sess)
172 {
173 return false;
174 }
175 /* TODO: implement session expiration behavior. */
176 return false;
177 }
178
179 void setupExampleHandler() __attribute__((constructor));
180
setupExampleHandler()181 void setupExampleHandler()
182 {
183 // You don't need to do anything in the constructor.
184 }
185
186 } // namespace blobs
187
188 /**
189 * This method is required by the blob manager.
190 *
191 * It is called to grab a handler for registering the blob handler instance.
192 */
createHandler()193 std::unique_ptr<blobs::GenericBlobInterface> createHandler()
194 {
195 return std::make_unique<blobs::ExampleBlobHandler>();
196 }
197