/** * Releases all the resources used by this Kiji instance. * * @throws IOException on I/O error. */ private void close() throws IOException { final State oldState = mState.getAndSet(State.CLOSED); Preconditions.checkState( oldState == State.OPEN, "Cannot close Kiji instance %s in state %s.", this, oldState); LOG.debug("Closing {}.", this); if (mMonitor != null) { try { mMonitor.unregisterInstanceUser(mURI, mKijiClientId, mSystemVersion.toString()); } catch (KeeperException ke) { // Unrecoverable ZooKeeper error: throw new IOException(ke); } mMonitor.close(); } if (mZKClient != null) { mZKClient.release(); } ResourceUtils.closeOrLog(mMetaTable); ResourceUtils.closeOrLog(mSystemTable); ResourceUtils.closeOrLog(mSchemaTable); ResourceUtils.closeOrLog(mSecurityManager); ResourceUtils.closeOrLog(mAdmin); mSchemaTable = null; mMetaTable = null; mAdmin = null; mSecurityManager = null; LOG.debug("{} closed.", this); }
/** * Creates a Kiji table in an HBase instance, without checking for validation compatibility and * without applying permissions. * * @param tableLayout The initial layout of the table (with unassigned column ids). * @param splitKeys The initial key boundaries between regions. There will be splitKeys + 1 * regions created. Pass null to specify the default single region. * @throws IOException on I/O error. * @throws KijiAlreadyExistsException if the table already exists. */ private void createTableUnchecked(TableLayoutDesc tableLayout, byte[][] splitKeys) throws IOException { final KijiURI tableURI = KijiURI.newBuilder(mURI).withTableName(tableLayout.getName()).build(); // This will validate the layout and may throw an InvalidLayoutException. final KijiTableLayout kijiTableLayout = KijiTableLayout.newLayout(tableLayout); if (getMetaTable().tableExists(tableLayout.getName())) { throw new KijiAlreadyExistsException( String.format("Kiji table '%s' already exists.", tableURI), tableURI); } if (tableLayout.getKeysFormat() instanceof RowKeyFormat) { LOG.warn("Usage of 'RowKeyFormat' is deprecated. New tables should use 'RowKeyFormat2'."); } getMetaTable().updateTableLayout(tableLayout.getName(), tableLayout); if (mSystemVersion.compareTo(Versions.SYSTEM_2_0) >= 0) { // system-2.0 clients retrieve the table layout from ZooKeeper as a stream of notifications. // Invariant: ZooKeeper hold the most recent layout of the table. LOG.debug("Writing initial table layout in ZooKeeper for table {}.", tableURI); try { final ZooKeeperMonitor monitor = new ZooKeeperMonitor(mZKClient); try { final byte[] layoutId = Bytes.toBytes(kijiTableLayout.getDesc().getLayoutId()); monitor.notifyNewTableLayout(tableURI, layoutId, -1); } finally { monitor.close(); } } catch (KeeperException ke) { throw new IOException(ke); } } try { final HTableSchemaTranslator translator = new HTableSchemaTranslator(); final HTableDescriptor desc = translator.toHTableDescriptor(mURI.getInstance(), kijiTableLayout); LOG.debug("Creating HBase table '{}'.", desc.getNameAsString()); if (null != splitKeys) { getHBaseAdmin().createTable(desc, splitKeys); } else { getHBaseAdmin().createTable(desc); } } catch (TableExistsException tee) { throw new KijiAlreadyExistsException( String.format("Kiji table '%s' already exists.", tableURI), tableURI); } }
/** * Creates a new <code>HBaseKiji</code> instance. * * <p>Should only be used by Kiji.Factory.open(). * * <p>Caller does not need to use retain(), but must call release() when done with it. * * @param kijiURI the KijiURI. * @param conf Hadoop Configuration. Deep copied internally. * @param tableFactory HTableInterface factory. * @param lockFactory Factory for locks. * @throws IOException on I/O error. */ HBaseKiji( KijiURI kijiURI, Configuration conf, HTableInterfaceFactory tableFactory, LockFactory lockFactory) throws IOException { mConstructorStack = CLEANUP_LOG.isDebugEnabled() ? Debug.getStackTrace() : null; // Deep copy the configuration. mConf = new Configuration(conf); // Validate arguments. mHTableFactory = Preconditions.checkNotNull(tableFactory); mLockFactory = Preconditions.checkNotNull(lockFactory); mURI = Preconditions.checkNotNull(kijiURI); // Configure the ZooKeeper quorum: mConf.setStrings("hbase.zookeeper.quorum", mURI.getZookeeperQuorum().toArray(new String[0])); mConf.setInt("hbase.zookeeper.property.clientPort", mURI.getZookeeperClientPort()); // Check for an instance name. Preconditions.checkArgument( mURI.getInstance() != null, "KijiURI '%s' does not specify a Kiji instance name.", mURI); if (LOG.isDebugEnabled()) { Debug.logConfiguration(mConf); LOG.debug( "Opening kiji instance '{}'" + " with client software version '{}'" + " and client data version '{}'.", mURI, VersionInfo.getSoftwareVersion(), VersionInfo.getClientDataVersion()); } // Load these lazily. mSchemaTable = null; mMetaTable = null; mSecurityManager = null; mSystemTable = new HBaseSystemTable(mURI, mConf, mHTableFactory); mRetainCount.set(1); final State oldState = mState.getAndSet(State.OPEN); Preconditions.checkState( oldState == State.UNINITIALIZED, "Cannot open Kiji instance in state %s.", oldState); LOG.debug("Kiji instance '{}' is now opened.", mURI); mSystemVersion = mSystemTable.getDataVersion(); LOG.debug("Kiji instance '{}' has data version '{}'.", mURI, mSystemVersion); // Make sure the data version for the client matches the cluster. LOG.debug("Validating version for Kiji instance '{}'.", mURI); try { VersionInfo.validateVersion(this); } catch (IOException ioe) { // If an IOException occurred the object will not be constructed so need to clean it up. close(); throw ioe; } catch (KijiNotInstalledException kie) { // Some clients handle this unchecked Exception so do the same here. close(); throw kie; } // TODO(SCHEMA-491) Share ZooKeeperClient instances when possible. if (mSystemVersion.compareTo(Versions.MIN_SYS_VER_FOR_LAYOUT_VALIDATION) >= 0) { // system-2.0 clients must connect to ZooKeeper: // - to register themselves as table users; // - to receive table layout updates. mZKClient = HBaseFactory.Provider.get().getZooKeeperClient(mURI); try { mMonitor = new ZooKeeperMonitor(mZKClient); mMonitor.registerInstanceUser(mURI, mKijiClientId, mSystemVersion.toString()); } catch (KeeperException ke) { // Unrecoverable KeeperException: throw new IOException(ke); } } else { // system-1.x clients do not need a ZooKeeper connection. mZKClient = null; mMonitor = null; } }