21
21
* Implements the Hadoop FileSystem Interface to allow applications to store
22
22
* files on GlusterFS and run Map/Reduce jobs on the data.
23
23
*/
24
-
25
24
package org .apache .hadoop .fs .glusterfs ;
26
25
27
26
import java .io .*;
28
27
import java .net .*;
29
28
29
+ import java .util .StringTokenizer ;
30
+ import java .util .TreeMap ;
30
31
import java .util .regex .*;
31
32
32
33
import org .apache .hadoop .conf .Configuration ;
39
40
import org .apache .hadoop .fs .BlockLocation ;
40
41
import org .apache .hadoop .fs .permission .FsPermission ;
41
42
import org .apache .hadoop .util .Progressable ;
42
-
43
- import java . util .TreeMap ;
43
+ import org . apache . hadoop . util . Shell ;
44
+ import org . apache . hadoop . util .StringUtils ;
44
45
45
46
/*
46
47
* This package provides interface for hadoop jobs (incl. Map/Reduce)
@@ -83,23 +84,22 @@ public boolean FUSEMount(String volname, String server, String mount)
83
84
boolean ret = true ;
84
85
int retVal = 0 ;
85
86
Process p = null ;
87
+ String s = null ;
86
88
String mountCmd = null ;
87
89
88
- mountCmd = "mount -t glusterfs " + server + ":" + "/" + volname + " " + mount ;
89
- System .out .println ("Running: " + mountCmd );
90
+ mountCmd = "mount -t glusterfs " + server + ":" + "/" + volname + " "
91
+ + mount ;
92
+ System .out .println (mountCmd );
90
93
try {
91
94
p = Runtime .getRuntime ().exec (mountCmd );
92
-
93
95
retVal = p .waitFor ();
94
96
if (retVal != 0 )
95
97
ret = false ;
96
98
}
97
99
catch (IOException e ) {
98
- e .printStackTrace ();
99
- System .out .println ("Error calling mount, Continuing.., hopefully its already been mounted." );
100
- //throw new RuntimeException("Problem mounting FUSE mount on: "+ mount);
100
+ System .out .println ("Problem mounting FUSE mount on: " + mount );
101
+ throw new RuntimeException (e );
101
102
}
102
-
103
103
return ret ;
104
104
}
105
105
@@ -122,20 +122,29 @@ public void initialize(URI uri, Configuration conf) throws IOException {
122
122
needQuickRead = conf .get ("quick.slave.io" , null );
123
123
autoMount = conf .getBoolean ("fs.glusterfs.automount" , true );
124
124
125
+ /*
126
+ * bail out if we do not have enough information to do a FUSE mount
127
+ */
125
128
if ((volName .length () == 0 ) || (remoteGFSServer .length () == 0 )
126
129
|| (glusterMount .length () == 0 ))
127
- throw new RuntimeException ("Not enough info to mount FUSE: volname=" +volName + " glustermount=" + glusterMount );
128
-
129
-
130
- if (autoMount ) {
131
- ret = FUSEMount (volName , remoteGFSServer , glusterMount );
132
- if (!ret ) {
133
- throw new RuntimeException ("Initialize: Failed to mount GlusterFS " );
134
- }
135
- }
136
-
137
- if ((needQuickRead .length () != 0 )
138
- && (needQuickRead .equalsIgnoreCase ("yes" )
130
+ throw new RuntimeException (
131
+ "Not enough info for FUSE Mount : volname=" + volName
132
+ + ",server=" + remoteGFSServer
133
+ + ",glustermount=" + glusterMount );
134
+
135
+ ret = FUSEMount (volName , remoteGFSServer , glusterMount );
136
+
137
+ if (!ret ) {
138
+ throw new RuntimeException ("Failed to init Gluster FS" );
139
+ }
140
+ if (autoMount ) {
141
+ ret = FUSEMount (volName , remoteGFSServer , glusterMount );
142
+ if (!ret ) {
143
+ throw new RuntimeException ("Initialize: Failed to mount GlusterFS " );
144
+ }
145
+ }
146
+ if ((needQuickRead .length () != 0 )
147
+ && (needQuickRead .equalsIgnoreCase ("yes" )
139
148
|| needQuickRead .equalsIgnoreCase ("on" ) || needQuickRead
140
149
.equals ("1" )))
141
150
this .quickSlaveIO = true ;
@@ -153,8 +162,7 @@ public void initialize(URI uri, Configuration conf) throws IOException {
153
162
setConf (conf );
154
163
}
155
164
catch (Exception e ) {
156
- e .printStackTrace ();
157
- throw new RuntimeException ("Unable to initialize GlusterFS " + e .getMessage ());
165
+ throw new RuntimeException (e );
158
166
}
159
167
}
160
168
@@ -199,13 +207,14 @@ public boolean exists(Path path) throws IOException {
199
207
*/
200
208
public boolean mkdirs (Path f , FsPermission permission ) throws IOException {
201
209
202
- if (f ==null ) return true ;
203
-
204
- Path parent = f .getParent ();
205
- Path absolute = makeAbsolute (f );
206
- File p2f = new File (absolute .toUri ().getPath ());
207
- return (f == null || mkdirs (parent )) && (p2f .mkdir () || p2f .isDirectory ());
208
- }
210
+ if (f ==null )
211
+ return true ;
212
+
213
+ Path parent = f .getParent ();
214
+ Path absolute = makeAbsolute (f );
215
+ File p2f = new File (absolute .toUri ().getPath ());
216
+ return (f == null || mkdirs (parent )) && (p2f .mkdir () || p2f .isDirectory ());
217
+ }
209
218
210
219
@ Deprecated
211
220
public boolean isDirectory (Path path ) throws IOException {
@@ -274,31 +283,137 @@ public FileStatus getFileStatusFromFileString(String path)
274
283
return getFileStatus (nPath );
275
284
}
276
285
286
+ public static class FUSEFileStatus extends FileStatus {
287
+ File theFile ;
288
+
289
+ public FUSEFileStatus (File f ) {
290
+ super ();
291
+ theFile = f ;
292
+ }
293
+
294
+ public FUSEFileStatus (File f , boolean isdir , int block_replication ,
295
+ long blocksize , Path path ) {
296
+ // if its a dir, 0 length
297
+ super (isdir ? 0 : f .length (), isdir , block_replication , blocksize ,
298
+ f .lastModified (), path );
299
+ theFile = f ;
300
+ }
301
+
302
+ /**
303
+ * Wrapper to "ls -aFL" - this should fix BZ908898
304
+ */
305
+ @ Override
306
+ public String getOwner () {
307
+ try {
308
+ return FileInfoUtil .getLSinfo (theFile .getAbsolutePath ()).
309
+ get ("owner" );
310
+ }
311
+ catch (Exception e ) {
312
+ throw new RuntimeException (e );
313
+ }
314
+ }
315
+
316
+ public FsPermission getPermission () {
317
+ //should be amortized, see method.
318
+ loadPermissionInfo ();
319
+ return super .getPermission ();
320
+ }
321
+
322
+ boolean permsLoaded =false ;
323
+
324
+ /// loads permissions, owner, and group from `ls -ld`
325
+ private void loadPermissionInfo () {
326
+ if (permsLoaded ) {
327
+ return ;
328
+ }
329
+ IOException e = null ;
330
+ try {
331
+ String output ;
332
+ StringTokenizer t = new StringTokenizer (
333
+ output =execCommand (theFile ,
334
+ Shell .getGET_PERMISSION_COMMAND ()));
335
+
336
+ //System.out.println("Output of PERMISSION command = " + output + " for " + this.getPath());
337
+ //expected format
338
+ //-rw------- 1 username groupname ...
339
+ String permission = t .nextToken ();
340
+ if (permission .length () > 10 ) { //files with ACLs might have a '+'
341
+ permission = permission .substring (0 , 10 );
342
+ }
343
+ setPermission (FsPermission .valueOf (permission ));
344
+ t .nextToken ();
345
+ setOwner (t .nextToken ());
346
+ setGroup (t .nextToken ());
347
+ } catch (Shell .ExitCodeException ioe ) {
348
+ if (ioe .getExitCode () != 1 ) {
349
+ e = ioe ;
350
+ } else {
351
+ setPermission (null );
352
+ setOwner (null );
353
+ setGroup (null );
354
+ }
355
+ permsLoaded =true ;
356
+ }
357
+ catch (IOException ioe ) {
358
+ e = ioe ;
359
+ }
360
+ finally {
361
+ if (e != null ) {
362
+ throw new RuntimeException ("Error while running command to get " +
363
+ "file permissions : " +
364
+ StringUtils .stringifyException (e ));
365
+ }
366
+ }
367
+ }
368
+
369
+ }
370
+
371
+ public static String execCommand (File f , String ... cmd ) throws IOException {
372
+ String [] args = new String [cmd .length + 1 ];
373
+ System .arraycopy (cmd , 0 , args , 0 , cmd .length );
374
+ args [cmd .length ] = f .getCanonicalPath ();
375
+ String output = Shell .execCommand (args );
376
+ return output ;
377
+ }
378
+
379
+ /**
380
+ * We ultimately use chmod to set permissions, same as in
381
+ * https://svn.apache.org/repos/asf/hadoop/common/branches/HADOOP-3628/src/core/org/apache/hadoop/fs/RawLocalFileSystem.java
382
+ */
383
+ @ Override
384
+ public void setPermission (Path p , FsPermission permission ){
385
+ try {
386
+ Path absolute = makeAbsolute (p );
387
+ final File f = new File (absolute .toUri ().getPath ());
388
+
389
+ execCommand (f , Shell .SET_PERMISSION_COMMAND ,
390
+ String .format ("%05o" , permission .toShort ()));
391
+ }
392
+ catch (Exception e ){
393
+ throw new RuntimeException (e );
394
+ }
395
+ }
396
+
397
+
277
398
public FileStatus getFileStatus (Path path ) throws IOException {
278
399
Path absolute = makeAbsolute (path );
279
- File f = new File (absolute .toUri ().getPath ());
400
+ final File f = new File (absolute .toUri ().getPath ());
280
401
281
402
if (!f .exists ())
282
403
throw new FileNotFoundException ("File " + f .getPath ()
283
404
+ " does not exist." );
284
-
285
405
FileStatus fs ;
406
+
286
407
// simple version - should work . we'll see.
408
+ // TODO COMPARE these w/ original signatures - do we retain the correct
409
+ // default args?
287
410
if (f .isDirectory ())
288
- fs = new FileStatus (0 , true , 1 , 0 , f .lastModified (),
289
- path .makeQualified (this )) {
290
- public String getOwner () {
291
- return "root" ;
292
- }
293
- };
411
+ fs = new FUSEFileStatus (f , true , 1 , 0 , path .makeQualified (this ));
294
412
else
295
- fs = new FileStatus (f .length (), false , 0 , getDefaultBlockSize (),
296
- f .lastModified (), path .makeQualified (this )) {
297
- public String getOwner () {
298
- return "root" ;
299
- }
300
- };
413
+ fs = new FUSEFileStatus (f , false , 0 , getDefaultBlockSize (),
414
+ path .makeQualified (this ));
301
415
return fs ;
416
+
302
417
}
303
418
304
419
/*
0 commit comments