* Represents a range of tokens on a Cassandra ring. * * A range is start-exclusive and end-inclusive. It is empty when * start and end are the same token, except if that is the minimum * token, in which case the range covers the whole ring (this is * consistent with the behavior of CQL range q
| 135 | * in a range, see {@link unwrap}. |
| 136 | */ |
| 137 | class TokenRange { |
| 138 | constructor(start, end, tokenizer) { |
| 139 | this.start = start; |
| 140 | this.end = end; |
| 141 | Object.defineProperty(this, '_tokenizer', { value: tokenizer, enumerable: false}); |
| 142 | } |
| 143 | |
| 144 | /** |
| 145 | * Splits this range into a number of smaller ranges of equal "size" |
| 146 | * (referring to the number of tokens, not the actual amount of data). |
| 147 | * |
| 148 | * Splitting an empty range is not permitted. But not that, in edge |
| 149 | * cases, splitting a range might produce one or more empty ranges. |
| 150 | * |
| 151 | * @param {Number} numberOfSplits Number of splits to make. |
| 152 | * @returns {TokenRange[]} Split ranges. |
| 153 | * @throws {Error} If splitting an empty range. |
| 154 | */ |
| 155 | splitEvenly(numberOfSplits) { |
| 156 | if (numberOfSplits < 1) { |
| 157 | throw new Error(util.format("numberOfSplits (%d) must be greater than 0.", numberOfSplits)); |
| 158 | } |
| 159 | if (this.isEmpty()) { |
| 160 | throw new Error("Can't split empty range " + this.toString()); |
| 161 | } |
| 162 | |
| 163 | const tokenRanges = []; |
| 164 | const splitPoints = this._tokenizer.split(this.start, this.end, numberOfSplits); |
| 165 | let splitStart = this.start; |
| 166 | let splitEnd; |
| 167 | for (let splitIndex = 0; splitIndex < splitPoints.length; splitIndex++) { |
| 168 | splitEnd = splitPoints[splitIndex]; |
| 169 | tokenRanges.push(new TokenRange(splitStart, splitEnd, this._tokenizer)); |
| 170 | splitStart = splitEnd; |
| 171 | } |
| 172 | tokenRanges.push(new TokenRange(splitStart, this.end, this._tokenizer)); |
| 173 | return tokenRanges; |
| 174 | } |
| 175 | |
| 176 | /** |
| 177 | * A range is empty when start and end are the same token, except if |
| 178 | * that is the minimum token, in which case the range covers the |
| 179 | * whole ring. This is consistent with the behavior of CQL range |
| 180 | * queries. |
| 181 | * |
| 182 | * @returns {boolean} Whether this range is empty. |
| 183 | */ |
| 184 | isEmpty() { |
| 185 | return this.start.equals(this.end) && !this.start.equals(this._tokenizer.minToken()); |
| 186 | } |
| 187 | |
| 188 | /** |
| 189 | * A range wraps around the end of the ring when the start token |
| 190 | * is greater than the end token and the end token is not the |
| 191 | * minimum token. |
| 192 | * |
| 193 | * @returns {boolean} Whether this range wraps around. |
| 194 | */ |
nothing calls this directly
no outgoing calls
no test coverage detected