1 // Copyright 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_CELL_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_CELL_H
17 
18 #include "google/cloud/bigtable/internal/google_bytes_traits.h"
19 #include "google/cloud/bigtable/row_key.h"
20 #include "google/cloud/bigtable/version.h"
21 #include "google/cloud/status_or.h"
22 #include <chrono>
23 #include <type_traits>
24 #include <vector>
25 
26 namespace google {
27 namespace cloud {
28 namespace bigtable {
29 inline namespace BIGTABLE_CLIENT_NS {
30 class Cell;
31 struct Mutation;
32 Mutation SetCell(Cell);
33 
34 /**
35  * Defines the type for column qualifiers.
36  *
37  * Inside Google some protobuf fields of type `bytes` are mapped to a different
38  * type than `std::string`. This is the case for column qualifiers. We use this
39  * type to automatically detect what is the representation for this field and
40  * use the correct mapping.
41  *
42  * External users of the Cloud Bigtable C++ client library should treat this as
43  * a complicated `typedef` for `std::string`. We have no plans to change the
44  * type in the external version of the C++ client library for the foreseeable
45  * future. In the eventuality that we do decide to change the type, this would
46  * be a reason update the library major version number, and we would give users
47  * time to migrate.
48  *
49  * In other words, external users of the Cloud Bigtable C++ client should simply
50  * write `std::string` where this type appears. For Google projects that must
51  * compile both inside and outside Google, this alias may be convenient.
52  */
53 using ColumnQualifierType = std::decay<decltype(
54     std::declval<google::bigtable::v2::Column>().qualifier())>::type;
55 
56 /**
57  * Defines the type for cell values.
58  *
59  * Inside Google some protobuf fields of type `bytes` are mapped to a different
60  * type than `std::string`. This is the case for column qualifiers. We use this
61  * type to automatically detect what is the representation for this field and
62  * use the correct mapping.
63  *
64  * External users of the Cloud Bigtable C++ client library should treat this as
65  * a complicated `typedef` for `std::string`. We have no plans to change the
66  * type in the external version of the C++ client library for the foreseeable
67  * future. In the eventuality that we do decide to change the type, this would
68  * be a reason update the library major version number, and we would give users
69  * time to migrate.
70  *
71  * In other words, external users of the Cloud Bigtable C++ client should simply
72  * write `std::string` where this type appears. For Google projects that must
73  * compile both inside and outside Google, this alias may be convenient.
74  */
75 using CellValueType = std::decay<decltype(
76     std::declval<google::bigtable::v2::Cell>().value())>::type;
77 
78 /**
79  * The in-memory representation of a Bigtable cell.
80  *
81  * Bigtable stores data in rows, indexes by row keys.  Each row may contain
82  * multiple column families, each column family might contain multiple columns,
83  * and each column has multiple cells indexed by timestamp.  Notice that the
84  * storage is sparse, column families, columns, and timestamps might contain
85  * zero cells.
86  *
87  * The Cell class owns all its data.
88  */
89 class Cell {
90  public:
91   /// Create a Cell and fill it with data.
92   template <typename KeyType, typename ColumnType, typename ValueType,
93             // This function does not participate in overload resolution if
94             // ValueType is not an integral type. The case for integral types is
95             // handled by the next overload, where the value is stored as a Big
96             // Endian number.
97             typename std::enable_if<!std::is_integral<ValueType>::value,
98                                     int>::type = 0>
Cell(KeyType && row_key,std::string family_name,ColumnType && column_qualifier,std::int64_t timestamp,ValueType && value,std::vector<std::string> labels)99   Cell(KeyType&& row_key, std::string family_name,
100        ColumnType&& column_qualifier, std::int64_t timestamp, ValueType&& value,
101        std::vector<std::string> labels)
102       : row_key_(std::forward<KeyType>(row_key)),
103         family_name_(std::move(family_name)),
104         column_qualifier_(std::forward<ColumnType>(column_qualifier)),
105         timestamp_(timestamp),
106         value_(std::forward<ValueType>(value)),
107         labels_(std::move(labels)) {}
108 
109   /// Create a Cell and fill it with a 64-bit value encoded as big endian.
110   template <typename KeyType, typename ColumnType>
111   // NOLINTNEXTLINE(performance-unnecessary-value-param) TODO(#4112)
Cell(KeyType && row_key,std::string family_name,ColumnType && column_qualifier,std::int64_t timestamp,std::int64_t value,std::vector<std::string> labels)112   Cell(KeyType&& row_key, std::string family_name,
113        ColumnType&& column_qualifier, std::int64_t timestamp,
114        // NOLINTNEXTLINE(performance-unnecessary-value-param) TODO(#4112)
115        std::int64_t value, std::vector<std::string> labels)
116       : Cell(std::forward<KeyType>(row_key), std::move(family_name),
117              std::forward<ColumnType>(column_qualifier), timestamp,
118              google::cloud::internal::EncodeBigEndian(value),
119              std::move(labels)) {}
120 
121   /// Create a cell and fill it with data, but with empty labels.
122   template <typename KeyType, typename ColumnType, typename ValueType>
123   // NOLINTNEXTLINE(performance-unnecessary-value-param) TODO(#4112)
Cell(KeyType && row_key,std::string family_name,ColumnType && column_qualifier,std::int64_t timestamp,ValueType && value)124   Cell(KeyType&& row_key, std::string family_name,
125        ColumnType&& column_qualifier, std::int64_t timestamp, ValueType&& value)
126       : Cell(std::forward<KeyType>(row_key), std::move(family_name),
127              std::forward<ColumnType>(column_qualifier), timestamp,
128              std::forward<ValueType>(value), std::vector<std::string>{}) {}
129 
130   /// Return the row key this cell belongs to. The returned value is not valid
131   /// after this object is deleted.
row_key()132   RowKeyType const& row_key() const { return row_key_; }
133 
134   /// Return the family this cell belongs to. The returned value is not valid
135   /// after this object is deleted.
family_name()136   std::string const& family_name() const { return family_name_; }
137 
138   /// Return the column this cell belongs to. The returned value is not valid
139   /// after this object is deleted.
column_qualifier()140   ColumnQualifierType const& column_qualifier() const {
141     return column_qualifier_;
142   }
143 
144   /// Return the timestamp of this cell.
timestamp()145   std::chrono::microseconds timestamp() const {
146     return std::chrono::microseconds(timestamp_);
147   }
148 
149   /// Return the contents of this cell. The returned value is not valid after
150   /// this object is deleted.
value()151   CellValueType const& value() const& { return value_; }
152   /// Return the contents of this cell.
value()153   CellValueType&& value() && { return std::move(value_); }
154 
155   /**
156    * Interpret the value as a big-endian encoded `T` and return it.
157    *
158    * Google Cloud Bigtable stores arbitrary blobs in each cell. Some
159    * applications interpret these blobs as strings, other as encoded protos,
160    * and sometimes as big-endian integers. This is a helper function to convert
161    * the blob into a T value.
162    */
163   template <typename T>
decode_big_endian_integer()164   StatusOr<T> decode_big_endian_integer() const {
165     return internal::DecodeBigEndianCellValue<T>(value_);
166   }
167 
168   /// Return the labels applied to this cell by label transformer read filters.
labels()169   std::vector<std::string> const& labels() const { return labels_; }
170 
171  private:
172   RowKeyType row_key_;
173   std::string family_name_;
174   ColumnQualifierType column_qualifier_;
175   std::int64_t timestamp_;
176   CellValueType value_;
177   std::vector<std::string> labels_;
178 
179   friend Mutation SetCell(Cell);
180 };
181 
182 }  // namespace BIGTABLE_CLIENT_NS
183 }  // namespace bigtable
184 }  // namespace cloud
185 }  // namespace google
186 
187 #endif  // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_CELL_H
188