Home > Blog > Programming > GSoC: ownCloud Sharing Folders

GSoC: ownCloud Sharing Folders

June 28th, 2011

ownCloud Folder Sharing

This past week I had intended to work on file permissions and user group file sharing. Unfortunately, niether of those were even started. Instead of working on those I decided that it was more important to implement sharing of folders. Along the way I did some refactoring in how I fetch the source locations from within the shared storage provider and the database. 

As I mentioned in my first post about ownCloud Sharing, the source and target locations are stored in the database for the shared files. Files are easy to work with in the shared storage provider because the target location matches up with a source location in the database. This isn’t the case with folders because the source and target locations in the database only show that the folder is shared, and has no understanding of what files are inside of that folder. This means that I have to manipulate the path I get from the shared storage provider in order to get the correct source location of the folder that is shared.

It sounded fairly easy to me, but it still took me a while to get working and I confused myself about it on numerous occasions. I decided to try out recursion for solving this problem because I needed to check each parent directory of the target to find out which one is the shared folder. I’ve never actually programmed a recursion function before so I thought it would be a great learning experience. I got a little confused with the recursion along the way, and was suprised when it actually started working. What it does is if it doesn’t get a result from the database, it will call dirname() on the target to get the parent directory and then calls itself again with the parent directory location. Once it gets a result it will append the part of the string removed by dirname() with basename(). It works perfectly and didn’t require very much programming.

public static function getSource($target) {
		$query = OC_DB::prepare("SELECT source FROM *PREFIX*sharing WHERE target = ? AND uid_shared_with = ?");
		$result = $query->execute(array($target, $_SESSION['user_id']))->fetchAll();
		if (count($result) > 0) {
			return $result[0]['source'];
		} else {
			// Check if the parent directory of this target is shared
			$parentDir = dirname($target);
			if ($parentDir != ".") {
				$result = OC_SHARE::getSource($parentDir);
				if ($result) {
					return $result."/".basename($target);
				} else {
					return false;
				}
			} else {
				return false;
			}
		}
}

After a few other additions to the shared storage provider I now have folder sharing implemented. While rewriting my getSource function for the share library I realized that I was doing a large number of queries to the database. It’s actually more than just the number of shared files, because the shared storage providers has multiple functions called for each file. Inside of shared folders I was doing over 100 queries to the database because of the way the recursion worked. I can’t think of a better way to fetch the source location, so I had the shared storage provider cache the source locations for the targets. This is done with a simple array with the array keys being the target locations and the values are the matching source locations. If the array key doesn’t exist, it uses the getSource function in the share library to fetch the source location.

In the tests I conducted with my shared files I had 9 queries with caching versus 56, and one directory level lower I had 20 queries with caching versus 124. These are still high numbers and the queries increase with the number of files. I believe I can do a little more caching with the shared folders to reduce it down to only a few queries, but I’m also considering just fetching all the shared files in one query. I’m not sure if I want to do this because it won’t need all of that information in one instance.

I’ll be away for the next 3 days, but when I get back I’ll be working on including the full path in the target location of the shared storage provider. For example I’d prefer if it used /MTGap/files/… This way I could setup the environment for shared files anywhere in your filesystem. Maybe after that I’ll actually get to file permissions and user group sharing.

Categories: Programming Tags: , ,
  1. June 29th, 2011 at 02:58 | #1

    While this would not limit the number of queries you could make the queries faster by appending a “LIMIT 1″ to it. You are using only the first result anyway so the database can stop searching for more on the first match.

  2. mutlu
    June 29th, 2011 at 04:40 | #2

    Folder sharing. :) Awesome!

  3. July 8th, 2011 at 15:35 | #3

    @Dakon Thanks for the tip! I’m now using LIMIT 1 in my database queries.

Comments are closed.