Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
59ce67e2
Commit
59ce67e2
authored
Feb 08, 2014
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
CompositeStorage: new Storage implementation
This is the backend for the upcoming "mount" command.
parent
2182209a
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
468 additions
and
0 deletions
+468
-0
Makefile.am
Makefile.am
+1
-0
CompositeStorage.cxx
src/storage/CompositeStorage.cxx
+344
-0
CompositeStorage.hxx
src/storage/CompositeStorage.hxx
+123
-0
No files found.
Makefile.am
View file @
59ce67e2
...
...
@@ -428,6 +428,7 @@ libstorage_a_SOURCES = \
src/storage/StoragePlugin.hxx
\
src/storage/Registry.cxx src/storage/Registry.hxx
\
src/storage/StorageInterface.cxx src/storage/StorageInterface.hxx
\
src/storage/CompositeStorage.cxx src/storage/CompositeStorage.hxx
\
src/storage/Configured.cxx src/storage/Configured.hxx
\
src/storage/plugins/LocalStorage.cxx src/storage/plugins/LocalStorage.hxx
\
src/storage/FileInfo.hxx
...
...
src/storage/CompositeStorage.cxx
0 → 100644
View file @
59ce67e2
/*
* Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include "CompositeStorage.hxx"
#include "FileInfo.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <set>
static
constexpr
Domain
composite_domain
(
"composite"
);
/**
* Combines the directory entries of another #StorageDirectoryReader
* instance and the virtual directory entries.
*/
class
CompositeDirectoryReader
final
:
public
StorageDirectoryReader
{
StorageDirectoryReader
*
other
;
std
::
set
<
std
::
string
>
names
;
std
::
set
<
std
::
string
>::
const_iterator
current
,
next
;
public
:
template
<
typename
M
>
CompositeDirectoryReader
(
StorageDirectoryReader
*
_other
,
const
M
&
map
)
:
other
(
_other
)
{
for
(
const
auto
&
i
:
map
)
names
.
insert
(
i
.
first
);
next
=
names
.
begin
();
}
virtual
~
CompositeDirectoryReader
()
{
delete
other
;
}
/* virtual methods from class StorageDirectoryReader */
virtual
const
char
*
Read
()
override
;
virtual
bool
GetInfo
(
bool
follow
,
FileInfo
&
info
,
Error
&
error
)
override
;
};
const
char
*
CompositeDirectoryReader
::
Read
()
{
if
(
other
!=
nullptr
)
{
const
char
*
name
=
other
->
Read
();
if
(
name
!=
nullptr
)
{
names
.
erase
(
name
);
return
name
;
}
delete
other
;
other
=
nullptr
;
}
if
(
next
==
names
.
end
())
return
nullptr
;
current
=
next
++
;
return
current
->
c_str
();
}
bool
CompositeDirectoryReader
::
GetInfo
(
bool
follow
,
FileInfo
&
info
,
Error
&
error
)
{
if
(
other
!=
nullptr
)
return
other
->
GetInfo
(
follow
,
info
,
error
);
assert
(
current
!=
names
.
end
());
info
.
type
=
FileInfo
::
Type
::
DIRECTORY
;
info
.
mtime
=
0
;
info
.
device
=
0
;
info
.
inode
=
0
;
return
true
;
}
static
std
::
string
NextSegment
(
const
char
*&
uri_r
)
{
const
char
*
uri
=
uri_r
;
const
char
*
slash
=
strchr
(
uri
,
'/'
);
if
(
slash
==
nullptr
)
{
uri_r
+=
strlen
(
uri
);
return
std
::
string
(
uri
);
}
else
{
uri_r
=
slash
+
1
;
return
std
::
string
(
uri
,
slash
);
}
}
CompositeStorage
::
Directory
::~
Directory
()
{
delete
storage
;
}
const
CompositeStorage
::
Directory
*
CompositeStorage
::
Directory
::
Find
(
const
char
*
uri
)
const
{
const
Directory
*
directory
=
this
;
while
(
*
uri
!=
0
)
{
const
std
::
string
name
=
NextSegment
(
uri
);
auto
i
=
directory
->
children
.
find
(
name
);
if
(
i
==
directory
->
children
.
end
())
return
nullptr
;
directory
=
&
i
->
second
;
}
return
directory
;
}
CompositeStorage
::
Directory
&
CompositeStorage
::
Directory
::
Make
(
const
char
*
uri
)
{
Directory
*
directory
=
this
;
while
(
*
uri
!=
0
)
{
const
std
::
string
name
=
NextSegment
(
uri
);
#if defined(__clang__) || GCC_CHECK_VERSION(4,8)
auto
i
=
directory
->
children
.
emplace
(
std
::
move
(
name
),
Directory
());
#else
auto
i
=
directory
->
children
.
insert
(
std
::
make_pair
(
std
::
move
(
name
),
Directory
()));
#endif
directory
=
&
i
.
first
->
second
;
}
return
*
directory
;
}
bool
CompositeStorage
::
Directory
::
Unmount
()
{
if
(
storage
==
nullptr
)
return
false
;
delete
storage
;
storage
=
nullptr
;
return
true
;
}
bool
CompositeStorage
::
Directory
::
Unmount
(
const
char
*
uri
)
{
const
std
::
string
name
=
NextSegment
(
uri
);
auto
i
=
children
.
find
(
name
);
if
(
i
==
children
.
end
()
||
!
i
->
second
.
Unmount
())
return
false
;
if
(
i
->
second
.
IsEmpty
())
children
.
erase
(
i
);
return
true
;
}
bool
CompositeStorage
::
Directory
::
MapToRelativeUTF8
(
std
::
string
&
buffer
,
const
char
*
uri
)
const
{
if
(
storage
!=
nullptr
)
{
const
char
*
result
=
storage
->
MapToRelativeUTF8
(
uri
);
if
(
result
!=
nullptr
)
{
buffer
=
result
;
return
true
;
}
}
for
(
const
auto
&
i
:
children
)
{
if
(
i
.
second
.
MapToRelativeUTF8
(
buffer
,
uri
))
{
buffer
.
insert
(
buffer
.
begin
(),
'/'
);
buffer
.
insert
(
buffer
.
begin
(),
i
.
first
.
begin
(),
i
.
first
.
end
());
return
true
;
}
}
return
false
;
}
CompositeStorage
::
CompositeStorage
()
{
}
CompositeStorage
::~
CompositeStorage
()
{
}
void
CompositeStorage
::
Mount
(
const
char
*
uri
,
Storage
*
storage
)
{
const
ScopeLock
protect
(
mutex
);
Directory
&
directory
=
root
.
Make
(
uri
);
if
(
directory
.
storage
!=
nullptr
)
delete
directory
.
storage
;
directory
.
storage
=
storage
;
}
bool
CompositeStorage
::
Unmount
(
const
char
*
uri
)
{
const
ScopeLock
protect
(
mutex
);
return
root
.
Unmount
(
uri
);
}
CompositeStorage
::
FindResult
CompositeStorage
::
FindStorage
(
const
char
*
uri
)
const
{
FindResult
result
{
&
root
,
uri
};
const
Directory
*
directory
=
&
root
;
while
(
*
uri
!=
0
)
{
const
std
::
string
name
=
NextSegment
(
uri
);
auto
i
=
directory
->
children
.
find
(
name
);
if
(
i
==
directory
->
children
.
end
())
break
;
directory
=
&
i
->
second
;
if
(
directory
->
storage
!=
nullptr
)
result
=
FindResult
{
directory
,
uri
};
}
return
result
;
}
CompositeStorage
::
FindResult
CompositeStorage
::
FindStorage
(
const
char
*
uri
,
Error
&
error
)
const
{
auto
result
=
FindStorage
(
uri
);
if
(
result
.
directory
==
nullptr
)
error
.
Set
(
composite_domain
,
"No such directory"
);
return
result
;
}
bool
CompositeStorage
::
GetInfo
(
const
char
*
uri
,
bool
follow
,
FileInfo
&
info
,
Error
&
error
)
{
const
ScopeLock
protect
(
mutex
);
auto
f
=
FindStorage
(
uri
,
error
);
if
(
f
.
directory
->
storage
!=
nullptr
&&
f
.
directory
->
storage
->
GetInfo
(
f
.
uri
,
follow
,
info
,
error
))
return
true
;
const
Directory
*
directory
=
f
.
directory
->
Find
(
f
.
uri
);
if
(
directory
!=
nullptr
)
{
error
.
Clear
();
info
.
type
=
FileInfo
::
Type
::
DIRECTORY
;
info
.
mtime
=
0
;
info
.
device
=
0
;
info
.
inode
=
0
;
return
true
;
}
return
false
;
}
StorageDirectoryReader
*
CompositeStorage
::
OpenDirectory
(
const
char
*
uri
,
Error
&
error
)
{
const
ScopeLock
protect
(
mutex
);
auto
f
=
FindStorage
(
uri
,
error
);
const
Directory
*
directory
=
f
.
directory
->
Find
(
f
.
uri
);
if
(
directory
==
nullptr
||
directory
->
children
.
empty
())
{
/* no virtual directories here */
if
(
f
.
directory
->
storage
==
nullptr
)
return
nullptr
;
return
f
.
directory
->
storage
->
OpenDirectory
(
f
.
uri
,
error
);
}
StorageDirectoryReader
*
other
=
f
.
directory
->
storage
->
OpenDirectory
(
f
.
uri
,
IgnoreError
());
return
new
CompositeDirectoryReader
(
other
,
directory
->
children
);
}
std
::
string
CompositeStorage
::
MapUTF8
(
const
char
*
uri
)
const
{
const
ScopeLock
protect
(
mutex
);
auto
f
=
FindStorage
(
uri
);
if
(
f
.
directory
->
storage
==
nullptr
)
return
std
::
string
();
return
f
.
directory
->
storage
->
MapUTF8
(
f
.
uri
);
}
AllocatedPath
CompositeStorage
::
MapFS
(
const
char
*
uri
)
const
{
const
ScopeLock
protect
(
mutex
);
auto
f
=
FindStorage
(
uri
);
if
(
f
.
directory
->
storage
==
nullptr
)
return
AllocatedPath
::
Null
();
return
f
.
directory
->
storage
->
MapFS
(
f
.
uri
);
}
const
char
*
CompositeStorage
::
MapToRelativeUTF8
(
const
char
*
uri
)
const
{
const
ScopeLock
protect
(
mutex
);
if
(
root
.
storage
!=
nullptr
)
{
const
char
*
result
=
root
.
storage
->
MapToRelativeUTF8
(
uri
);
if
(
result
!=
nullptr
)
return
result
;
}
if
(
!
root
.
MapToRelativeUTF8
(
relative_buffer
,
uri
))
return
nullptr
;
return
relative_buffer
.
c_str
();
}
src/storage/CompositeStorage.hxx
0 → 100644
View file @
59ce67e2
/*
* Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPD_COMPOSITE_STORAGE_HXX
#define MPD_COMPOSITE_STORAGE_HXX
#include "check.h"
#include "StorageInterface.hxx"
#include "thread/Mutex.hxx"
#include "Compiler.h"
#include <string>
#include <map>
class
Error
;
class
Storage
;
/**
* A #Storage implementation that combines multiple other #Storage
* instances in one virtual tree. It is used to "mount" new #Storage
* instances into the storage tree.
*
* This class is thread-safe: mounts may be added and removed at any
* time in any thread.
*/
class
CompositeStorage
final
:
public
Storage
{
/**
* A node in the virtual directory tree.
*/
struct
Directory
{
/**
* The #Storage mounted n this virtual directory. All
* "leaf" Directory instances must have a #Storage.
* Other Directory instances may have one, and child
* mounts will be "mixed" in.
*/
Storage
*
storage
;
std
::
map
<
std
::
string
,
Directory
>
children
;
Directory
()
:
storage
(
nullptr
)
{}
~
Directory
();
gcc_pure
bool
IsEmpty
()
const
{
return
storage
==
nullptr
&&
children
.
empty
();
}
gcc_pure
const
Directory
*
Find
(
const
char
*
uri
)
const
;
Directory
&
Make
(
const
char
*
uri
);
bool
Unmount
();
bool
Unmount
(
const
char
*
uri
);
gcc_pure
bool
MapToRelativeUTF8
(
std
::
string
&
buffer
,
const
char
*
uri
)
const
;
};
struct
FindResult
{
const
Directory
*
directory
;
const
char
*
uri
;
};
/**
* Protects the virtual #Directory tree.
*
* TODO: use readers-writer lock
*/
mutable
Mutex
mutex
;
Directory
root
;
mutable
std
::
string
relative_buffer
;
public
:
CompositeStorage
();
virtual
~
CompositeStorage
();
void
Mount
(
const
char
*
uri
,
Storage
*
storage
);
bool
Unmount
(
const
char
*
uri
);
/* virtual methods from class Storage */
virtual
bool
GetInfo
(
const
char
*
uri
,
bool
follow
,
FileInfo
&
info
,
Error
&
error
)
override
;
virtual
StorageDirectoryReader
*
OpenDirectory
(
const
char
*
uri
,
Error
&
error
)
override
;
virtual
std
::
string
MapUTF8
(
const
char
*
uri
)
const
override
;
virtual
AllocatedPath
MapFS
(
const
char
*
uri
)
const
override
;
virtual
const
char
*
MapToRelativeUTF8
(
const
char
*
uri
)
const
override
;
private
:
gcc_pure
FindResult
FindStorage
(
const
char
*
uri
)
const
;
FindResult
FindStorage
(
const
char
*
uri
,
Error
&
error
)
const
;
const
char
*
MapToRelativeUTF8
(
const
Directory
&
directory
,
const
char
*
uri
)
const
;
};
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment