P2PFUSE-OPENDHT A BUG

This is the blog to record a bug that I encountered in the process of developing my P2P File System.

Introduction

By saying P2P file system, I mean that this file system doesn’t store the files storaged in the local disk. It will call the API provided by another P2P platform to fetch the data from it, and display the content returned.

For the file system part, I choose FUSE as the tool to develope a user-level file system. In this case, I don’t need to dive into the low-level detail about the disk or something else. Rather, I just need to implement specific API that FUSE provides, where I fill the data to the given data structure such as buf. And then the system API will call the user-defined API, fetch the required data and form the files.

For the P2P part, I choose the open source project OpenDHT as the backend of the file storage. Though there’re some limitations like the uploading data could only exist 10mins by default, garbled character after the user input string, overall, this has provided adequate functions for our system.

The BUG

Finally, this is the most important part of this blog. Well, actually it is kind of shamed for me to get a bug like this. Because this is a really fundamental-level bug in a high-level project. And the lesson I learnt from this is that, I need to study the fundamental knowledge more and more.

First of all, I decalre the header file which includes many definitions of the functions, class and global variables. And the issues lie at the global variables.

1
2
3
4
5
6
7
8
9
10
namespace nbfs {
// hard coded user name, used for the namespace for files
static std::string user_name = "hongbo/";

// connection entry
static dht::DhtRunner node;

// root file node
static FileNode* root;
}

Here is the definition of all the global variables. All the operations rely on the entry point provided by them. Well, it is totally fine with the first user_name variable, becase we don’t want it to be modified, and it should be visible to all the functions.

However, for the latter two variables, there’s a huge mistake. I set them to be static. In which case, the variable imported by the source file ending with cpp will all have different entry point of their own version. For example, I initialize the entry point in main.cpp file, however, when I call in the operations.cpp file, it will be set to NULL. I spent a huge time on this, because the core function dht::get() function will be called even though the node has not been initialized. And I just sticked on this point over and over again, failed to get the truth that the variable should not be static.

The solution

The correct way to declare the global variable in cpp is to give the definition in the header file like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// hard coded user name, used for the namespace for files
static std::string user_name = "hongbo/";

// connection entry
extern dht::DhtRunner node;

// root file node
extern FileNode* root;

// map for file names
extern std::map<std::string, bool> exists;

// log file
extern FILE *logfile;

And this is just the definition, we will need to declare it in the source file where we initialize it. After that, all other files includes the header file could directly call the global variables right now.

0%