Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
ostree_object.h
1 #ifndef SOTA_CLIENT_TOOLS_OSTREE_OBJECT_H_
2 #define SOTA_CLIENT_TOOLS_OSTREE_OBJECT_H_
3 
4 #include <chrono>
5 #include <iostream>
6 #include <sstream>
7 
8 #include <curl/curl.h>
9 #include <boost/filesystem.hpp>
10 #include <boost/intrusive_ptr.hpp>
11 #include "gtest/gtest_prod.h"
12 
13 #include "garage_common.h"
14 #include "treehub_server.h"
15 
16 class OSTreeRepo;
17 class RequestPool;
18 
19 enum class PresenceOnServer { kObjectStateUnknown, kObjectPresent, kObjectMissing, kObjectInProgress };
20 
21 enum class CurrentOp { kOstreeObjectUploading, kOstreeObjectPresenceCheck };
22 
23 /**
24  * Broad categories for server response codes.
25  * There is no category for a permanent failure at the moment: we are unable to
26  * detect a failure that is definitely permanent.
27  */
28 enum class ServerResponse { kNoResponse, kOk, kTemporaryFailure };
29 
30 class OSTreeObject {
31  public:
32  using ptr = boost::intrusive_ptr<OSTreeObject>;
33  OSTreeObject(const OSTreeRepo& repo, const std::string& object_name);
34  OSTreeObject(const OSTreeObject&) = delete;
35  OSTreeObject operator=(const OSTreeObject&) = delete;
36 
37  ~OSTreeObject();
38 
39  /* This object has been uploaded, notify parents. If parent object has no more
40  * children pending upload, add the parent to the upload queue. */
41  void NotifyParents(RequestPool& pool);
42 
43  /* Send a HEAD request to the destination server to check if this object is
44  * present there. */
45  void MakeTestRequest(const TreehubServer& push_target, CURLM* curl_multi_handle);
46 
47  /* Upload this object to the destination server. */
48  void Upload(TreehubServer& push_target, CURLM* curl_multi_handle, RunMode mode);
49 
50  /* Process a completed curl transaction (presence check or upload). */
51  void CurlDone(CURLM* curl_multi_handle, RequestPool& pool);
52 
53  PresenceOnServer is_on_server() const { return is_on_server_; }
54  CurrentOp operation() const { return current_operation_; }
55  bool children_ready() { return children_.empty(); }
56  void LaunchNotify() { is_on_server_ = PresenceOnServer::kObjectInProgress; }
57  std::chrono::steady_clock::time_point RequestStartTime() const { return request_start_time_; }
58  ServerResponse LastOperationResult() const { return last_operation_result_; }
59 
60  private:
61  using childiter = std::list<OSTreeObject::ptr>::iterator;
62  typedef std::pair<OSTreeObject*, childiter> parentref;
63 
64  /* Add parent to this object. */
65  void AddParent(OSTreeObject* parent, std::list<OSTreeObject::ptr>::iterator parent_it);
66 
67  /* Child object of this object has been uploaded, remove it from the list. */
68  void ChildNotify(std::list<OSTreeObject::ptr>::iterator child_it);
69 
70  /* If the child has is not already on the server, add it to this object's list
71  * of children and add this object as the parent of the new child. */
72  void AppendChild(const OSTreeObject::ptr& child);
73 
74  /* Parse this object for children. */
75  void PopulateChildren();
76 
77  /* Add queries to the queue for any children whose presence on the server is
78  * unknown. */
79  void QueryChildren(RequestPool& pool);
80 
81  std::string Url() const;
82 
83  /* Check for children. If they are all present and this object isn't present,
84  * upload it. If any children are missing, query them. */
85  void CheckChildren(RequestPool& pool, long rescode); // NOLINT(google-runtime-int)
86 
87  /* Handle an error from a presence check. */
88  void PresenceError(RequestPool& pool, int64_t rescode);
89 
90  /* Handle an error from an upload. */
91  void UploadError(RequestPool& pool, int64_t rescode);
92 
93  static size_t curl_handle_write(void* buffer, size_t size, size_t nmemb, void* userp);
94 
95  FRIEND_TEST(OstreeObject, Request);
96  FRIEND_TEST(OstreeObject, UploadDryRun);
97  FRIEND_TEST(OstreeObject, UploadFail);
98  FRIEND_TEST(OstreeObject, UploadSuccess);
99  friend void intrusive_ptr_add_ref(OSTreeObject* /*h*/);
100  friend void intrusive_ptr_release(OSTreeObject* /*h*/);
101  friend std::ostream& operator<<(std::ostream& stream, const OSTreeObject& o);
102 
103  const boost::filesystem::path file_path_; // Full path to the object
104  const std::string object_name_; // OSTree name of the object
105  const OSTreeRepo& repo_;
106  int refcount_; // refcounts and intrusive_ptr are used to simplify
107  // interaction with curl
108  PresenceOnServer is_on_server_;
109  CurrentOp current_operation_{};
110 
111  std::stringstream http_response_;
112  CURL* curl_handle_;
113  FILE* fd_;
114  std::list<parentref> parents_;
115  std::list<OSTreeObject::ptr> children_;
116 
117  std::chrono::steady_clock::time_point request_start_time_;
118  ServerResponse last_operation_result_{ServerResponse::kNoResponse};
119  OstreeObjectType type_{OstreeObjectType::OSTREE_OBJECT_TYPE_UNKNOWN};
120 };
121 
122 OSTreeObject::ptr ostree_object_from_curl(CURL* curlhandle);
123 
124 std::ostream& operator<<(std::ostream& stream, const OSTreeObject::ptr& o);
125 
126 // vim: set tabstop=2 shiftwidth=2 expandtab:
127 #endif // SOTA_CLIENT_TOOLS_OSTREE_OBJECT_H_
OSTreeObject
Definition: ostree_object.h:30
TreehubServer
Definition: treehub_server.h:11
OSTreeRepo
A source repository to read OSTree objects from.
Definition: ostree_repo.h:19
RequestPool
Definition: request_pool.h:12
garage_common.h
OstreeObjectType
OstreeObjectType
Types of OSTree objects, borrowed from libostree/ostree-core.h.
Definition: garage_common.h:34
RunMode
RunMode
Execution mode to run garage tools in.
Definition: garage_common.h:6