2 * Eddie Kohler, Yandong Mao, Robert Morris
3 * Copyright (c) 2012-2014 President and Fellows of Harvard College
4 * Copyright (c) 2012-2014 Massachusetts Institute of Technology
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, subject to the conditions
9 * listed in the Masstree LICENSE file. These conditions include: you must
10 * preserve this copyright notice, and you cannot mention the copyright
11 * holders in advertising related to the Software without their permission.
12 * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
13 * notice is a summary of the Masstree LICENSE file; the license in that file
16 #ifndef VALUE_VERSIONED_ARRAY_HH
17 #define VALUE_VERSIONED_ARRAY_HH
18 #include "compiler.hh"
19 #include "value_array.hh"
29 v_.u = v_.u | 0x80000000;
32 v_.u = v_.u & 0x7fffffff;
35 v_.u = (v_.u + 1) & 0x7fffffff;
37 rowversion stable() const {
46 bool has_changed(rowversion x) const {
48 return x.v_.ctr != v_.ctr;
66 class value_versioned_array {
68 typedef value_array::index_type index_type;
69 static const char *name() { return "ArrayVersion"; }
71 typedef lcdf::Json Json;
73 inline value_versioned_array();
75 inline kvtimestamp_t timestamp() const;
76 inline int ncol() const;
77 inline Str col(int i) const;
79 void deallocate(threadinfo &ti);
80 void deallocate_rcu(threadinfo &ti);
82 void snapshot(value_versioned_array*& storage,
83 const std::vector<index_type>& f, threadinfo& ti) const;
85 value_versioned_array* update(const Json* first, const Json* last,
86 kvtimestamp_t ts, threadinfo& ti,
87 bool always_copy = false);
88 static value_versioned_array* create(const Json* first, const Json* last,
89 kvtimestamp_t ts, threadinfo& ti);
90 static value_versioned_array* create1(Str value, kvtimestamp_t ts, threadinfo& ti);
91 inline void deallocate_rcu_after_update(const Json* first, const Json* last, threadinfo& ti);
92 inline void deallocate_after_failed_update(const Json* first, const Json* last, threadinfo& ti);
94 template <typename PARSER>
95 static value_versioned_array* checkpoint_read(PARSER& par, kvtimestamp_t ts,
97 template <typename UNPARSER>
98 void checkpoint_write(UNPARSER& unpar) const;
100 void print(FILE *f, const char *prefix, int indent, Str key,
101 kvtimestamp_t initial_ts, const char *suffix = "") {
102 kvtimestamp_t adj_ts = timestamp_sub(ts_, initial_ts);
103 fprintf(f, "%s%*s%.*s = ### @" PRIKVTSPARTS "%s\n", prefix, indent, "",
104 key.len, key.s, KVTS_HIGHPART(adj_ts), KVTS_LOWPART(adj_ts), suffix);
112 lcdf::inline_string* cols_[0];
114 static inline size_t shallow_size(int ncol);
115 inline size_t shallow_size() const;
116 static value_versioned_array* make_sized_row(int ncol, kvtimestamp_t ts, threadinfo& ti);
120 struct query_helper<value_versioned_array> {
121 value_versioned_array* snapshot_;
126 inline const value_versioned_array* snapshot(const value_versioned_array* row,
127 const std::vector<value_versioned_array::index_type>& f,
129 row->snapshot(snapshot_, f, ti);
134 inline value_versioned_array::value_versioned_array()
135 : ts_(0), ncol_(0), ncol_cap_(0) {
138 inline kvtimestamp_t value_versioned_array::timestamp() const {
142 inline int value_versioned_array::ncol() const {
146 inline Str value_versioned_array::col(int i) const {
147 if (unsigned(i) < unsigned(ncol_) && cols_[i])
148 return Str(cols_[i]->s, cols_[i]->len);
153 inline size_t value_versioned_array::shallow_size(int ncol) {
154 return sizeof(value_versioned_array) + ncol * sizeof(lcdf::inline_string*);
157 inline size_t value_versioned_array::shallow_size() const {
158 return shallow_size(ncol_);
161 inline value_versioned_array* value_versioned_array::create(const Json* first, const Json* last, kvtimestamp_t ts, threadinfo& ti) {
162 value_versioned_array empty;
163 return empty.update(first, last, ts, ti, true);
166 inline value_versioned_array* value_versioned_array::create1(Str value, kvtimestamp_t ts, threadinfo& ti) {
167 value_versioned_array* row = (value_versioned_array*) ti.allocate(shallow_size(1), memtag_value);
169 row->ver_ = rowversion();
170 row->ncol_ = row->ncol_cap_ = 1;
171 row->cols_[0] = value_array::make_column(value, ti);
175 inline void value_versioned_array::deallocate_rcu_after_update(const Json*, const Json*, threadinfo& ti) {
176 ti.deallocate_rcu(this, shallow_size(), memtag_value);
179 inline void value_versioned_array::deallocate_after_failed_update(const Json*, const Json*, threadinfo&) {
183 template <typename PARSER>
184 value_versioned_array*
185 value_versioned_array::checkpoint_read(PARSER& par, kvtimestamp_t ts,
188 par.read_array_header(ncol);
189 value_versioned_array* row = make_sized_row(ncol, ts, ti);
191 for (unsigned i = 0; i != ncol; i++) {
193 row->cols_[i] = value_array::make_column(col, ti);
198 template <typename UNPARSER>
199 void value_versioned_array::checkpoint_write(UNPARSER& unpar) const {
200 unpar.write_array_header(ncol_);
201 for (short i = 0; i != ncol_; ++i)