I would like to build a FUSE-based underland filesystem application, in Java.
There are a few bindings library available on the web, Fuse-J, jnetfs, Fuseforjava, javafuse.
None of them seem really alive as of today, so I gave my first try to JavaFuse.
The interface we must implement is there:
http://code.google.com/p/javafuse/source/browse/fs/JavaFS.java
and I wanted to reproduce this fuse helloworld example.
Question: Is there any chance that this:
static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
{
(void) offset;
(void) fi;
if(strcmp(path, "/") != 0)
return -ENOENT;
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
filler(buf, hello_path + 1, NULL, 0);
return 0;
}
can be implemented by this java function:
public int readdir_pre(String path, long buf, long filler, int offset, Fuse_file_info info);
public int readdir_post(String path, long buf, long filler, int offset, Fuse_file_info info, int result);
Fuse_file_info
Maybe I missed something, but I can't see how to use filler to populate the directory content ...
There are other oddities just for this helloworld example, like:
public int read_post(String path, String buf, int size, int offset, Fuse_file_info info, int result);
which is supposed to fill buf with size bytes of data, whereas Java String are supposed to be immutable.
You can try jnr-fuse project.
The project uses JNR, so you achieve full JNI performance and ease of implementation.
An example of implementation hello-world filesystem filter.
I'm not exactly sure, what you are trying to do with the double function read_pre & read_post.
Though I guess, they represent pre-work and post-work. Maybe you can declare the normal readdir() and call you pre & post from inside? Passing the same arguments back & forth? Because you have to declare readdir() to the fuse_main().
And about the second thing with buffers, it just expects a byte holding storage. You can pass it character arrays, or anything with bytes in it, denoted by size_t size that represents the size of buffer. In helloworld.c, the string characters are copied to buffer through memcpy(). You can read bytes from file and pass them on as buffer along with appropriate length.
I'm new to FUSE and would like to know how it is to work using Java as compared to the standard C.
Related
Good morning,
I am trying to understand the low lattency library aeron, I have an instance of the class Publication:
Publication publication=new Publication(CHANNEL, STREAM_ID);
Where:
CHANNEL=System.getProperty("aeron.sample.channel", "aeron:udp?endpoint=224.0.1.1:40456");
and
STREAM_ID=Integer.getInteger("aeron.sample.streamId", 10);
After creating the instance, to send a message what it does is:
String a="What I want to send"; //Text that I want to send
bytes[] aBytes=a.getBytes(); // Convert the string to an array of bytes
UnsafeBuffer BUFFER = new UnsafeBuffer(BufferUtil.allocateDirectAligned(256, 64)); //Create an UnsafeBuffer (https://github.com/real-logic/agrona/blob/master/agrona/src/main/java/org/agrona/concurrent/UnsafeBuffer.java)
BUFFER.putBytes(0, aBytes); //Put the Bytes of the array of bytes that contains the text intro tje BUFFER
final long result = publication.offer(BUFFER, 0, messageBytes.length); //This is the last line of the code to send the message, so I guess that this line is used to send the message to the mediaDriver.
I want to understand how the last line of code works, Method offer() is at the following file: https://github.com/real-logic/aeron/blob/master/aeron-client/src/main/java/io/aeron/Publication.java
At line 373 There is the following method:
public final long offer(final DirectBuffer buffer, final int offset, final int length)
{
return offer(buffer, offset, length, null);
}
That returns a function, If I search for this function in the Publication.java file I only found the following:
public abstract long offer(DirectBuffer buffer, int offset, int length, ReservedValueSupplier reservedValueSupplier);
It's an abstract method that I don't know where I could found the definition of it.
If someone could help me I will appreciate a lot to understand how this library works.
I bet you have found all answers but in case for future searchers:
There are 2 implementation of Publication class :
ConcurrentPublication
ExclusivePublication
I can recomend to watch Martin's video about how Aeron works https://www.youtube.com/watch?v=tM4YskS94b0
In the past I have written code which handles incoming data from a serial port. The data has a fixed format.
Now I want to migrate this code to java (android). However, I see many obstacles.
The actual code is more complex, but I have a simplified version here:
#define byte unsigned char
#define word unsigned short
#pragma pack(1);
struct addr_t
{
byte foo;
word bar;
};
#pragma pack();
bool RxData( byte val )
{
static byte buffer[20];
static int idx = 0;
buffer[idx++] = val;
return ( idx == sizeof(addr_t) );
}
The RxData function is called everytime a byte is received. When the complete chunk of data is in, it returns true.
Some of the obstacles:
The used data types are not available to java. In other threads it is recommended to use larger datatypes, but in this case this is not a workable solution.
The size of the structure is in this case exactly 3 bytes. That's also why the #pragma statement is important. Otherwise the C compiler might "optimize" it for memory use, with a different size as a result.
Java also doesn't have a sizeof function and I have found no alternative for this kind of situation.
I could replace the 'sizeof' with a fixed value of 3, but that would be very bad practice IMO.
Is it at all possible to write such a code in java? Or is it wiser to try to add native c source into Android Studio?
Your C code has its problems too. Technically, you do not know how big a char and a short is. You probably want uint8_t and uint16_t respectively. Also, I'm not sure how portable packing is.
In Java, you need a class. The class might as well tell you how many bytes you need to initialise it.
class Addr
{
private byte foo;
private short bar;
public final static int bufferBytes = 3;
public int getUnsignedFoo()
{
return (int)foo & 0xff;
}
public int getUnsignedBar()
{
return (int)bar & 0xffff;
}
}
Probably a class for the buffer too although there may already be a suitable class in the standard library.
class Buffer
{
private final static int maxSize = 20;
private byte[] bytes = new byte[maxSize];
private int idx = 0;
private bool rxData(byte b)
{
bytes[idx++] = b;
return idx == Addr.bufferBytes;
}
}
To answer the question about the hardcodedness of the 3, this is actually the better way to do it because your the specification of your protocol should say "one byte for foo and two bytes for bar" not "a packed C struct with a char and a short in it". One way to deserialise the buffer is like this:
public class Addr
{
// All the stuff from above
public Addr(byte[] buffer)
{
foo = buffer[0];
bar = someFunctionThatGetsTheEndiannessRight(buffer[1], buffer[2]);
}
}
TI have left the way bar is calculated deliberately vague because it depends on your platform as much as anything. You can do it simply with bit shifts e.g.
(((short)buffer[1] & 0xff) << 8) | ((short)buffer[2] & 0xff)
However, there are better options available. For example, you can use a java.nio.ByteBuffer which has the machinery to cope with endian isssues.
Native Code :
writing number 27 using fwrite().
int main()
{
int a = 27;
FILE *fp;
fp = fopen("/data/tmp.log", "w");
if (!fp)
return -errno;
fwrite(&a, 4, 1, fp);
fclose();
return 0;
}
Reading back the data(27) using DataInputStream.readInt() :
public int readIntDataInputStream(void)
{
String filePath = "/data/tmp.log";
InputStream is = null;
DataInputStream dis = null;
int k;
is = new FileInputStream(filePath);
dis = new DataInputStream(is);
k = dis.readInt();
Log.i(TAG, "Size : " + k);
return 0;
}
O/p
Size : 452984832
Well that in hex is 0x1b000000
0x1b is 27. But the readInt() is reading the data as big endian while my native coding is writing as little endian. . So, instead of 0x0000001b i get 0x1b000000.
Is my understanding correct? Did anyone came across this problem before?
From the Javadoc for readInt():
This method is suitable for reading bytes written by the writeInt method of interface DataOutput
If you want to read something written by a C program you'll have to do the byte swapping yourself, using the facilities in java.nio. I've never done this but I believe you would read the data into a ByteBuffer, set the buffer's order to ByteOrder.LITTLE_ENDIAN and then create an IntBuffer view over the ByteBuffer if you have an array of values, or just use ByteBuffer#getInt() for a single value.
All that aside, I agree with #EJP that the external format for the data should be big-endian for greatest compatibility.
There are multiple issues in your code:
You assume that the size of int is 4, it is not necessarily true, and since you want to deal with 32-bit ints, you should use int32_t or uint32_t.
You must open the file in binary more to write binary data reliably. The above code would fail on Windows for less trivial output. Use fopen("/data/tmp.log", "wb").
You must deal with endianness. You are using the file to exchange data between different platforms that may have different native endianness and/or endian specific APIs. Java seems to use big-endian, aka network byte order, so you should convert the values on the C platform with the hton32() utility function. It is unlikely to have significant impact on performance on the PC side, as this function is usually expanded inline, possibly as a single instruction and most of the time will be spent waiting for I/O anyway.
Here is a modified version of the code:
#include <endian.h>
#include <stdint.h>
#include <stdio.h>
int main(void) {
uint32_t a = hton32(27);
FILE *fp = fopen("/data/tmp.log", "wb");
if (!fp) {
return errno;
}
fwrite(&a, sizeof a, 1, fp);
fclose();
return 0;
}
I know that Java is no C, so no pointers and direct usable addresses but still I need it, because of the given library.
The library Andglk has been ported from native C and whoever did it, has the following constructor declaration in one of the classes:
public LineInputEvent(Window w, String s, int lineBuffer,
long maxLen, int dispatchRock, boolean unicode)
I now want to create one such event, but have no idea how to specify the lineBuffer. About the dispatchRock - it is also problematic but I believe it is not the bigger problem here.
Basically, this int lineBuffer (as the dispatchRock) is used one for all events during a session. One example is 1405421324 for all inputs.
About it (in the C documentation, there is for now almost nothing about andglk) is said:
This text will be placed in a buffer of your choice.
Any idea how can I specify it in Java for a given String?
EDIT:
This is from the andglk.c:
int andglk_loader_glk_MemoryStream_retainVmArray(JNIEnv *env, jobject this, int buffer, long length)
{
if (gli_register_arr) {
gidispatch_rock_t rock = gli_register_arr((void *)buffer, length, gidispatch_char_array);
return rock.num;
}
}
I am using a library libfprint on ubuntu nd I am trying to call a function through my java code.
API_EXPORTED struct fp_img *fpi_img_new(size_t length)
{
struct fp_img *img = g_malloc(sizeof(*img) + length);
memset(img, 0, sizeof(*img));
fp_dbg("length=%zd", length);
img->length = length;
return img;
}
I am passing integer value 5 from my java code to this function. When I try to execute above function I got following errors:
GLib-ERROR **: /build/buildd/glib2.0-2.30.0/./glib/gmem.c:170: failed to allocate 3077591024 bytes
I have tried same code on 2 different ubuntu machine but the error remains the same. I dont know why it is trying to allocate so many bytes for 24+5 length.
Could anyone suggest me any solution?
The source code clearly states:
/* structs that applications are not allowed to peek into */
(...)
struct fp_img;
So, I'm not sure what you did in order to even compile something that needs the size of struct fp_img: you're not supposed to be able to do that, since the structure declaration is opaque.
It look like you get a pointer instead of a size_t.
Try to change your definition to:
API_EXPORTED struct fp_img *fpi_img_new(size_t * length);
You then need to derefenrece it:
API_EXPORTED struct fp_img *fpi_img_new(size_t * length)
{
struct fp_img *img = g_malloc(sizeof(*img) + *length);
memset(img, 0, sizeof(*img));
fp_dbg("length=%zd", *length);
img->length = *length;
return img;
}
Note: It seems that 3077591024 is on the stack (0x125807FE) it is highly platform dependent so don't quote me on that.
What happens if you change
sizeof(*img)
with
sizeof(struct fp_img)
? I'm thinking that this could be your problem because *img is not initialised to anything at the time you are calling g_malloc().
ERROR: struct fp_img *img = g_malloc(sizeof(*img) + length);
*img is new created, so you can not use it like "sizeof(*img)",
you could write like this: "sizeof(struct fp_img)"