forked from kohler/masstree-beta
-
Notifications
You must be signed in to change notification settings - Fork 1
/
value_versioned_array.cc
97 lines (89 loc) · 3.45 KB
/
value_versioned_array.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/* Masstree
* Eddie Kohler, Yandong Mao, Robert Morris
* Copyright (c) 2012-2014 President and Fellows of Harvard College
* Copyright (c) 2012-2014 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, subject to the conditions
* listed in the Masstree LICENSE file. These conditions include: you must
* preserve this copyright notice, and you cannot mention the copyright
* holders in advertising related to the Software without their permission.
* The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
* notice is a summary of the Masstree LICENSE file; the license in that file
* is legally binding.
*/
#include "kvrow.hh"
#include "value_versioned_array.hh"
#include <string.h>
value_versioned_array* value_versioned_array::make_sized_row(int ncol, kvtimestamp_t ts, threadinfo& ti) {
value_versioned_array* row = (value_versioned_array*) ti.allocate(shallow_size(ncol), memtag_value);
row->ts_ = ts;
row->ver_ = rowversion();
row->ncol_ = row->ncol_cap_ = ncol;
memset(row->cols_, 0, sizeof(row->cols_[0]) * ncol);
return row;
}
void value_versioned_array::snapshot(value_versioned_array*& storage,
const std::vector<index_type>& f, threadinfo& ti) const {
if (!storage || storage->ncol_cap_ < ncol_) {
if (storage)
storage->deallocate(ti);
storage = make_sized_row(ncol_, ts_, ti);
}
storage->ncol_ = ncol_;
rowversion v1 = ver_.stable();
while (1) {
if (f.size() == 1)
storage->cols_[f[0]] = cols_[f[0]];
else
memcpy(storage->cols_, cols_, sizeof(cols_[0]) * storage->ncol_);
rowversion v2 = ver_.stable();
if (!v1.has_changed(v2))
break;
v1 = v2;
}
}
value_versioned_array*
value_versioned_array::update(const Json* first, const Json* last,
kvtimestamp_t ts, threadinfo& ti,
bool always_copy) {
int ncol = last[-2].as_u() + 1;
value_versioned_array* row;
if (ncol > ncol_cap_ || always_copy) {
row = (value_versioned_array*) ti.allocate(shallow_size(ncol), memtag_value);
row->ts_ = ts;
row->ver_ = rowversion();
row->ncol_ = row->ncol_cap_ = ncol;
memcpy(row->cols_, cols_, sizeof(cols_[0]) * ncol_);
} else
row = this;
if (ncol > ncol_)
memset(row->cols_ + ncol_, 0, sizeof(cols_[0]) * (ncol - ncol_));
if (row == this) {
ver_.setdirty();
fence();
}
if (row->ncol_ < ncol)
row->ncol_ = ncol;
for (; first != last; first += 2) {
unsigned idx = first[0].as_u();
value_array::deallocate_column_rcu(row->cols_[idx], ti);
row->cols_[idx] = value_array::make_column(first[1].as_s(), ti);
}
if (row == this) {
fence();
ver_.clearandbump();
}
return row;
}
void value_versioned_array::deallocate(threadinfo &ti) {
for (short i = 0; i < ncol_; ++i)
value_array::deallocate_column(cols_[i], ti);
ti.deallocate(this, shallow_size(), memtag_value);
}
void value_versioned_array::deallocate_rcu(threadinfo &ti) {
for (short i = 0; i < ncol_; ++i)
value_array::deallocate_column_rcu(cols_[i], ti);
ti.deallocate_rcu(this, shallow_size(), memtag_value);
}