1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase;
20
21 import java.io.IOException;
22 import java.security.PrivilegedAction;
23 import java.util.ArrayList;
24 import java.util.List;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hadoop.hbase.classification.InterfaceAudience;
29 import org.apache.hadoop.hbase.classification.InterfaceStability;
30 import org.apache.hadoop.conf.Configuration;
31 import org.apache.hadoop.fs.FileSystem;
32 import org.apache.hadoop.hbase.master.HMaster;
33 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.AdminService;
34 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ClientService;
35 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MasterService;
36 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionServerStartupResponse;
37 import org.apache.hadoop.hbase.regionserver.HRegion;
38 import org.apache.hadoop.hbase.regionserver.HRegionServer;
39 import org.apache.hadoop.hbase.regionserver.Region;
40 import org.apache.hadoop.hbase.security.User;
41 import org.apache.hadoop.hbase.test.MetricsAssertHelper;
42 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
43 import org.apache.hadoop.hbase.util.JVMClusterUtil;
44 import org.apache.hadoop.hbase.util.JVMClusterUtil.MasterThread;
45 import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread;
46 import org.apache.hadoop.hbase.util.Threads;
47
48
49
50
51
52
53
54 @InterfaceAudience.Public
55 @InterfaceStability.Evolving
56 public class MiniHBaseCluster extends HBaseCluster {
57 private static final Log LOG = LogFactory.getLog(MiniHBaseCluster.class.getName());
58 public LocalHBaseCluster hbaseCluster;
59 private static int index;
60
61
62
63
64
65
66
67 public MiniHBaseCluster(Configuration conf, int numRegionServers)
68 throws IOException, InterruptedException {
69 this(conf, 1, numRegionServers);
70 }
71
72
73
74
75
76
77
78
79 public MiniHBaseCluster(Configuration conf, int numMasters, int numRegionServers)
80 throws IOException, InterruptedException {
81 this(conf, numMasters, numRegionServers, null, null);
82 }
83
84 public MiniHBaseCluster(Configuration conf, int numMasters, int numRegionServers,
85 Class<? extends HMaster> masterClass,
86 Class<? extends MiniHBaseCluster.MiniHBaseClusterRegionServer> regionserverClass)
87 throws IOException, InterruptedException {
88 super(conf);
89 if (conf.getBoolean(LocalHBaseCluster.ASSIGN_RANDOM_PORTS, true)) {
90 conf.set(HConstants.MASTER_PORT, "0");
91 if (conf.getInt(HConstants.MASTER_INFO_PORT, 0) != -1) {
92 conf.set(HConstants.MASTER_INFO_PORT, "0");
93 }
94 }
95
96
97 CompatibilityFactory.getInstance(MetricsAssertHelper.class).init();
98
99 init(numMasters, numRegionServers, masterClass, regionserverClass);
100 this.initialClusterStatus = getClusterStatus();
101 }
102
103 public Configuration getConfiguration() {
104 return this.conf;
105 }
106
107
108
109
110
111
112
113 public static class MiniHBaseClusterRegionServer extends HRegionServer {
114 private Thread shutdownThread = null;
115 private User user = null;
116
117 public MiniHBaseClusterRegionServer(Configuration conf, CoordinatedStateManager cp)
118 throws IOException, InterruptedException {
119 super(conf, cp);
120 this.user = User.getCurrent();
121 }
122
123
124
125
126
127
128
129
130
131 @Override
132 protected void handleReportForDutyResponse(
133 final RegionServerStartupResponse c) throws IOException {
134 super.handleReportForDutyResponse(c);
135
136 this.shutdownThread = new SingleFileSystemShutdownThread(getFileSystem());
137 }
138
139 @Override
140 public void run() {
141 try {
142 this.user.runAs(new PrivilegedAction<Object>(){
143 public Object run() {
144 runRegionServer();
145 return null;
146 }
147 });
148 } catch (Throwable t) {
149 LOG.error("Exception in run", t);
150 } finally {
151
152 if (this.shutdownThread != null) {
153 this.shutdownThread.start();
154 Threads.shutdown(this.shutdownThread, 30000);
155 }
156 }
157 }
158
159 private void runRegionServer() {
160 super.run();
161 }
162
163 @Override
164 public void kill() {
165 super.kill();
166 }
167
168 @Override
169 public void abort(final String reason, final Throwable cause) {
170 this.user.runAs(new PrivilegedAction<Object>() {
171 public Object run() {
172 abortRegionServer(reason, cause);
173 return null;
174 }
175 });
176 }
177
178 private void abortRegionServer(String reason, Throwable cause) {
179 super.abort(reason, cause);
180 }
181 }
182
183
184
185
186
187 static class SingleFileSystemShutdownThread extends Thread {
188 private final FileSystem fs;
189 SingleFileSystemShutdownThread(final FileSystem fs) {
190 super("Shutdown of " + fs);
191 this.fs = fs;
192 }
193 @Override
194 public void run() {
195 try {
196 LOG.info("Hook closing fs=" + this.fs);
197 this.fs.close();
198 } catch (NullPointerException npe) {
199 LOG.debug("Need to fix these: " + npe.toString());
200 } catch (IOException e) {
201 LOG.warn("Running hook", e);
202 }
203 }
204 }
205
206 private void init(final int nMasterNodes, final int nRegionNodes,
207 Class<? extends HMaster> masterClass,
208 Class<? extends MiniHBaseCluster.MiniHBaseClusterRegionServer> regionserverClass)
209 throws IOException, InterruptedException {
210 try {
211 if (masterClass == null){
212 masterClass = HMaster.class;
213 }
214 if (regionserverClass == null){
215 regionserverClass = MiniHBaseCluster.MiniHBaseClusterRegionServer.class;
216 }
217
218
219 hbaseCluster = new LocalHBaseCluster(conf, nMasterNodes, 0,
220 masterClass, regionserverClass);
221
222
223 for (int i=0; i<nRegionNodes; i++) {
224 Configuration rsConf = HBaseConfiguration.create(conf);
225 User user = HBaseTestingUtility.getDifferentUser(rsConf,
226 ".hfs."+index++);
227 hbaseCluster.addRegionServer(rsConf, i, user);
228 }
229
230 hbaseCluster.startup();
231 } catch (IOException e) {
232 shutdown();
233 throw e;
234 } catch (Throwable t) {
235 LOG.error("Error starting cluster", t);
236 shutdown();
237 throw new IOException("Shutting down", t);
238 }
239 }
240
241 @Override
242 public void startRegionServer(String hostname, int port) throws IOException {
243 this.startRegionServer();
244 }
245
246 @Override
247 public void killRegionServer(ServerName serverName) throws IOException {
248 HRegionServer server = getRegionServer(getRegionServerIndex(serverName));
249 if (server instanceof MiniHBaseClusterRegionServer) {
250 LOG.info("Killing " + server.toString());
251 ((MiniHBaseClusterRegionServer) server).kill();
252 } else {
253 abortRegionServer(getRegionServerIndex(serverName));
254 }
255 }
256
257 @Override
258 public void stopRegionServer(ServerName serverName) throws IOException {
259 stopRegionServer(getRegionServerIndex(serverName));
260 }
261
262 @Override
263 public void suspendRegionServer(ServerName serverName) throws IOException {
264 suspendRegionServer(getRegionServerIndex(serverName));
265 }
266
267 @Override
268 public void resumeRegionServer(ServerName serverName) throws IOException {
269 resumeRegionServer(getRegionServerIndex(serverName));
270 }
271
272 @Override
273 public void waitForRegionServerToStop(ServerName serverName, long timeout) throws IOException {
274
275 waitOnRegionServer(getRegionServerIndex(serverName));
276 }
277
278 @Override
279 public void startZkNode(String hostname, int port) throws IOException {
280 LOG.warn("Starting zookeeper nodes on mini cluster is not supported");
281 }
282
283 @Override
284 public void killZkNode(ServerName serverName) throws IOException {
285 LOG.warn("Aborting zookeeper nodes on mini cluster is not supported");
286 }
287
288 @Override
289 public void stopZkNode(ServerName serverName) throws IOException {
290 LOG.warn("Stopping zookeeper nodes on mini cluster is not supported");
291 }
292
293 @Override
294 public void waitForZkNodeToStart(ServerName serverName, long timeout) throws IOException {
295 LOG.warn("Waiting for zookeeper nodes to start on mini cluster is not supported");
296 }
297
298 @Override
299 public void waitForZkNodeToStop(ServerName serverName, long timeout) throws IOException {
300 LOG.warn("Waiting for zookeeper nodes to stop on mini cluster is not supported");
301 }
302
303 @Override
304 public void startDataNode(ServerName serverName) throws IOException {
305 LOG.warn("Starting datanodes on mini cluster is not supported");
306 }
307
308 @Override
309 public void killDataNode(ServerName serverName) throws IOException {
310 LOG.warn("Aborting datanodes on mini cluster is not supported");
311 }
312
313 @Override
314 public void stopDataNode(ServerName serverName) throws IOException {
315 LOG.warn("Stopping datanodes on mini cluster is not supported");
316 }
317
318 @Override
319 public void waitForDataNodeToStart(ServerName serverName, long timeout) throws IOException {
320 LOG.warn("Waiting for datanodes to start on mini cluster is not supported");
321 }
322
323 @Override
324 public void waitForDataNodeToStop(ServerName serverName, long timeout) throws IOException {
325 LOG.warn("Waiting for datanodes to stop on mini cluster is not supported");
326 }
327
328 @Override
329 public void startNameNode(ServerName serverName) throws IOException {
330 LOG.warn("Starting namenodes on mini cluster is not supported");
331 }
332
333 @Override
334 public void killNameNode(ServerName serverName) throws IOException {
335 LOG.warn("Aborting namenodes on mini cluster is not supported");
336 }
337
338 @Override
339 public void stopNameNode(ServerName serverName) throws IOException {
340 LOG.warn("Stopping namenodes on mini cluster is not supported");
341 }
342
343 @Override
344 public void waitForNameNodeToStart(ServerName serverName, long timeout) throws IOException {
345 LOG.warn("Waiting for namenodes to start on mini cluster is not supported");
346 }
347
348 @Override
349 public void waitForNameNodeToStop(ServerName serverName, long timeout) throws IOException {
350 LOG.warn("Waiting for namenodes to stop on mini cluster is not supported");
351 }
352
353 @Override
354 public void startMaster(String hostname, int port) throws IOException {
355 this.startMaster();
356 }
357
358 @Override
359 public void killMaster(ServerName serverName) throws IOException {
360 abortMaster(getMasterIndex(serverName));
361 }
362
363 @Override
364 public void stopMaster(ServerName serverName) throws IOException {
365 stopMaster(getMasterIndex(serverName));
366 }
367
368 @Override
369 public void waitForMasterToStop(ServerName serverName, long timeout) throws IOException {
370
371 waitOnMaster(getMasterIndex(serverName));
372 }
373
374
375
376
377
378
379
380 public JVMClusterUtil.RegionServerThread startRegionServer()
381 throws IOException {
382 final Configuration newConf = HBaseConfiguration.create(conf);
383 User rsUser =
384 HBaseTestingUtility.getDifferentUser(newConf, ".hfs."+index++);
385 JVMClusterUtil.RegionServerThread t = null;
386 try {
387 t = hbaseCluster.addRegionServer(
388 newConf, hbaseCluster.getRegionServers().size(), rsUser);
389 t.start();
390 t.waitForServerOnline();
391 } catch (InterruptedException ie) {
392 throw new IOException("Interrupted adding regionserver to cluster", ie);
393 }
394 return t;
395 }
396
397
398
399
400
401
402
403
404 public JVMClusterUtil.RegionServerThread startRegionServerAndWait(long timeout)
405 throws IOException {
406
407 JVMClusterUtil.RegionServerThread t = startRegionServer();
408 ServerName rsServerName = t.getRegionServer().getServerName();
409
410 long start = EnvironmentEdgeManager.currentTime();
411 while ((EnvironmentEdgeManager.currentTime() - start) < timeout) {
412 ClusterStatus clusterStatus = getMaster().getClusterStatus();
413 if (clusterStatus != null && clusterStatus.getLiveServersLoad().containsKey(rsServerName)) {
414 return t;
415 }
416 Threads.sleep(100);
417 }
418 if (t.getRegionServer().isOnline()) {
419 throw new IOException("RS: " + rsServerName + " online, but not processed by master");
420 } else {
421 throw new IOException("RS: " + rsServerName + " is offline");
422 }
423 }
424
425
426
427
428
429 public String abortRegionServer(int serverNumber) {
430 HRegionServer server = getRegionServer(serverNumber);
431 LOG.info("Aborting " + server.toString());
432 server.abort("Aborting for tests", new Exception("Trace info"));
433 return server.toString();
434 }
435
436
437
438
439
440
441
442 public JVMClusterUtil.RegionServerThread stopRegionServer(int serverNumber) {
443 return stopRegionServer(serverNumber, true);
444 }
445
446
447
448
449
450
451
452
453
454
455
456 public JVMClusterUtil.RegionServerThread stopRegionServer(int serverNumber,
457 final boolean shutdownFS) {
458 JVMClusterUtil.RegionServerThread server =
459 hbaseCluster.getRegionServers().get(serverNumber);
460 LOG.info("Stopping " + server.toString());
461 server.getRegionServer().stop("Stopping rs " + serverNumber);
462 return server;
463 }
464
465
466
467
468
469
470 public JVMClusterUtil.RegionServerThread suspendRegionServer(int serverNumber) {
471 JVMClusterUtil.RegionServerThread server =
472 hbaseCluster.getRegionServers().get(serverNumber);
473 LOG.info("Suspending " + server.toString());
474 server.suspend();
475 return server;
476 }
477
478
479
480
481
482
483 public JVMClusterUtil.RegionServerThread resumeRegionServer(int serverNumber) {
484 JVMClusterUtil.RegionServerThread server =
485 hbaseCluster.getRegionServers().get(serverNumber);
486 LOG.info("Resuming " + server.toString());
487 server.resume();
488 return server;
489 }
490
491
492
493
494
495
496
497 public String waitOnRegionServer(final int serverNumber) {
498 return this.hbaseCluster.waitOnRegionServer(serverNumber);
499 }
500
501
502
503
504
505
506
507
508 public JVMClusterUtil.MasterThread startMaster() throws IOException {
509 Configuration c = HBaseConfiguration.create(conf);
510 User user =
511 HBaseTestingUtility.getDifferentUser(c, ".hfs."+index++);
512
513 JVMClusterUtil.MasterThread t = null;
514 try {
515 t = hbaseCluster.addMaster(c, hbaseCluster.getMasters().size(), user);
516 t.start();
517 } catch (InterruptedException ie) {
518 throw new IOException("Interrupted adding master to cluster", ie);
519 }
520 return t;
521 }
522
523
524
525
526
527 public MasterService.BlockingInterface getMasterAdminService() {
528 return this.hbaseCluster.getActiveMaster().getMasterRpcServices();
529 }
530
531
532
533
534
535 public HMaster getMaster() {
536 return this.hbaseCluster.getActiveMaster();
537 }
538
539
540
541
542
543 public MasterThread getMasterThread() {
544 for (MasterThread mt: hbaseCluster.getLiveMasters()) {
545 if (mt.getMaster().isActiveMaster()) {
546 return mt;
547 }
548 }
549 return null;
550 }
551
552
553
554
555
556 public HMaster getMaster(final int serverNumber) {
557 return this.hbaseCluster.getMaster(serverNumber);
558 }
559
560
561
562
563
564 public String abortMaster(int serverNumber) {
565 HMaster server = getMaster(serverNumber);
566 LOG.info("Aborting " + server.toString());
567 server.abort("Aborting for tests", new Exception("Trace info"));
568 return server.toString();
569 }
570
571
572
573
574
575
576
577 public JVMClusterUtil.MasterThread stopMaster(int serverNumber) {
578 return stopMaster(serverNumber, true);
579 }
580
581
582
583
584
585
586
587
588
589
590
591 public JVMClusterUtil.MasterThread stopMaster(int serverNumber,
592 final boolean shutdownFS) {
593 JVMClusterUtil.MasterThread server =
594 hbaseCluster.getMasters().get(serverNumber);
595 LOG.info("Stopping " + server.toString());
596 server.getMaster().stop("Stopping master " + serverNumber);
597 return server;
598 }
599
600
601
602
603
604
605
606 public String waitOnMaster(final int serverNumber) {
607 return this.hbaseCluster.waitOnMaster(serverNumber);
608 }
609
610
611
612
613
614
615
616
617
618 public boolean waitForActiveAndReadyMaster(long timeout) throws IOException {
619 List<JVMClusterUtil.MasterThread> mts;
620 long start = System.currentTimeMillis();
621 while (!(mts = getMasterThreads()).isEmpty()
622 && (System.currentTimeMillis() - start) < timeout) {
623 for (JVMClusterUtil.MasterThread mt : mts) {
624 if (mt.getMaster().isActiveMaster() && mt.getMaster().isInitialized()) {
625 return true;
626 }
627 }
628
629 Threads.sleep(100);
630 }
631 return false;
632 }
633
634
635
636
637 public List<JVMClusterUtil.MasterThread> getMasterThreads() {
638 return this.hbaseCluster.getMasters();
639 }
640
641
642
643
644 public List<JVMClusterUtil.MasterThread> getLiveMasterThreads() {
645 return this.hbaseCluster.getLiveMasters();
646 }
647
648
649
650
651 public void join() {
652 this.hbaseCluster.join();
653 }
654
655
656
657
658
659 @SuppressWarnings("deprecation")
660 public void shutdown() throws IOException {
661 if (this.hbaseCluster != null) {
662 this.hbaseCluster.shutdown();
663 }
664 }
665
666 @Override
667 public void close() throws IOException {
668 }
669
670 @Override
671 public ClusterStatus getClusterStatus() throws IOException {
672 HMaster master = getMaster();
673 return master == null ? null : master.getClusterStatus();
674 }
675
676
677
678
679
680 public void flushcache() throws IOException {
681 for (JVMClusterUtil.RegionServerThread t:
682 this.hbaseCluster.getRegionServers()) {
683 for(Region r: t.getRegionServer().getOnlineRegionsLocalContext()) {
684 r.flush(true);
685 }
686 }
687 }
688
689
690
691
692
693 public void flushcache(TableName tableName) throws IOException {
694 for (JVMClusterUtil.RegionServerThread t:
695 this.hbaseCluster.getRegionServers()) {
696 for(Region r: t.getRegionServer().getOnlineRegionsLocalContext()) {
697 if(r.getTableDesc().getTableName().equals(tableName)) {
698 r.flush(true);
699 }
700 }
701 }
702 }
703
704
705
706
707
708 public void compact(boolean major) throws IOException {
709 for (JVMClusterUtil.RegionServerThread t:
710 this.hbaseCluster.getRegionServers()) {
711 for(Region r: t.getRegionServer().getOnlineRegionsLocalContext()) {
712 r.compact(major);
713 }
714 }
715 }
716
717
718
719
720
721 public void compact(TableName tableName, boolean major) throws IOException {
722 for (JVMClusterUtil.RegionServerThread t:
723 this.hbaseCluster.getRegionServers()) {
724 for(Region r: t.getRegionServer().getOnlineRegionsLocalContext()) {
725 if(r.getTableDesc().getTableName().equals(tableName)) {
726 r.compact(major);
727 }
728 }
729 }
730 }
731
732
733
734
735 public List<JVMClusterUtil.RegionServerThread> getRegionServerThreads() {
736 return this.hbaseCluster.getRegionServers();
737 }
738
739
740
741
742 public List<JVMClusterUtil.RegionServerThread> getLiveRegionServerThreads() {
743 return this.hbaseCluster.getLiveRegionServers();
744 }
745
746
747
748
749
750
751 public HRegionServer getRegionServer(int serverNumber) {
752 return hbaseCluster.getRegionServer(serverNumber);
753 }
754
755 public HRegionServer getRegionServer(ServerName serverName) {
756 for (RegionServerThread t : hbaseCluster.getRegionServers()) {
757 HRegionServer r = t.getRegionServer();
758 if (r.getServerName().equals(serverName)) {
759 return r;
760 }
761 }
762 return null;
763 }
764
765 public List<HRegion> getRegions(byte[] tableName) {
766 return getRegions(TableName.valueOf(tableName));
767 }
768
769 public List<HRegion> getRegions(TableName tableName) {
770 List<HRegion> ret = new ArrayList<HRegion>();
771 for (JVMClusterUtil.RegionServerThread rst : getRegionServerThreads()) {
772 HRegionServer hrs = rst.getRegionServer();
773 for (Region region : hrs.getOnlineRegionsLocalContext()) {
774 if (region.getTableDesc().getTableName().equals(tableName)) {
775 ret.add((HRegion)region);
776 }
777 }
778 }
779 return ret;
780 }
781
782
783
784
785
786 public int getServerWithMeta() {
787 return getServerWith(HRegionInfo.FIRST_META_REGIONINFO.getRegionName());
788 }
789
790
791
792
793
794
795
796 public int getServerWith(byte[] regionName) {
797 int index = -1;
798 int count = 0;
799 for (JVMClusterUtil.RegionServerThread rst: getRegionServerThreads()) {
800 HRegionServer hrs = rst.getRegionServer();
801 if (!hrs.isStopped()) {
802 Region region = hrs.getOnlineRegion(regionName);
803 if (region != null) {
804 index = count;
805 break;
806 }
807 }
808 count++;
809 }
810 return index;
811 }
812
813 @Override
814 public ServerName getServerHoldingRegion(final TableName tn, byte[] regionName)
815 throws IOException {
816
817
818
819
820 HMaster master = getMaster();
821 Region region = master.getOnlineRegion(regionName);
822 if (region != null) {
823 return master.getServerName();
824 }
825 int index = getServerWith(regionName);
826 if (index < 0) {
827 return null;
828 }
829 return getRegionServer(index).getServerName();
830 }
831
832
833
834
835
836
837
838 public long countServedRegions() {
839 long count = 0;
840 for (JVMClusterUtil.RegionServerThread rst : getLiveRegionServerThreads()) {
841 count += rst.getRegionServer().getNumberOfOnlineRegions();
842 }
843 for (JVMClusterUtil.MasterThread mt : getLiveMasterThreads()) {
844 count += mt.getMaster().getNumberOfOnlineRegions();
845 }
846 return count;
847 }
848
849
850
851
852
853 public void killAll() {
854 for (RegionServerThread rst : getRegionServerThreads()) {
855 rst.getRegionServer().abort("killAll");
856 }
857 for (MasterThread masterThread : getMasterThreads()) {
858 masterThread.getMaster().abort("killAll", new Throwable());
859 }
860 }
861
862 @Override
863 public void waitUntilShutDown() {
864 this.hbaseCluster.join();
865 }
866
867 public List<HRegion> findRegionsForTable(TableName tableName) {
868 ArrayList<HRegion> ret = new ArrayList<HRegion>();
869 for (JVMClusterUtil.RegionServerThread rst : getRegionServerThreads()) {
870 HRegionServer hrs = rst.getRegionServer();
871 for (Region region : hrs.getOnlineRegions(tableName)) {
872 if (region.getTableDesc().getTableName().equals(tableName)) {
873 ret.add((HRegion)region);
874 }
875 }
876 }
877 return ret;
878 }
879
880
881 protected int getRegionServerIndex(ServerName serverName) {
882
883 List<RegionServerThread> servers = getRegionServerThreads();
884 for (int i=0; i < servers.size(); i++) {
885 if (servers.get(i).getRegionServer().getServerName().equals(serverName)) {
886 return i;
887 }
888 }
889 return -1;
890 }
891
892 protected int getMasterIndex(ServerName serverName) {
893 List<MasterThread> masters = getMasterThreads();
894 for (int i = 0; i < masters.size(); i++) {
895 if (masters.get(i).getMaster().getServerName().equals(serverName)) {
896 return i;
897 }
898 }
899 return -1;
900 }
901
902 @Override
903 public AdminService.BlockingInterface getAdminProtocol(ServerName serverName) throws IOException {
904 return getRegionServer(getRegionServerIndex(serverName)).getRSRpcServices();
905 }
906
907 @Override
908 public ClientService.BlockingInterface getClientProtocol(ServerName serverName)
909 throws IOException {
910 return getRegionServer(getRegionServerIndex(serverName)).getRSRpcServices();
911 }
912 }