7.2. キャッシュストア実装
Data Grid は、使用できるキャッシュストア実装を複数提供します。または、カスタムキャッシュストアを指定することもできます。
7.2.1. クラスターキャッシュローダー
ClusterCacheLoader
は、他の Data Grid クラスターメンバーからデータを取得しますが、データは永続化されません。つまり、ClusterCacheLoader
はキャッシュストアではありません。
ClusterCacheLoader
は、状態遷移へのブロック以外の部分を提供します。ClusterCacheLoader
は、それらの鍵がローカルノードで利用できない場合に、他のノードからキーを取得します。これは、キャッシュコンテンツを後で読み込むのと似ています。
以下のポイントは ClusterCacheLoader
にも適用されます。
-
事前読み込みは有効になりません (
preload=true
)。 -
永続状態の取得はサポートされていません (
fetch-state=true
)。 - セグメンテーションはサポートされていません。
ClusterLoader
は非推奨となり、今後のリリースで削除されます。
宣言型設定
<persistence> <cluster-loader remote-timeout="500"/> </persistence>
プログラムによる設定
ConfigurationBuilder b = new ConfigurationBuilder(); b.persistence() .addClusterLoader() .remoteCallTimeout(500);
7.2.2. 単一ファイルキャッシュストア
Single File キャッシュストアである SingleFileStore
は、ファイルにデータを永続化します。また、Data Grid は、キーと値がファイルに保存される間に、キーのインメモリーインデックスも維持されます。デフォルトでは、単一ファイルキャッシュストアはセグメント化されるため、Data Grid は各セグメントに個別のファイルを作成します。
SingleFileStore
はキーのインメモリーインデックス、および値の場所を保持するため、キーのサイズと数に応じて追加のメモリーが必要です。このため、SingleFileStore
は、鍵のサイズが大きいユースケースには推奨されません。
SingleFileStore
が断片化される場合もあります。値のサイズが継続的に増加している場合は、単一ファイルで利用可能な領域は使用されませんが、エントリーはファイルの最後に追加されます。このファイルで使用可能な領域は、エントリーに収まることができる場合に限り使用されます。同様に、メモリーからすべてのエントリーを削除すると、単一のファイルストアのサイズが減少したり、デフラグしたりしません。
宣言型設定
<persistence> <file-store max-entries="5000"/> </persistence>
プログラムによる設定
- 埋め込みデプロイメントの場合は、以下を実行します。
ConfigurationBuilder b = new ConfigurationBuilder(); b.persistence() .addSingleFileStore() .maxEntries(5000);
- サーバーデプロイメントの場合は、以下を実行します。
import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; import org.infinispan.client.hotrod.configuration.NearCacheMode; ... ConfigurationBuilder builder = new ConfigurationBuilder(); builder .remoteCache("mycache") .configuration("<distributed-cache name=\"mycache\"><persistence><file-store max-entries=\"5000\"/></persistence></distributed-cache>");
セグメンテーション
単一ファイルキャッシュは、セグメンテーションをサポートし、セグメントごとに別のインスタンスを作成するので、設定するパスに複数のディレクトリーが作成されます。各ディレクトリーは、データマップ先のセグメントを表す数字です。
7.2.3. JDBC 文字列ベースのキャッシュストア
JDBC 文字列ベースのキャッシュストアである JdbcStringBasedStore
は JDBC ドライバーを使用して、基礎となるデータベースに値を読み込みおよび保存します。
JdbcStringBasedStore
はテーブル内の独自の行に各エントリーを保存し、同時読み込みのスループットを高めます。JdbcStringBasedStore
は、key-to-string-mapper
インターフェイスを使用して各キーを String
オブジェクトにマッピングする単純な 1 対 1 のマッピングも使用します。
Data Grid は、プリミティブタイプを処理する DefaultTwoWayKey2StringMapper
のデフォルト実装を提供します。
キャッシュエントリーを保存するために使用されるデータテーブルの他に、ストアはメタデータを保存するための _META
テーブルも作成します。この表は、既存のデータベースコンテンツが現在の Data Grid バージョンおよび設定と互換性があることを確認するために使用されます。
デフォルトでは、Data Grid 共有は保存されません。つまり、クラスター内のすべてのノードが更新ごとに基盤のストアに書き込まれます。基盤のデータベースに一度書き込みを行う場合、JDBC ストアを共有として設定する必要があります。
セグメンテーション
JdbcStringBasedStore
はデフォルトでセグメンテーションを使用し、エントリーが属するセグメントを表すためにデータベーステーブルの列を必要とします。
7.2.3.1. 接続ファクトリー
JdbcStringBasedStore
は、ConnectionFactory
実装に依存してデータベースに接続します。
Data Grid は以下の ConnectionFactory
実装を提供します。
PooledConnectionFactoryConfigurationBuilder
PooledConnectionFactoryConfiguration
で設定する Agroal に基づく接続ファクトリー。
または、以下の例のように、org.infinispan.agroal.
の接頭辞が付けられた設定プロパティーを指定することもできます。
org.infinispan.agroal.metricsEnabled=false org.infinispan.agroal.minSize=10 org.infinispan.agroal.maxSize=100 org.infinispan.agroal.initialSize=20 org.infinispan.agroal.acquisitionTimeout_s=1 org.infinispan.agroal.validationTimeout_m=1 org.infinispan.agroal.leakTimeout_s=10 org.infinispan.agroal.reapTimeout_m=10 org.infinispan.agroal.metricsEnabled=false org.infinispan.agroal.autoCommit=true org.infinispan.agroal.jdbcTransactionIsolation=READ_COMMITTED org.infinispan.agroal.jdbcUrl=jdbc:h2:mem:PooledConnectionFactoryTest;DB_CLOSE_DELAY=-1 org.infinispan.agroal.driverClassName=org.h2.Driver.class org.infinispan.agroal.principal=sa org.infinispan.agroal.credential=sa
その後、Data Grid が PooledConnectionFactoryConfiguration.propertyFile
でプロパティーファイルを使用するように設定します。
サーブレットコンテナーのデプロイメントではなく、スタンドアロンデプロイメントで PooledConnectionFactory
を使用する必要があります。
ManagedConnectionFactoryConfigurationBuilder
アプリケーションサーバーなどの管理環境で使用できる接続ファクトリー。この接続ファクトリーは JNDI ツリーで設定可能な場所を確認し、接続管理を DataSource
に委譲できます。
SimpleConnectionFactoryConfigurationBuilder
呼び出しごとにデータベース接続を作成する接続ファクトリー。この接続ファクトリーは、テスト環境または開発環境にのみ使用してください。
7.2.3.2. JDBC 文字列ベースのキャッシュストア設定
プログラムまたは宣言型で JdbcStringBasedStore
を設定できます。
宣言型設定
-
PooledConnectionFactory
の使用
<persistence> <string-keyed-jdbc-store xmlns="urn:infinispan:config:store:jdbc:12.1" shared="true"> <connection-pool connection-url="jdbc:h2:mem:infinispan_string_based;DB_CLOSE_DELAY=-1" username="sa" driver="org.h2.Driver"/> <string-keyed-table drop-on-exit="true" prefix="ISPN_STRING_TABLE"> <id-column name="ID_COLUMN" type="VARCHAR(255)" /> <data-column name="DATA_COLUMN" type="BINARY" /> <timestamp-column name="TIMESTAMP_COLUMN" type="BIGINT" /> <segment-column name="SEGMENT_COLUMN" type="INT" /> </string-keyed-table> </string-keyed-jdbc-store> </persistence>
-
ManagedConnectionFactory
の使用
<persistence> <string-keyed-jdbc-store xmlns="urn:infinispan:config:store:jdbc:12.1" shared="true"> <data-source jndi-url="java:/StringStoreWithManagedConnectionTest/DS" /> <string-keyed-table drop-on-exit="true" create-on-start="true" prefix="ISPN_STRING_TABLE"> <id-column name="ID_COLUMN" type="VARCHAR(255)" /> <data-column name="DATA_COLUMN" type="BINARY" /> <timestamp-column name="TIMESTAMP_COLUMN" type="BIGINT" /> <segment-column name="SEGMENT_COLUMN" type="INT"/> </string-keyed-table> </string-keyed-jdbc-store> </persistence>
プログラムによる設定
-
PooledConnectionFactory
の使用
ConfigurationBuilder builder = new ConfigurationBuilder(); builder.persistence().addStore(JdbcStringBasedStoreConfigurationBuilder.class) .fetchPersistentState(false) .ignoreModifications(false) .purgeOnStartup(false) .shared(true) .table() .dropOnExit(true) .createOnStart(true) .tableNamePrefix("ISPN_STRING_TABLE") .idColumnName("ID_COLUMN").idColumnType("VARCHAR(255)") .dataColumnName("DATA_COLUMN").dataColumnType("BINARY") .timestampColumnName("TIMESTAMP_COLUMN").timestampColumnType("BIGINT") .segmentColumnName("SEGMENT_COLUMN").segmentColumnType("INT") .connectionPool() .connectionUrl("jdbc:h2:mem:infinispan_string_based;DB_CLOSE_DELAY=-1") .username("sa") .driverClass("org.h2.Driver");
-
ManagedConnectionFactory
の使用
ConfigurationBuilder builder = new ConfigurationBuilder(); builder.persistence().addStore(JdbcStringBasedStoreConfigurationBuilder.class) .fetchPersistentState(false) .ignoreModifications(false) .purgeOnStartup(false) .shared(true) .table() .dropOnExit(true) .createOnStart(true) .tableNamePrefix("ISPN_STRING_TABLE") .idColumnName("ID_COLUMN").idColumnType("VARCHAR(255)") .dataColumnName("DATA_COLUMN").dataColumnType("BINARY") .timestampColumnName("TIMESTAMP_COLUMN").timestampColumnType("BIGINT") .segmentColumnName("SEGMENT_COLUMN").segmentColumnType("INT") .dataSource() .jndiUrl("java:/StringStoreWithManagedConnectionTest/DS");
7.2.4. JPA キャッシュストア
JPA (Java Persistence API) キャッシュストア、JpaStore
は正式なスキーマを使用してデータを永続化します。その後、他のアプリケーションは永続ストレージから読み取れ、Data Grid からデータを読み込むことができます。ただし、他のアプリケーションは、Data Grid と同時に永続ストレージを使用しないでください。
JpaStore
を使用する場合は、以下を考慮する必要があります。
- キーはエンティティーの ID である必要があります。値はエンティティーオブジェクトにする必要があります。
-
1 つの
@Id
または@EmbeddedId
アノテーションのみが許可されます。 -
@GeneratedValue
アノテーションを使用した自動生成 ID はサポートされません。 - すべてのエントリーは immortal として保存されます。
-
JpaStore
はセグメンテーションをサポートしていません。
宣言型設定
<local-cache name="vehicleCache"> <persistence passivation="false"> <jpa-store xmlns="urn:infinispan:config:store:jpa:12.1" persistence-unit="org.infinispan.persistence.jpa.configurationTest" entity-class="org.infinispan.persistence.jpa.entity.Vehicle"> /> </persistence> </local-cache>
パラメーター | 説明 |
---|---|
|
JPA エンティティークラスを含む JPA 設定ファイル |
| このキャッシュに保存されることが想定される完全修飾 JPA エンティティークラス名を指定します。1 つのクラスのみが許可されます。 |
プログラムによる設定
Configuration cacheConfig = new ConfigurationBuilder().persistence() .addStore(JpaStoreConfigurationBuilder.class) .persistenceUnitName("org.infinispan.loaders.jpa.configurationTest") .entityClass(User.class) .build();
パラメーター | 説明 |
---|---|
|
JPA エンティティークラスを含む JPA 設定ファイル |
| このキャッシュに保存されることが想定される完全修飾 JPA エンティティークラス名を指定します。1 つのクラスのみが許可されます。 |
7.2.4.1. JPA キャッシュストア使用例
このセクションでは、JPA キャッシュストアを使用する例を紹介します。
前提条件
-
JPA エンティティーをマーシャリングするように Data Grid を設定します。デフォルトでは、DataGrid は Java オブジェクトのマーシャリングに ProtoStream を使用します。JPA エンティティーをマーシャリングするには、
.proto
スキーマおよびマーシャラーをSerializationContext
に登録するSerializationContextInitializer
実装を作成する必要があります。
手順
永続性ユニット "myPersistenceUnit" を
persistence.xml
で定義します。<persistence-unit name="myPersistenceUnit"> <!-- Persistence configuration goes here. --> </persistence-unit>
ユーザーエンティティークラスを作成します。
@Entity public class User implements Serializable { @Id private String username; private String firstName; private String lastName; ... }
JPA キャッシュストアで"usersCache"という名前のキャッシュを設定します。
キャッシュ usersCache を設定して JPA キャッシュストアを使用するように設定できます。これにより、データをキャッシュに配置すると、JPA 設定を基にデータがデータベースに永続化されます。
EmbeddedCacheManager cacheManager = ...; Configuration cacheConfig = new ConfigurationBuilder().persistence() .addStore(JpaStoreConfigurationBuilder.class) .persistenceUnitName("org.infinispan.loaders.jpa.configurationTest") .entityClass(User.class) .build(); cacheManager.defineCache("usersCache", cacheConfig); Cache<String, User> usersCache = cacheManager.getCache("usersCache"); usersCache.put("raytsang", new User(...));
JPA キャッシュストアを使用するキャッシュは、以下の例のように、1 種類のデータのみを保存できます。
Cache<String, User> usersCache = cacheManager.getCache("myJPACache"); // Cache is configured for the User entity class usersCache.put("username", new User()); // Cannot configure caches to use another entity class with JPA cache stores Cache<Integer, Teacher> teachersCache = cacheManager.getCache("myJPACache"); teachersCache.put(1, new Teacher()); // The put request does not work for the Teacher entity class
@EmbeddedId
アノテーションでは、以下の例のように複合キーを使用できます。@Entity public class Vehicle implements Serializable { @EmbeddedId private VehicleId id; private String color; ... } @Embeddable public class VehicleId implements Serializable { private String state; private String licensePlate; ... }
関連資料
7.2.5. リモートキャッシュストア
リモートキャッシュストア RemoteStore
は Hot Rod プロトコルを使用して Data Grid クラスターにデータを保存します。
以下は、"one" および "two" という名前の 2 つの Data Grid Server インスタンスの "mycache" という名前のキャッシュにデータを保存する RemoteStore
設定例になります。
リモートキャッシュストアを共有として設定している場合は、事前にデータを読み込めません。つまり、設定の shared="true"
の場合は、preload="false"
を設定する必要があります。
宣言型設定
<persistence> <remote-store xmlns="urn:infinispan:config:store:remote:12.1" cache="mycache" raw-values="true"> <remote-server host="one" port="12111" /> <remote-server host="two" /> <connection-pool max-active="10" exhausted-action="CREATE_NEW" /> <write-behind /> </remote-store> </persistence>
プログラムによる設定
ConfigurationBuilder b = new ConfigurationBuilder(); b.persistence().addStore(RemoteStoreConfigurationBuilder.class) .fetchPersistentState(false) .ignoreModifications(false) .purgeOnStartup(false) .remoteCacheName("mycache") .rawValues(true) .addServer() .host("one").port(12111) .addServer() .host("two") .connectionPool() .maxActive(10) .exhaustedAction(ExhaustedAction.CREATE_NEW) .async().enable();
セグメンテーション
RemoteStore
はセグメンテーションをサポートし、セグメントごとにキーとエントリーを公開できるため、一括操作がより効率的になります。ただし、セグメンテーションは Data Grid Hot Rod プロトコルバージョン 2.3 以降でのみ利用できます。
RemoteStore
のセグメンテーションを有効にすると、Data Grid サーバー設定で定義したセグメントの数が使用されます。
ソースキャッシュがセグメント化され、RemoteStore
以外のセグメントを使用する場合は、一括操作のために誤った値が返されます。この場合は、RemoteStore
のセグメンテーションを無効にする必要があります。
7.2.6. RocksDB キャッシュストア
RocksDB は、同時環境のパフォーマンスと信頼性が高いキー/ファイルシステムベースのストレージを提供します。
RocksDB キャッシュストア RocksDBStore
は、2 つのデータベースを使用します。1 つのデータベースは、データをメモリーに主要なキャッシュストアを提供します。他のデータベースには、Data Grid がメモリーから失効するエントリーを保持します。
宣言型設定
<local-cache name="vehicleCache"> <persistence> <rocksdb-store xmlns="urn:infinispan:config:store:rocksdb:12.1" path="rocksdb/data"> <expiration path="rocksdb/expired"/> </rocksdb-store> </persistence> </local-cache>
プログラムによる設定
Configuration cacheConfig = new ConfigurationBuilder().persistence() .addStore(RocksDBStoreConfigurationBuilder.class) .build(); EmbeddedCacheManager cacheManager = new DefaultCacheManager(cacheConfig); Cache<String, User> usersCache = cacheManager.getCache("usersCache"); usersCache.put("raytsang", new User(...));
Properties props = new Properties(); props.put("database.max_background_compactions", "2"); props.put("data.write_buffer_size", "512MB"); Configuration cacheConfig = new ConfigurationBuilder().persistence() .addStore(RocksDBStoreConfigurationBuilder.class) .location("rocksdb/data") .expiredLocation("rocksdb/expired") .properties(props) .build();
表7.1 RocksDBStore
設定パラメーター
パラメーター | 説明 |
---|---|
| プライマリーキャッシュストアを提供する RocksDB データベースへのパスを指定します。ロケーションを設定しない場合には、自動的に作成されます。パスはグローバル永続の場所と相対的である必要があります。 |
| 期限切れのデータのキャッシュストアを提供する RocksDB データベースへのパスを指定します。ロケーションを設定しない場合には、自動的に作成されます。パスはグローバル永続の場所と相対的である必要があります。 |
| 期限切れのエントリーのためにインメモリーキューのサイズを設定します。キューがサイズに達すると、Data Grid は期限切れの RocksDB キャッシュストアにフラッシュします。 |
| RocksDB データベースを削除し、再初期化する (re-init) 前にエントリーの最大数を設定します。サイズが小さいキャッシュストアの場合、すべてのエントリーを繰り返し処理し、各エントリーを個別に削除すると、より高速な方法が得られます。 |
RocksDB チューニングパラメーター
以下の RocksDB チューニングパラメーターを指定することもできます。
-
compressionType
-
blockSize
-
cacheSize
RocksDB 設定プロパティー
任意で、以下のように設定でプロパティーを設定します。
-
RocksDB データベースを調整およびチューニングするために、プロパティーの前に
database
接頭辞を追加します。 -
プロパティーの前に
data
接頭辞を追加して、RocksDB がデータを格納する列ファミリーを設定します。
<property name="database.max_background_compactions">2</property> <property name="data.write_buffer_size">64MB</property> <property name="data.compression_per_level">kNoCompression:kNoCompression:kNoCompression:kSnappyCompression:kZSTD:kZSTD</property>
セグメンテーション
RocksDBStore
はセグメンテーションをサポートし、セグメントごとに個別の列ファミリーを作成します。セグメント化された RocksDB キャッシュストアは、ルックアップのパフォーマンスと反復が改善されますが、書き込み操作のパフォーマンスに若干低下します。
数百のセグメントを複数設定しないでください。RocksDB は、列ファミリーの数を無制限に指定するように設計されていません。セグメントが多すぎると、キャッシュストアの起動時間が大幅に増加します。
7.2.7. Soft-Index ファイルストア
soft-Index ファイルキャッシュストア SoftIndexFileStore
は、ローカルファイルベースのストレージを提供します。
SoftIndexFileStore
は、Java のソフト参照を使用してインメモリーでキャッシュされる B+ Tree のバリアントを使用する Java 実装です。Index
と呼ばれる B+ Tree は、キャッシュストアが再起動するたびに削除および再ビルドされる単一のファイルにオフロードされます。
SoftIndexFileStore
は、データを単一のファイルではなく一連のファイルに保存します。ファイルの使用量が 50% を下回ると、ファイルのエントリーが別のファイルに上書きされ、ファイルは削除されます。
SoftIndexFileStore
は、add-only メソッドで記述されたファイルのセットでデータを永続化します。このため、従来の磁気ディスクで SoftIndexFileStore
を使用する場合は、エントリーのバーストを書き込むときにシークする必要はありません。
SoftIndexFileStore
のほとんどの構造はバインドされるため、メモリー不足の例外は危険にさらされません。同時オープンファイルの制限を設定することもできます。
デフォルトでは、Index
のノードのサイズは 4096 バイトに制限されます。このサイズはキーの長さも制限します。シリアライズされたキーの長さが正確になります。このため、ノードのサイズ (15 バイト) よりも長い鍵を使用することはできません。さらに、キーの長さは "short" として保存され、キーの長さは 32767 バイトに制限されます。SoftIndexFileStore
は、シリアル化後にキーが長い場合に例外を出力します。
SoftIndexFileStore
は期限切れのエントリーを検出できず、ファイルシステムで領域が過剰に使用されてしまう可能性があります。
AdvancedStore.purgeExpired()
は SoftIndexFileStore
には実装されていません。
宣言型設定
<persistence> <soft-index-file-store xmlns="urn:infinispan:config:store:soft-index:12.1"> <index path="testCache/index" /> <data path="testCache/data" /> </soft-index-file-store> </persistence>
プログラムによる設定
ConfigurationBuilder b = new ConfigurationBuilder(); b.persistence() .addStore(SoftIndexFileStoreConfigurationBuilder.class) .indexLocation("testCache/index"); .dataLocation("testCache/data")
セグメンテーション
soft-Index ファイルキャッシュは、サポートセグメントとセグメントごとに別のインスタンスを作成するので、設定するパスに複数のディレクトリーが作成されます。各ディレクトリーは、データマップ先のセグメントを表す数字です。
7.2.8. カスタムキャッシュストアの実装
Data Grid の永続 SPI を使用してカスタムキャッシュストアを作成できます。
7.2.8.1. Data Grid 永続性 SPI
Data Grid Service Provider Interface (SPI) は、NonBlockingStore
インターフェイスを介して外部ストレージへの読み書き操作を有効にし、以下の機能を持ちます。
- JCache 準拠のベンダー間での移植性
-
Data Grid は、ブロッキングコードを処理するアダプターを使用して、
NonBlockingStore
インターフェイスとJSR-107
JCache 仕様間の互換性を維持します。 - 簡素化されたトランザクション統合
- Data Grid はロックを自動的に処理するため、実装は永続ストアへの同時アクセスを調整する必要はありません。使用するロックモードによっては、通常、同じキーへの同時書き込みは発生しません。ただし、永続ストレージ上の操作は複数のスレッドから発信され、この動作を許容する実装を作成することを想定する必要があります。
- 並列反復
- Data Grid を使用すると、複数のスレッドを持つ永続ストアのエントリーを繰り返すことができます。
- シリアル化の減少による CPU 使用率の削減
- Data Grid は、リモートで送信できるシリアル化された形式で保存されたエントリーを公開します。このため、Data Grid は永続ストレージから取得されたエントリーをデシリアライズし、ネットワークに書き込む際に再びシリアライズする必要はありません。
7.2.8.2. キャッシュストアの作成
NonBlockingStore
インターフェイスを実装してカスタムキャッシュストアを作成します。
- 適切な Data Grid の永続 SPI を実装します。
-
カスタム設定がある場合は、ストアクラスに
@ConfiguredBy
アノテーションを付けます。 必要に応じてカスタムキャッシュストア設定およびビルダーを作成します。
-
AbstractStoreConfiguration
およびAbstractStoreConfigurationBuilder
を拡張します。 オプションで以下のアノテーションをストア設定クラスに追加し、カスタム設定ビルダーが XML からキャッシュストア設定を解析できるようにします。
-
@ConfigurationFor
@BuiltBy
これらのアノテーションを追加しないと、
CustomStoreConfigurationBuilder
はAbstractStoreConfiguration
で定義された共通のストア属性を解析し、追加の要素は無視されます。注記設定が
@ConfigurationFor
アノテーションを宣言しない場合は、Data Grid がキャッシュを初期化する際に警告メッセージがログに記録されます。
-
-
7.2.8.3. カスタムストアを使用するための Data Grid の設定
カスタムキャッシュストア実装を作成したら、使用する Data Grid を設定します。
宣言型設定
<local-cache name="customStoreExample"> <persistence> <store class="org.infinispan.persistence.dummy.DummyInMemoryStore" /> </persistence> </local-cache>
プログラムによる設定
Configuration config = new ConfigurationBuilder() .persistence() .addStore(CustomStoreConfigurationBuilder.class) .build();
7.2.8.4. カスタムキャッシュストアのデプロイ
カスタムキャッシュストアを JAR ファイルにパッケージ化し、以下のように Data Grid サーバーにデプロイできます。
- カスタムキャッシュストア実装を JAR ファイルにパッケージ化します。
-
JAR ファイルを Data Grid サーバーの
server/lib
ディレクトリーに追加します。