1#
2# micro_multi.py
3#
4# This source file is part of the FoundationDB open source project
5#
6# Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
7#
8# Licensed under the Apache License, Version 2.0 (the "License");
9# you may not use this file except in compliance with the License.
10# You may obtain a copy of the License at
11#
12#     http://www.apache.org/licenses/LICENSE-2.0
13#
14# Unless required by applicable law or agreed to in writing, software
15# distributed under the License is distributed on an "AS IS" BASIS,
16# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17# See the License for the specific language governing permissions and
18# limitations under the License.
19#
20
21import struct
22
23import fdb
24fdb.api_version(300)
25db = fdb.open()
26
27
28@fdb.transactional
29def clear_subspace(tr, subspace):
30    tr.clear_range_startswith(subspace.key())
31
32
33multi = fdb.Subspace(('M',))
34clear_subspace(db, multi)
35
36
37# Multimaps with multiset values
38
39
40@fdb.transactional
41def multi_add(tr, index, value):
42    tr.add(multi[index][value], struct.pack('<q', 1))
43
44
45@fdb.transactional
46def multi_subtract(tr, index, value):
47    v = tr[multi[index][value]]
48    if v.present() and struct.unpack('<q', str(v))[0] > 1:
49        tr.add(multi[index][value], struct.pack('<q', -1))
50    else:
51        del tr[multi[index][value]]
52
53
54@fdb.transactional
55def multi_get(tr, index):
56    return [multi.unpack(k)[1] for k, v in tr[multi[index].range()]]
57
58
59@fdb.transactional
60def multi_get_counts(tr, index):
61    return {multi.unpack(k)[1]: struct.unpack('<q', v)[0]
62            for k, v in tr[multi[index].range()]}
63
64
65@fdb.transactional
66def multi_is_element(tr, index, value):
67    return tr[multi[index][value]].present()
68
69
70import time
71
72N = 10000
73
74
75@fdb.transactional
76def time_atomic_add(tr):
77    for i in xrange(N):
78        multi_add(db, 'foo', 'bar')
79
80
81@fdb.transactional
82def time_atomic_subtract(tr):
83    start = time.time()
84    for i in xrange(N):
85        multi_subtract(tr, 'foo', 'bar')
86    end = time.time()
87    print "{} seconds for atomic subtract".format(end - start)
88
89
90if __name__ == '__main__':
91    time_atomic_add(db)
92    time_atomic_subtract(db)
93