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