aboutsummaryrefslogtreecommitdiff
path: root/db/memtable.cuh
blob: 766eb0371d4e246b4d1f9c7388ea6881007dcde2 (plain)
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

#ifndef STORAGE_LEVELDB_DB_MEMTABLE_H_
#define STORAGE_LEVELDB_DB_MEMTABLE_H_

#include <string>

#include "db/dbformat.h"
#include "db/skiplist.cuh"
#include "leveldb/db.h"
#include "util/arena.cuh"
#include "util/arena.h"

namespace leveldb {

class InternalKeyComparator;
class MemTableIterator;

__device__ const char* GetVarint32PtrFallbackCuda(const char* p, const char* limit,
                                                  uint32_t* value) {
  uint32_t result = 0;
  for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) {
    uint32_t byte = *(reinterpret_cast<const uint8_t*>(p));
    p++;
    if (byte & 128) {
      // More bytes are present
      result |= ((byte & 127) << shift);
    } else {
      result |= (byte << shift);
      *value = result;
      return reinterpret_cast<const char*>(p);
    }
  }
  return nullptr;
}

__device__ inline const char* GetVarint32PtrCuda(const char* p, const char* limit,
                                                 uint32_t* value) {
  if (p < limit) {
    uint32_t result = *(reinterpret_cast<const uint8_t*>(p));
    if ((result & 128) == 0) {
      *value = result;
      return p + 1;
    }
  }
  return GetVarint32PtrFallbackCuda(p, limit, value);
}

struct SizedString {
  char * data;
  size_t length;

  __host__ explicit SizedString() {
    this->data = nullptr;
    this->length = 0;
  }

  __device__ explicit SizedString(const char* p, size_t len) {
    this->data = nullptr;
    cudaMalloc((void**)&this->data, len);
    memcpy(this->data, p, len);
    this->length = len;
  }

  __host__ __device__ SizedString(const SizedString & other) {
    this->data = other.data;
    this->length = other.length;
  }

  __host__ __device__ SizedString & operator=(const SizedString& other) = default;
};


__device__ static SizedString GetLengthPrefixedSliceCuda(const char* data) {
  uint32_t len;
  const char* p = data;
  p = GetVarint32PtrCuda(p, p + 5, &len);  // +5: we assume "p" is not corrupted
  return SizedString(p, len);
}

class MemTable {
 public:
  // MemTables are reference counted.  The initial reference count
  // is zero and the caller must call Ref() at least once.
  explicit MemTable(const InternalKeyComparator& comparator);

  MemTable(const MemTable&) = delete;
  MemTable& operator=(const MemTable&) = delete;

  // Increase reference count.
  void Ref() { ++refs_; }

  // Drop reference count.  Delete if no more references exist.
  void Unref() {
    --refs_;
    assert(refs_ >= 0);
    if (refs_ <= 0) {
      delete this;
    }
  }

  // Returns an estimate of the number of bytes of data in use by this
  // data structure. It is safe to call when MemTable is being modified.
  size_t ApproximateMemoryUsage();

  // Return an iterator that yields the contents of the memtable.
  //
  // The caller must ensure that the underlying MemTable remains live
  // while the returned iterator is live.  The keys returned by this
  // iterator are internal keys encoded by AppendInternalKey in the
  // db/format.{h,cc} module.
  Iterator* NewIterator();

  // Add an entry into memtable that maps key to value at the
  // specified sequence number and with the specified type.
  // Typically value will be empty if type==kTypeDeletion.
  void Add(SequenceNumber seq, ValueType type, const Slice& key,
           const Slice& value);

  // If memtable contains a value for key, store it in *value and return true.
  // If memtable contains a deletion for key, store a NotFound() error
  // in *status and return true.
  // Else, return false.
  bool Get(const LookupKey& key, std::string* value, Status* s);

 private:
  friend class MemTableIterator;
  friend class MemTableBackwardIterator;
  friend __global__ void Add_(MemTable *, size_t, char *);
  friend __global__ void Get_(MemTable *, char *, char **, size_t* malloc_size);

  struct KeyComparator {
    const InternalKeyComparator comparator;
    explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) {}
    int operator()(const char* a, const char* b) const;
    ~KeyComparator() = default;
  };

  typedef SkipList<const char*, KeyComparator> Table;

  __device__  Table::Iterator getIter() {
    Table::Iterator iter(&this->table_);
    return iter;
  }

  ~MemTable();  // Private since only Unref() should be used to delete it

  KeyComparator comparator_;
  int refs_;
  Arena host_arena_;
  ArenaCuda arena_;
  Table table_;
};

}  // namespace leveldb

#endif  // STORAGE_LEVELDB_DB_MEMTABLE_H_