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& path)
40 {
41     return false;
42 }
43 
44 bool ExampleBlobHandler::stat(const std::string& path, BlobMeta* meta)
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 session, uint32_t offset,
120                                    const std::vector<uint8_t>& data)
121 {
122     /* Not supported. */
123     return false;
124 }
125 
126 bool ExampleBlobHandler::commit(uint16_t session,
127                                 const std::vector<uint8_t>& data)
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 
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 
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 
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 
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  */
193 std::unique_ptr<blobs::GenericBlobInterface> createHandler()
194 {
195     return std::make_unique<blobs::ExampleBlobHandler>();
196 }
197