Skip to content

Commit 7107f41

Browse files
authored
ignite: dist chmod optimization (LIKE '?%') (#340)
1 parent f8e34e0 commit 7107f41

File tree

8 files changed

+212
-12
lines changed

8 files changed

+212
-12
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ bench/hdfs
8383
bench/voltfs
8484
ignite/*
8585

86-
ignite
86+
filescale_init/ignite/work
8787
*.pem
8888

8989
work_dir

filescale_init/src/main/java/HdfsMetaInfoSchema.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,14 @@ private HdfsMetaInfoSchema() throws SQLException {
264264
} catch (SQLException ex) {
265265
System.err.println(ex.getMessage());
266266
}
267+
268+
if (env.equals("IGNITE")) {
269+
IgniteCluster cluster = ignite_client.cluster();
270+
cluster.active(true);
271+
cluster.enableWal("inodes");
272+
cluster.baselineAutoAdjustEnabled(false);
273+
ignite_client.close();
274+
}
267275
}
268276

269277
public Connection getConnection() {

hadoop-hdfs-project/hadoop-hdfs-db/src/main/java/org/apache/hadoop/hdfs/db/ignite/PermissionsPayload.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
import org.apache.ignite.binary.BinaryObject;
55

66
public class PermissionsPayload {
7-
public Set<BinaryObject> keys;
7+
public String path;
88
public long permission;
99

10-
public PermissionsPayload(Set<BinaryObject> keys, long permission) {
11-
this.keys = keys;
10+
public PermissionsPayload(String path, long permission) {
11+
this.path = path;
1212
this.permission = permission;
1313
}
1414
}

hadoop-hdfs-project/hadoop-hdfs-db/src/main/java/org/apache/hadoop/hdfs/db/ignite/RenameSubtreeINodes.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121
import org.apache.ignite.transactions.TransactionConcurrency;
2222
import org.apache.ignite.transactions.TransactionIsolation;
2323

24+
// Ignite does not allow updating a primary key because the latter defines a partition the key
25+
// and its value belong to statically. While the partition with all its data can change several
26+
// cluster owners, the key always belongs to a single partition. The partition is calculated
27+
// using a hash function applied to the key’s value.
28+
// Thus, if a key needs to be updated it has to be removed and then inserted.
2429
public class RenameSubtreeINodes implements IgniteClosure<RenamePayload, String> {
2530

2631
@IgniteInstanceResource

hadoop-hdfs-project/hadoop-hdfs-db/src/main/java/org/apache/hadoop/hdfs/db/ignite/SetPermissions.java

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
package org.apache.hadoop.hdfs.db.ignite;
22

3+
import java.io.File;
34
import java.util.List;
45
import java.util.TreeSet;
56
import java.util.Set;
67
import java.util.Map;
7-
import org.apache.ignite.IgniteCache;
8+
import java.util.HashMap;
9+
import java.util.HashSet;
10+
import javax.cache.Cache;
811
import org.apache.ignite.Ignite;
12+
import org.apache.ignite.IgniteCache;
13+
import org.apache.ignite.cache.query.ScanQuery;
914
import org.apache.ignite.lang.IgniteClosure;
15+
import org.apache.ignite.lang.IgniteBiPredicate;
1016
import org.apache.ignite.internal.IgniteEx;
1117
import org.apache.ignite.internal.processors.cache.persistence.wal.FileWriteAheadLogManager;
1218
import org.apache.ignite.resources.IgniteInstanceResource;
1319
import org.apache.ignite.binary.BinaryObject;
1420
import org.apache.ignite.binary.BinaryObjectBuilder;
1521
import org.apache.ignite.cache.query.SqlFieldsQuery;
22+
import org.apache.ignite.transactions.Transaction;
23+
import org.apache.ignite.transactions.TransactionConcurrency;
24+
import org.apache.ignite.transactions.TransactionIsolation;
1625

1726
public class SetPermissions implements IgniteClosure<PermissionsPayload, String> {
1827

@@ -23,12 +32,51 @@ public class SetPermissions implements IgniteClosure<PermissionsPayload, String>
2332
public String apply(PermissionsPayload payload) {
2433
IgniteCache<BinaryObject, BinaryObject> inodesBinary = ignite.cache("inodes").withKeepBinary();
2534

26-
// Using EntryProcessor.invokeAll to set every permission value in place.
27-
inodesBinary.invokeAll(payload.keys, (entry, object) -> {
28-
BinaryObject inode = entry.getValue().toBuilder().setField("permission", payload.permission).build();
29-
entry.setValue(inode);
30-
return null;
31-
});
35+
File file = new File(payload.path);
36+
String parent = file.getParent();
37+
String name = file.getName();
38+
39+
Transaction tx = ignite.transactions().txStart(
40+
TransactionConcurrency.PESSIMISTIC, TransactionIsolation.SERIALIZABLE);
41+
42+
// 1. query subtree inodes
43+
List<Cache.Entry<BinaryObject, BinaryObject>> result;
44+
ScanQuery<BinaryObject, BinaryObject> scanAddress = new ScanQuery<>(
45+
new IgniteBiPredicate<BinaryObject, BinaryObject>() {
46+
@Override
47+
public boolean apply(BinaryObject binaryKey, BinaryObject binaryObject) {
48+
return ((String)binaryKey.field("parentName")).startsWith(parent);
49+
}
50+
}
51+
);
52+
result = inodesBinary.query(scanAddress).getAll();
53+
54+
// 2. update subtree permission
55+
Map<BinaryObject, BinaryObject> map = new HashMap<>();
56+
BinaryObjectBuilder inodeKeyBuilder = ignite.binary().builder("InodeKey");
57+
for (Cache.Entry<BinaryObject, BinaryObject> entry : result) {
58+
BinaryObject inodeValue = entry.getValue();
59+
inodeValue = inodeValue.toBuilder()
60+
.setField("permission", payload.permission)
61+
.build();
62+
map.put(entry.getKey(), inodeValue);
63+
}
64+
65+
// 3. update subtree to DB
66+
inodesBinary.putAll(map);
67+
68+
BinaryObject rootKey = inodeKeyBuilder
69+
.setField("parentName", parent)
70+
.setField("name", name)
71+
.build();
72+
BinaryObject inodeValue = inodesBinary.get(rootKey);
73+
inodeValue = inodeValue.toBuilder()
74+
.setField("permission", payload.permission)
75+
.build();
76+
inodesBinary.put(rootKey, inodeValue);
77+
78+
tx.commit();
79+
tx.close();
3280

3381
FileWriteAheadLogManager walMgr = (FileWriteAheadLogManager)(
3482
((IgniteEx)ignite).context().cache().context().wal());
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package org.apache.hadoop.hdfs.db.ignite;
2+
3+
import java.io.File;
4+
import java.util.List;
5+
import java.util.TreeSet;
6+
import java.util.Set;
7+
import java.util.Map;
8+
import java.util.HashMap;
9+
import java.util.HashSet;
10+
import javax.cache.Cache;
11+
import org.apache.ignite.Ignite;
12+
import org.apache.ignite.IgniteCache;
13+
import org.apache.ignite.cache.query.ScanQuery;
14+
import org.apache.ignite.lang.IgniteClosure;
15+
import org.apache.ignite.lang.IgniteBiPredicate;
16+
import org.apache.ignite.internal.IgniteEx;
17+
import org.apache.ignite.internal.processors.cache.persistence.wal.FileWriteAheadLogManager;
18+
import org.apache.ignite.resources.IgniteInstanceResource;
19+
import org.apache.ignite.binary.BinaryObject;
20+
import org.apache.ignite.binary.BinaryObjectBuilder;
21+
import org.apache.ignite.cache.query.SqlFieldsQuery;
22+
import org.apache.ignite.transactions.Transaction;
23+
import org.apache.ignite.transactions.TransactionConcurrency;
24+
import org.apache.ignite.transactions.TransactionIsolation;
25+
26+
27+
public class SetPermissionsV2 implements IgniteClosure<PermissionsPayload, String> {
28+
29+
@IgniteInstanceResource
30+
private Ignite ignite;
31+
32+
@Override
33+
public String apply(PermissionsPayload payload) {
34+
IgniteCache<BinaryObject, BinaryObject> inodesBinary = ignite.cache("inodes").withKeepBinary();
35+
36+
File file = new File(payload.path);
37+
String parent = file.getParent();
38+
String name = file.getName();
39+
40+
Transaction tx = ignite.transactions().txStart(
41+
TransactionConcurrency.PESSIMISTIC, TransactionIsolation.SERIALIZABLE);
42+
43+
inodesBinary.query(new SqlFieldsQuery("UPDATE inodes SET permission = ? WHERE parentName LIKE ?")
44+
.setArgs(payload.permission, payload.path + "%")).getAll();
45+
inodesBinary.query(new SqlFieldsQuery("UPDATE inodes SET permission = ? WHERE parentName = ? and name = ?")
46+
.setArgs(payload.permission, parent, name)).getAll();
47+
48+
tx.commit();
49+
tx.close();
50+
51+
FileWriteAheadLogManager walMgr = (FileWriteAheadLogManager)(
52+
((IgniteEx)ignite).context().cache().context().wal());
53+
return walMgr.lastWritePointer().toString();
54+
}
55+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package org.apache.hadoop.hdfs.db.ignite;
2+
3+
import java.io.File;
4+
import java.util.List;
5+
import java.util.TreeSet;
6+
import java.util.Set;
7+
import java.util.Map;
8+
import java.util.HashMap;
9+
import java.util.HashSet;
10+
import java.util.Iterator;
11+
import javax.cache.Cache;
12+
import org.apache.ignite.Ignite;
13+
import org.apache.ignite.IgniteCache;
14+
import org.apache.ignite.cache.query.ScanQuery;
15+
import org.apache.ignite.lang.IgniteClosure;
16+
import org.apache.ignite.lang.IgniteBiPredicate;
17+
import org.apache.ignite.internal.IgniteEx;
18+
import org.apache.ignite.internal.processors.cache.persistence.wal.FileWriteAheadLogManager;
19+
import org.apache.ignite.resources.IgniteInstanceResource;
20+
import org.apache.ignite.binary.BinaryObject;
21+
import org.apache.ignite.binary.BinaryObjectBuilder;
22+
import org.apache.ignite.cache.query.SqlFieldsQuery;
23+
import org.apache.ignite.transactions.Transaction;
24+
import org.apache.ignite.transactions.TransactionConcurrency;
25+
import org.apache.ignite.transactions.TransactionIsolation;
26+
27+
public class SetPermissionsV3 implements IgniteClosure<PermissionsPayload, String> {
28+
29+
@IgniteInstanceResource
30+
private Ignite ignite;
31+
32+
@Override
33+
public String apply(PermissionsPayload payload) {
34+
IgniteCache<BinaryObject, BinaryObject> inodesBinary = ignite.cache("inodes").withKeepBinary();
35+
36+
File file = new File(payload.path);
37+
String parent = file.getParent();
38+
String name = file.getName();
39+
40+
Transaction tx = ignite.transactions().txStart(
41+
TransactionConcurrency.PESSIMISTIC, TransactionIsolation.SERIALIZABLE);
42+
43+
// 1. query subtree inodes
44+
ScanQuery<BinaryObject, BinaryObject> scanAddress = new ScanQuery<>(
45+
new IgniteBiPredicate<BinaryObject, BinaryObject>() {
46+
@Override
47+
public boolean apply(BinaryObject binaryKey, BinaryObject binaryObject) {
48+
return ((String)binaryKey.field("parentName")).startsWith(parent);
49+
}
50+
}
51+
);
52+
Iterator<Cache.Entry<BinaryObject, BinaryObject>> iterator = inodesBinary.
53+
query(scanAddress).iterator();
54+
55+
// 2. update subtree permission
56+
while (iterator.hasNext()) {
57+
BinaryObject key = iterator.next().getKey();
58+
BinaryObject value = inodesBinary.get(key);
59+
value = value.toBuilder()
60+
.setField("permission", payload.permission)
61+
.build();
62+
inodesBinary.put(key, value);
63+
}
64+
65+
BinaryObjectBuilder inodeKeyBuilder = ignite.binary().builder("InodeKey");
66+
BinaryObject rootKey = inodeKeyBuilder
67+
.setField("parentName", parent)
68+
.setField("name", name)
69+
.build();
70+
BinaryObject rootValue = inodesBinary.get(rootKey);
71+
rootValue = rootValue.toBuilder()
72+
.setField("permission", payload.permission)
73+
.build();
74+
inodesBinary.put(rootKey, rootValue);
75+
76+
tx.commit();
77+
tx.close();
78+
79+
FileWriteAheadLogManager walMgr = (FileWriteAheadLogManager)(
80+
((IgniteEx)ignite).context().cache().context().wal());
81+
return walMgr.lastWritePointer().toString();
82+
}
83+
}

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/INodeWithAdditionalFields.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.apache.hadoop.hdfs.db.ignite.RenamePayload;
4343
import org.apache.hadoop.hdfs.db.ignite.RenameSubtreeINodes;
4444
import org.apache.hadoop.hdfs.db.ignite.SetPermissions;
45+
import org.apache.hadoop.hdfs.db.ignite.SetPermissionsV2;
4546
import org.apache.hadoop.hdfs.db.ignite.PermissionsPayload;
4647

4748
/**
@@ -571,7 +572,7 @@ private final void remoteChmod(String path, Set<Pair<String, String>> mpoints) {
571572
} else if (database.equals("IGNITE")) {
572573
IgniteCompute compute = conn.getIgniteClient().compute();
573574
INodeKeyedObjects.setWalOffset(
574-
compute.apply(new SetPermissions(), new PermissionsPayload(keys, this.permission))
575+
compute.apply(new SetPermissionsV2(), new PermissionsPayload(path, this.permission))
575576
);
576577
}
577578
String end = INodeKeyedObjects.getWalOffset();

0 commit comments

Comments
 (0)