1
+ /**
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+ package org .apache .hadoop .hbase .master .procedure ;
19
+
20
+ import java .io .IOException ;
21
+ import java .util .Optional ;
22
+ import org .apache .hadoop .hbase .TableName ;
23
+ import org .apache .hadoop .hbase .client .TableDescriptor ;
24
+ import org .apache .hadoop .hbase .procedure2 .ProcedureStateSerializer ;
25
+ import org .apache .hadoop .hbase .procedure2 .ProcedureSuspendedException ;
26
+ import org .apache .hadoop .hbase .procedure2 .ProcedureYieldException ;
27
+ import org .apache .yetus .audience .InterfaceAudience ;
28
+ import org .slf4j .Logger ;
29
+ import org .slf4j .LoggerFactory ;
30
+
31
+ import org .apache .hadoop .hbase .shaded .protobuf .ProtobufUtil ;
32
+ import org .apache .hadoop .hbase .shaded .protobuf .generated .MasterProcedureProtos .ModifyTableDescriptorState ;
33
+ import org .apache .hadoop .hbase .shaded .protobuf .generated .MasterProcedureProtos .ModifyTableDescriptorStateData ;
34
+
35
+ /**
36
+ * The procedure will only update the table descriptor without reopening all the regions.
37
+ * <p/>
38
+ * It is usually used for migrating when upgrading, where we need to add something into the table
39
+ * descriptor, such as the rs group information.
40
+ */
41
+ @ InterfaceAudience .Private
42
+ public abstract class ModifyTableDescriptorProcedure
43
+ extends AbstractStateMachineTableProcedure <ModifyTableDescriptorState > {
44
+
45
+ private static final Logger LOG = LoggerFactory .getLogger (ModifyTableDescriptorProcedure .class );
46
+
47
+ private TableDescriptor unmodifiedTableDescriptor ;
48
+ private TableDescriptor modifiedTableDescriptor ;
49
+
50
+ protected ModifyTableDescriptorProcedure () {
51
+ }
52
+
53
+ protected ModifyTableDescriptorProcedure (MasterProcedureEnv env , TableDescriptor unmodified ) {
54
+ super (env );
55
+ this .unmodifiedTableDescriptor = unmodified ;
56
+ }
57
+
58
+ @ Override
59
+ public TableName getTableName () {
60
+ return unmodifiedTableDescriptor .getTableName ();
61
+ }
62
+
63
+ @ Override
64
+ public TableOperationType getTableOperationType () {
65
+ return TableOperationType .EDIT ;
66
+ }
67
+
68
+ /**
69
+ * Sub class should implement this method to modify the table descriptor, such as storing the rs
70
+ * group information.
71
+ * <p/>
72
+ * Since the migrating is asynchronouns, it is possible that users have already changed the rs
73
+ * group for a table, in this case we do not need to modify the table descriptor any more, then
74
+ * you could just return {@link Optional#empty()}.
75
+ */
76
+ protected abstract Optional <TableDescriptor > modify (MasterProcedureEnv env ,
77
+ TableDescriptor current ) throws IOException ;
78
+
79
+ @ Override
80
+ protected Flow executeFromState (MasterProcedureEnv env , ModifyTableDescriptorState state )
81
+ throws ProcedureSuspendedException , ProcedureYieldException , InterruptedException {
82
+ try {
83
+ switch (state ) {
84
+ case MODIFY_TABLE_DESCRIPTOR_PREPARE :
85
+ Optional <TableDescriptor > modified = modify (env , unmodifiedTableDescriptor );
86
+ if (modified .isPresent ()) {
87
+ modifiedTableDescriptor = modified .get ();
88
+ setNextState (ModifyTableDescriptorState .MODIFY_TABLE_DESCRIPTOR_UPDATE );
89
+ return Flow .HAS_MORE_STATE ;
90
+ } else {
91
+ // do not need to modify
92
+ return Flow .NO_MORE_STATE ;
93
+ }
94
+ case MODIFY_TABLE_DESCRIPTOR_UPDATE :
95
+ env .getMasterServices ().getTableDescriptors ().update (modifiedTableDescriptor );
96
+ return Flow .NO_MORE_STATE ;
97
+ default :
98
+ throw new UnsupportedOperationException ("unhandled state=" + state );
99
+ }
100
+ } catch (IOException e ) {
101
+ if (isRollbackSupported (state )) {
102
+ setFailure ("master-modify-table-descriptor" , e );
103
+ } else {
104
+ LOG .warn ("Retriable error trying to modify table descriptor={} (in state={})" ,
105
+ getTableName (), state , e );
106
+ }
107
+ }
108
+ return Flow .HAS_MORE_STATE ;
109
+ }
110
+
111
+ @ Override
112
+ protected void rollbackState (MasterProcedureEnv env , ModifyTableDescriptorState state )
113
+ throws IOException , InterruptedException {
114
+ if (state == ModifyTableDescriptorState .MODIFY_TABLE_DESCRIPTOR_PREPARE ) {
115
+ return ;
116
+ }
117
+ throw new UnsupportedOperationException ("unhandled state=" + state );
118
+ }
119
+
120
+ @ Override
121
+ protected boolean isRollbackSupported (ModifyTableDescriptorState state ) {
122
+ return state == ModifyTableDescriptorState .MODIFY_TABLE_DESCRIPTOR_PREPARE ;
123
+ }
124
+
125
+ @ Override
126
+ protected ModifyTableDescriptorState getState (int stateId ) {
127
+ return ModifyTableDescriptorState .forNumber (stateId );
128
+ }
129
+
130
+ @ Override
131
+ protected int getStateId (ModifyTableDescriptorState state ) {
132
+ return state .getNumber ();
133
+ }
134
+
135
+ @ Override
136
+ protected ModifyTableDescriptorState getInitialState () {
137
+ return ModifyTableDescriptorState .MODIFY_TABLE_DESCRIPTOR_PREPARE ;
138
+ }
139
+
140
+ @ Override
141
+ protected void serializeStateData (ProcedureStateSerializer serializer ) throws IOException {
142
+ super .serializeStateData (serializer );
143
+ ModifyTableDescriptorStateData .Builder builder = ModifyTableDescriptorStateData .newBuilder ()
144
+ .setUnmodifiedTableSchema (ProtobufUtil .toTableSchema (unmodifiedTableDescriptor ));
145
+ if (modifiedTableDescriptor != null ) {
146
+ builder .setModifiedTableSchema (ProtobufUtil .toTableSchema (modifiedTableDescriptor ));
147
+ }
148
+ serializer .serialize (builder .build ());
149
+ }
150
+
151
+ @ Override
152
+ protected void deserializeStateData (ProcedureStateSerializer serializer ) throws IOException {
153
+ super .deserializeStateData (serializer );
154
+ ModifyTableDescriptorStateData data =
155
+ serializer .deserialize (ModifyTableDescriptorStateData .class );
156
+ unmodifiedTableDescriptor = ProtobufUtil .toTableDescriptor (data .getUnmodifiedTableSchema ());
157
+ if (data .hasModifiedTableSchema ()) {
158
+ modifiedTableDescriptor = ProtobufUtil .toTableDescriptor (data .getModifiedTableSchema ());
159
+ }
160
+ }
161
+ }
0 commit comments