1#encoding:BINARY 2 3# 4# directory_extension.rb 5# 6# This source file is part of the FoundationDB open source project 7# 8# Copyright 2013-2018 Apple Inc. and the FoundationDB project authors 9# 10# Licensed under the Apache License, Version 2.0 (the "License"); 11# you may not use this file except in compliance with the License. 12# You may obtain a copy of the License at 13# 14# http://www.apache.org/licenses/LICENSE-2.0 15# 16# Unless required by applicable law or agreed to in writing, software 17# distributed under the License is distributed on an "AS IS" BASIS, 18# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19# See the License for the specific language governing permissions and 20# limitations under the License. 21# 22 23require 'fdb' 24 25module DirectoryExtension 26 class DirectoryTester 27 @@ops_that_create_dirs = [ 28 'DIRECTORY_CREATE_SUBSPACE', 29 'DIRECTORY_CREATE_LAYER', 30 'DIRECTORY_CREATE_OR_OPEN', 31 'DIRECTORY_CREATE', 32 'DIRECTORY_OPEN', 33 'DIRECTORY_MOVE', 34 'DIRECTORY_MOVE_TO', 35 'DIRECTORY_OPEN_SUBSPACE', 36 ] 37 38 def initialize 39 @dir_list = [FDB.directory] 40 @dir_index = 0 41 @error_index = 0 42 end 43 44 def pop_tuples(inst, num=nil) 45 actual_num = num 46 if actual_num.nil? 47 actual_num = 1 48 end 49 50 tuples = (0...actual_num).map do 51 (0...inst.wait_and_pop).map do 52 inst.wait_and_pop 53 end 54 end 55 56 if num.nil? 57 return tuples[0] 58 end 59 60 return tuples 61 end 62 63 def process_instruction(inst) 64 begin 65 #puts "#{inst.index} #{inst.op}" 66 directory = @dir_list[@dir_index] 67 if inst.op == 'DIRECTORY_CREATE_SUBSPACE' 68 path = pop_tuples(inst) 69 raw_prefix = inst.wait_and_pop 70 @dir_list << FDB::Subspace.new(path, raw_prefix) 71 elsif inst.op == 'DIRECTORY_CREATE_LAYER' 72 index1 = inst.wait_and_pop 73 index2 = inst.wait_and_pop 74 allow_manual_prefixes = inst.wait_and_pop 75 if @dir_list[index1].nil? or @dir_list[index2].nil? 76 @dir_list << nil 77 else 78 @dir_list << FDB::DirectoryLayer.new(:node_subspace => @dir_list[index1], 79 :content_subspace => @dir_list[index2], 80 :allow_manual_prefixes => allow_manual_prefixes == 1) 81 end 82 elsif inst.op == 'DIRECTORY_CHANGE' 83 @dir_index = inst.wait_and_pop 84 if @dir_list[@dir_index].nil? 85 @dir_index = @error_index 86 end 87 elsif inst.op == 'DIRECTORY_SET_ERROR_INDEX' 88 @error_index = inst.wait_and_pop 89 elsif inst.op == 'DIRECTORY_CREATE_OR_OPEN' 90 @dir_list << directory.create_or_open(inst.tr, pop_tuples(inst), :layer=>inst.wait_and_pop || '') 91 elsif inst.op == 'DIRECTORY_CREATE' 92 @dir_list << directory.create(inst.tr, pop_tuples(inst), :layer=>inst.wait_and_pop || '', :prefix=>inst.wait_and_pop) 93 elsif inst.op == 'DIRECTORY_OPEN' 94 @dir_list << directory.open(inst.tr, pop_tuples(inst), :layer=>inst.wait_and_pop || '') 95 elsif inst.op == 'DIRECTORY_MOVE' 96 @dir_list << directory.move(inst.tr, pop_tuples(inst), pop_tuples(inst)) 97 elsif inst.op == 'DIRECTORY_MOVE_TO' 98 @dir_list << directory.move_to(inst.tr, pop_tuples(inst)) 99 elsif inst.op == 'DIRECTORY_REMOVE' 100 count = inst.wait_and_pop 101 if count == 0 102 directory.remove(inst.tr) 103 else 104 directory.remove(inst.tr, pop_tuples(inst)) 105 end 106 elsif inst.op == 'DIRECTORY_REMOVE_IF_EXISTS' 107 count = inst.wait_and_pop 108 if count == 0 109 directory.remove_if_exists(inst.tr) 110 else 111 directory.remove_if_exists(inst.tr, pop_tuples(inst)) 112 end 113 elsif inst.op == 'DIRECTORY_LIST' 114 count = inst.wait_and_pop 115 results = 116 if count == 0 117 directory.list(inst.tr) 118 else 119 directory.list(inst.tr, pop_tuples(inst)) 120 end 121 122 inst.push(FDB::Tuple.pack(results)) 123 elsif inst.op == 'DIRECTORY_EXISTS' 124 count = inst.wait_and_pop 125 result = 126 if count == 0 127 directory.exists?(inst.tr) 128 else 129 directory.exists?(inst.tr, pop_tuples(inst)) 130 end 131 132 if result 133 inst.push(1) 134 else 135 inst.push(0) 136 end 137 elsif inst.op == 'DIRECTORY_PACK_KEY' 138 inst.push(directory.pack(pop_tuples(inst))) 139 elsif inst.op == 'DIRECTORY_UNPACK_KEY' 140 tup = directory.unpack(inst.wait_and_pop) 141 tup.each do |t| inst.push(t) end 142 elsif inst.op == 'DIRECTORY_RANGE' 143 rng = directory.range(pop_tuples(inst)) 144 inst.push(rng[0]) 145 inst.push(rng[1]) 146 elsif inst.op == 'DIRECTORY_CONTAINS' 147 if directory.contains?(inst.wait_and_pop) 148 inst.push(1) 149 else 150 inst.push(0) 151 end 152 elsif inst.op == 'DIRECTORY_OPEN_SUBSPACE' 153 @dir_list << directory.subspace(pop_tuples(inst)) 154 elsif inst.op == 'DIRECTORY_LOG_SUBSPACE' 155 inst.tr[inst.wait_and_pop + FDB::Tuple.pack([@dir_index])] = directory.key 156 elsif inst.op == 'DIRECTORY_LOG_DIRECTORY' 157 exists = directory.exists?(inst.tr) 158 children = exists ? directory.list(inst.tr) : [] 159 log_subspace = FDB::Subspace.new([@dir_index], inst.wait_and_pop) 160 inst.tr[log_subspace['path'.encode('utf-8')]] = FDB::Tuple.pack(directory.path) 161 inst.tr[log_subspace['layer'.encode('utf-8')]] = FDB::Tuple.pack([directory.layer]) 162 inst.tr[log_subspace['exists'.encode('utf-8')]] = FDB::Tuple.pack([exists ? 1 : 0]) 163 inst.tr[log_subspace['children'.encode('utf-8')]] = FDB::Tuple.pack(children) 164 elsif inst.op == 'DIRECTORY_STRIP_PREFIX' 165 str = inst.wait_and_pop 166 throw "String #{str} does not start with raw prefix #{directory.key}" if !str.start_with?(directory.key) 167 inst.push(str[directory.key.length..-1]) 168 else 169 raise "Unknown op #{inst.op}" 170 end 171 rescue Exception => e 172 #puts "#{e}" 173 #puts e.backtrace 174 #raise 175 if @@ops_that_create_dirs.include?(inst.op) 176 @dir_list << nil 177 end 178 179 inst.push('DIRECTORY_ERROR') 180 end 181 end 182 end 183end 184 185