回源码主页即时通讯网 - 即时通讯开发者社区!
1   /*
2    * Copyright (c) 2017 Baidu, Inc. All Rights Reserve.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.baidu.fsg.uid;
17  
18  import org.apache.commons.lang.builder.ToStringBuilder;
19  import org.apache.commons.lang.builder.ToStringStyle;
20  import org.springframework.util.Assert;
21  
22  /**
23   * Allocate 64 bits for the UID(long)<br>
24   * sign (fixed 1bit) -> deltaSecond -> workerId -> sequence(within the same second)
25   * 
26   * @author yutianbao
27   */
28  public class BitsAllocator {
29      /**
30       * Total 64 bits
31       */
32      public static final int TOTAL_BITS = 1 << 6;
33  
34      /**
35       * Bits for [sign-> second-> workId-> sequence]
36       */
37      private int signBits = 1;
38      private final int timestampBits;
39      private final int workerIdBits;
40      private final int sequenceBits;
41  
42      /**
43       * Max value for workId & sequence
44       */
45      private final long maxDeltaSeconds;
46      private final long maxWorkerId;
47      private final long maxSequence;
48  
49      /**
50       * Shift for timestamp & workerId
51       */
52      private final int timestampShift;
53      private final int workerIdShift;
54  
55      /**
56       * Constructor with timestampBits, workerIdBits, sequenceBits<br>
57       * The highest bit used for sign, so <code>63</code> bits for timestampBits, workerIdBits, sequenceBits
58       */
59      public BitsAllocator(int timestampBits, int workerIdBits, int sequenceBits) {
60          // make sure allocated 64 bits
61          int allocateTotalBits = signBits + timestampBits + workerIdBits + sequenceBits;
62          Assert.isTrue(allocateTotalBits == TOTAL_BITS, "allocate not enough 64 bits");
63  
64          // initialize bits
65          this.timestampBits = timestampBits;
66          this.workerIdBits = workerIdBits;
67          this.sequenceBits = sequenceBits;
68  
69          // initialize max value
70          this.maxDeltaSeconds = ~(-1L << timestampBits);
71          this.maxWorkerId = ~(-1L << workerIdBits);
72          this.maxSequence = ~(-1L << sequenceBits);
73  
74          // initialize shift
75          this.timestampShift = workerIdBits + sequenceBits;
76          this.workerIdShift = sequenceBits;
77      }
78  
79      /**
80       * Allocate bits for UID according to delta seconds & workerId & sequence<br>
81       * <b>Note that: </b>The highest bit will always be 0 for sign
82       * 
83       * @param deltaSeconds
84       * @param workerId
85       * @param sequence
86       * @return
87       */
88      public long allocate(long deltaSeconds, long workerId, long sequence) {
89          return (deltaSeconds << timestampShift) | (workerId << workerIdShift) | sequence;
90      }
91      
92      /**
93       * Getters
94       */
95      public int getSignBits() {
96          return signBits;
97      }
98  
99      public int getTimestampBits() {
100         return timestampBits;
101     }
102 
103     public int getWorkerIdBits() {
104         return workerIdBits;
105     }
106 
107     public int getSequenceBits() {
108         return sequenceBits;
109     }
110 
111     public long getMaxDeltaSeconds() {
112         return maxDeltaSeconds;
113     }
114 
115     public long getMaxWorkerId() {
116         return maxWorkerId;
117     }
118 
119     public long getMaxSequence() {
120         return maxSequence;
121     }
122 
123     public int getTimestampShift() {
124         return timestampShift;
125     }
126 
127     public int getWorkerIdShift() {
128         return workerIdShift;
129     }
130     
131     @Override
132     public String toString() {
133         return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
134     }
135     
136 }