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