Commit Graph

1026 Commits

Author SHA1 Message Date
Max Kellermann 5f262da09d db/simple: remove unused method LookupDirectory() 2014-02-25 20:13:40 +01:00
Max Kellermann 82985a9488 db/simple: make internal methods "private" 2014-02-25 19:48:01 +01:00
Max Kellermann afcdb65f80 db/simple: add comment 2014-02-25 18:17:54 +01:00
Max Kellermann 6b66e86f40 db/simple: move Create() up 2014-02-25 18:17:39 +01:00
Max Kellermann cb145d290e DirectorySave: save the flags "DEVICE_INARCHIVE" and "DEVICE_CONTAINER"
Helps avoid unnecessary archive scans during database update on a
fresh MPD process.
2014-02-25 18:16:19 +01:00
Max Kellermann 167803d2a1 DatabaseSave: increase DB_FORMAT version 2014-02-25 18:16:06 +01:00
Max Kellermann 58a981d2f6 DatabaseSave: add constant OLDEST_DB_FORMAT 2014-02-25 18:15:55 +01:00
Max Kellermann 8963cd1fab DirectorySave: move code to ParseLine() 2014-02-25 18:15:43 +01:00
Max Kellermann 55cd5a9a78 DirectorySave: save the mtime only if it is known 2014-02-24 21:17:06 +01:00
Max Kellermann 33fc3af775 SongSort, ...: use libicu instead of GLib's g_utf8_*() 2014-02-24 20:39:37 +01:00
Max Kellermann 25431f32a2 DecoderPlugin: free the container_scan() return value with delete[] 2014-02-24 20:19:34 +01:00
Max Kellermann 09e5f17b5d Directory: use PathTraitsUTF8::Build() instead of g_strconcat() 2014-02-23 22:02:39 +01:00
Max Kellermann db20e29af6 Directory: pass std::string&& to constructor 2014-02-23 22:02:02 +01:00
Max Kellermann b7a7953757 db/Directory: use "unsigned" for inode and device
This is what we get from the storage plugin via FileInfo.  Fixes a
compiler warning on Mac OS X where dev_t appears to be signed.
2014-02-21 10:48:43 +01:00
Max Kellermann e92a41fa3a db/upnp: move plugin source to upnp directory 2014-02-19 23:46:00 +01:00
Max Kellermann 150443b014 DatabasePlugin: add FLAG_REQUIRE_STORAGE
Ignore the storage configuration if FLAG_REQUIRE_STORAGE is not set in
the DatabasePlugin.
2014-02-19 23:24:17 +01:00
Max Kellermann 9e36af7916 DatabasePlugin: add attribute "flags" 2014-02-19 23:24:15 +01:00
Max Kellermann 85b8675e7a db/Interface: add attribute "plugin"
The new method IsPlugin() replaces the "is_simple" flag.
2014-02-19 23:17:21 +01:00
Max Kellermann ae594ad92c DatabasePlugin: split header 2014-02-19 22:54:52 +01:00
Max Kellermann 579e48edbb util/StringUtil: add function Strip()
Replaces g_strstrip().
2014-02-17 22:37:43 +01:00
Max Kellermann 91729437a0 Main: initialize Database before Storage 2014-02-17 22:14:00 +01:00
Max Kellermann 1ddd00433e db/Configured: disallow both "db_file" and "database"
This is misconfiguration, and MPD should abort.
2014-02-17 22:13:53 +01:00
Max Kellermann de160bb2d1 Main: move code to db/Configured.cxx 2014-02-17 22:13:53 +01:00
Max Kellermann 6da0af94df db/DatabaseSimple: remove obsolete header 2014-02-17 20:44:03 +01:00
Max Kellermann 2182209a8a db/update/Walk: disable FindAncestorLoop() if device/inode==0 2014-02-09 10:47:29 +01:00
Max Kellermann e29a8b3a9c db/update/Walk: document FindAncestorLoop() 2014-02-09 10:46:39 +01:00
Max Kellermann ace3f37af4 db/update/Walk: rename find_inode_ancestor() to FindAncestorLoop() 2014-02-09 10:46:39 +01:00
Max Kellermann fe7c6fee34 ArchivePlugin: pass Path to open() 2014-02-08 13:25:44 +01:00
Max Kellermann 9906daeca7 ArchivePlugin: rename struct archive_plugin to ArchivePlugin 2014-02-08 13:22:13 +01:00
Max Kellermann f947274626 InotifyUpdate: use class Storage instead of Mapper.cxx 2014-02-07 22:30:40 +01:00
Max Kellermann f6939f71a7 InotifyUpdate: use the root name instead of mapper_get_music_directory_fs()
The root WatchDirectory instance already contains the music directory,
and we don't need to fetch it again.
2014-02-07 22:30:01 +01:00
Max Kellermann 25aa17ad89 InotifyUpdate: move functions into the WatchDirectory class 2014-02-07 22:24:26 +01:00
Max Kellermann 05ee057db5 InotifyUpdate: remove unnecessary #ifdefs 2014-02-07 22:17:27 +01:00
Max Kellermann ffd16b55a6 StoragePlugin: add method MapToRelativeUTF8()
Replaces map_to_relative_path() from Mapper.cxx.
2014-02-07 19:09:28 +01:00
Max Kellermann 6b421cc354 DecoderPlugin: pass Path instance to file_decode() and scan_file() 2014-02-07 18:52:19 +01:00
Max Kellermann 4ab4cf8532 SongUpdate: pass Storage to UpdateFileInArchive() 2014-02-07 18:44:47 +01:00
Max Kellermann c13810ebaa Mapper: move map_song_detach() to db/DatabaseSong.cxx
Use Storage::MapUTF8() internally, don't use global variables.
2014-02-07 00:42:14 +01:00
geneticdrift 0f1f509be7 fixed leaked LocalDirectoryReader *const reader in UpdateWalk::UpdateDirectory 2014-02-06 23:08:24 +01:00
Max Kellermann 29b18d9ab7 SongUpdate: use the Storage interface, support remote files
This commit finally allows the database update to scan remote files,
e.g. using the smbclient storage plugin.  However, it is not yet
possible to configure that, therefore the feature is not accessible
yet.
2014-02-06 19:06:08 +01:00
Max Kellermann f6682aae77 db/update: include StorageInterface.hxx instead of LocalStorage.hxx 2014-02-05 19:26:18 +01:00
Max Kellermann 0ba1b73395 storage: add abstract interface
Prepare for the plugin interface.
2014-02-05 18:53:51 +01:00
Max Kellermann 4c995eb498 db/UpdateWalk: move LocalStorage to Instance
Keep only a reference.
2014-02-05 17:58:13 +01:00
Max Kellermann 144cfe70bf db/update/Remove: initialize attribute "removed_song"
Fixes bogus assertion failure.
2014-02-05 17:58:13 +01:00
Max Kellermann 9ae7f186bc LocalStorage: new API abstracting filesystem walk
Prepare to make this a new plugin API, for example to use a SMB share
for the music_directory.
2014-02-05 10:04:03 +01:00
Max Kellermann f8d114be42 db/UpdateIO: add "pure" attributes 2014-02-05 10:04:03 +01:00
Max Kellermann 2c70251df1 db/UpdateGlue: relax assertion
Fixes assertion failure when update gets launched during MPD startup.
2014-02-05 10:04:03 +01:00
Max Kellermann ff665b37cb db/DatabaseListener: add method OnDatabaseSongRemoved()
Decouples db/update/Remove.cpp from global variables.
2014-02-04 19:53:37 +01:00
Max Kellermann ce73843014 db/proxy: include cleanup 2014-02-04 19:53:12 +01:00
Max Kellermann eec6d09959 db/update/Service: use DatabaseListener instead of Instance
Don't use the global variable "instance".
2014-02-04 18:54:54 +01:00
Max Kellermann c5fa8ed321 db/update/Service: use EventLoop::IsInside()
Don't use the global variable "main_thread".
2014-02-04 18:54:45 +01:00
Max Kellermann cf6281a5a7 Instance: add Database attribute
Move from db/DatabaseGlue.cxx, eliminating global variable.
2014-02-04 11:22:33 +01:00
Max Kellermann c953904343 db/update/Service: initialize "progress" and "update_task_id"
Database update was randomly broken due to these uninitialized
variables.
2014-02-04 11:22:13 +01:00
Max Kellermann d76b6f878e db/update/Service: add SimpleDatabase reference
Don't use the global variables from the DatabaseSimple library.
2014-02-04 09:05:32 +01:00
Max Kellermann f25ef8d682 db/update/Walk: add Directory reference parameter
Remove dependency on the DatabaseSimple library.
2014-02-04 09:05:32 +01:00
Max Kellermann 33a2c01ea2 db/Simple: remove unused function db_get_directory() 2014-02-04 09:03:17 +01:00
Max Kellermann 29072797ca db/DatabasePlaylist: pass Database reference around
Reduce global variable usage, move to frontend code.
2014-02-04 00:57:43 +01:00
Max Kellermann db69ceade6 db/LightSong: make "real_uri" a pointer
Reduce overhead.  LightSong can always point to the "real" allocated
string.
2014-02-04 00:38:52 +01:00
Max Kellermann 78689645dc db/update/Archive: delete archive from database on error 2014-01-31 22:24:28 +01:00
Max Kellermann 26970579b8 db/update/Editor: add locking method variants 2014-01-31 22:17:49 +01:00
Max Kellermann 04b4f53488 db/update: convert runtime check to assertion 2014-01-31 21:59:35 +01:00
Max Kellermann a631200cca update/Walk: declare std::string at assignment
Reduce overhead.
2014-01-30 22:19:56 +01:00
Max Kellermann c6725884bc db/update: convert to OO API
Move global variables into the new classes.  That may allow multiple
update threads for multiple databases one day.
2014-01-30 18:47:05 +01:00
Max Kellermann d5b017407d ExcludeList: move to db/update/ 2014-01-30 10:11:12 +01:00
Max Kellermann 4b044bd8e1 InotifyUpdate: pass EventLoop to mpd_inotify_init() 2014-01-29 18:36:32 +01:00
Max Kellermann a137f817f5 db/Directory: move isRootDirectory() to Uri.hxx
Decouple command/OtherCommands.cxx from the "simple" database plugin.
2014-01-29 18:05:33 +01:00
Max Kellermann f548a966f5 Playlist{Info,Vector}: move to db/ 2014-01-27 11:05:21 +01:00
Max Kellermann 3dad837ca6 db/upnp: remove sleep(2) call
This call was unnecessary.  It is a bad idea anyway to block the MPD
process for some arbitrary amount of time.
2014-01-26 15:50:30 +01:00
Max Kellermann d7e78059b0 upnp: initialize the client handle only once
Eliminate class LibUPnP and move the code to ClientInit.cxx.  Its
initialization function can be called multiple times, but
UpnpRegisterClient() is called at most once.
2014-01-26 15:43:23 +01:00
Max Kellermann e57e89b9d5 upnp/discovery: use a plain UpnpClient_Handle instead of class LibUPnP 2014-01-26 15:22:33 +01:00
Max Kellermann f86f5ad224 db/upnp: move generic code to lib/upnp/ 2014-01-26 13:41:40 +01:00
Max Kellermann 4a3dc2cea2 db/upnp: rename variables 2014-01-26 13:08:52 +01:00
Max Kellermann 97391fd4b9 DespotifyUtils, Expat: move to lib/ 2014-01-24 16:44:36 +01:00
Max Kellermann 9d34fc394c Database*: move to db/ 2014-01-24 16:38:44 +01:00
Max Kellermann 197b503f3e Config*: move to config/ 2014-01-24 00:20:01 +01:00
Max Kellermann b8e382b011 db/upnp/Discovery: use std::list instead of std::map
There will only be very few items, and that does not justify the bloat
of std::map.
2014-01-23 22:35:22 +01:00
Max Kellermann c9af358e4b db/upnp/Discovery: move code to LockAdd(), LockRemove() 2014-01-23 22:35:22 +01:00
Max Kellermann 3afcfe3330 db/upnp/Discovery: un-inline the destructor 2014-01-23 22:35:22 +01:00
Max Kellermann f3f5e2e162 db/upnp: un-inline a few destructors
Reduce bloat.
2014-01-23 21:17:40 +01:00
Max Kellermann b52d8fbebe db/upnp: strict vpath checks for the "root" directory 2014-01-23 00:40:39 +01:00
Max Kellermann b61a2c722c db/upnp: move code to VisitObject() 2014-01-23 00:28:27 +01:00
Max Kellermann c455d2c1de db/upnp: merge two PathTraitsUTF8::Build() calls 2014-01-23 00:25:08 +01:00
Max Kellermann 77070f5ab9 db/upnp: move code to VisitItem() 2014-01-23 00:17:38 +01:00
Max Kellermann 8d5f7160ac db/upnp: fix subdirectory paths in "listallinfo"
Add missing server name prefix.
2014-01-23 00:07:35 +01:00
Max Kellermann b167ce2913 base_uri 2014-01-23 00:06:17 +01:00
Max Kellermann 3ac15ca8d1 db/upnp: pass char* to visitSong()
Don't use std::string, reduce bloat.
2014-01-23 00:06:03 +01:00
Max Kellermann f703d4fc3e db/upnp: call VisitDirectory on servers, even in recursive mode 2014-01-22 23:52:08 +01:00
Max Kellermann 77c461fed7 db/upnp: make several methods "const" 2014-01-22 23:50:33 +01:00
Max Kellermann a89c21b06a db/upnp: inline Configure() 2014-01-22 23:30:53 +01:00
Max Kellermann b74aa6b14c db/upnp: don't duplicate song data for VisitSong
Not necessary because we control the LightSong's life cycle.
2014-01-22 23:28:23 +01:00
Max Kellermann 0c4a791111 db/upnp: emplace/move in csvToStrings() 2014-01-22 23:21:23 +01:00
Max Kellermann 1feedd4d9c db/upnp: require an empty token list in csvToStrings() 2014-01-22 23:21:14 +01:00
Max Kellermann 0ec1808956 db/proxy: simplify csvToStrings() 2014-01-22 23:17:42 +01:00
Max Kellermann 546e7cafa4 db/proxy: merge redundant string::push_back() calls 2014-01-22 23:13:24 +01:00
Max Kellermann d9926a1c21 db/upnp: use PathTraitsUTF8::Build() 2014-01-22 23:10:00 +01:00
Max Kellermann e50969e31c db/proxy: fix for libmpdclient < 2.9 2014-01-22 23:09:36 +01:00
Max Kellermann a6d9998e1d db/proxy: copy "Last-Modified" from remote directories 2014-01-22 23:07:21 +01:00
Max Kellermann a42f9e4ee3 LightDirectory: new struct replacing Directory in the DB API 2014-01-22 23:01:32 +01:00
Max Kellermann 4943606f4a db/upnp: append characters instead of single-character strings 2014-01-22 21:55:58 +01:00
Max Kellermann 87629dda81 db/upnp: use string::push_back() instead of string::append() 2014-01-22 21:55:08 +01:00
Max Kellermann 71928b473e db/upnp/Discovery: unlock mutex before deleting DiscoveredTask 2014-01-22 21:48:33 +01:00
Max Kellermann a0bee9fa0a db/upnp/Discovery: eliminate two strlen() calls 2014-01-22 21:47:34 +01:00
Max Kellermann 0defd927f3 db/upnp: use std::list instead of std::set for SearchCapabilities
Reduce bloat.  We never used the set lookup.
2014-01-22 21:41:05 +01:00
Max Kellermann 6c41e8f63f db/upnp: check offset<total at end of loop 2014-01-22 21:37:21 +01:00
Max Kellermann fa67a4e956 db/upnp: break when zero objects have been returned 2014-01-22 21:37:19 +01:00
Max Kellermann bf9352fb26 db/upnp: free responses manually 2014-01-22 21:33:54 +01:00
Max Kellermann 7573d4e1ba db/upnp: break when count==0
Make this non-fatal.  Just stop reading more objects.
2014-01-22 21:33:19 +01:00
Max Kellermann bfb483898f db/upnp: use ParseUnsigned() instead of atoi() 2014-01-22 21:11:04 +01:00
Max Kellermann f363788d76 db/upnp: pass unsigned integers to readDirSlice() 2014-01-22 20:57:10 +01:00
Max Kellermann 714056f157 db/upnp: inline ContentDirectoryService::readDirSlice() 2014-01-22 20:42:36 +01:00
Max Kellermann 1abc96fa27 db/upnp: remove special case for "*"
Passing this to csvToStrings() will do the same.
2014-01-22 20:37:17 +01:00
Max Kellermann 0fa98479ad db/upnp: obtain char* from ixmlwrap::getFirstElementValue()
Fixes crash when there's no SearchCaps element.
2014-01-22 20:26:33 +01:00
Max Kellermann 02f2171010 db/upnp/Util: pass char* to csvToStrings() 2014-01-22 20:24:55 +01:00
Max Kellermann a5e7d0a90f db/upnp: require an empty input capability set 2014-01-22 20:21:01 +01:00
Max Kellermann 9fb5134f64 db/upnp/Util: handle absolute URI paths properly in caturl()
Fixes problems with some UPnP servers.
2014-01-22 19:38:07 +01:00
Max Kellermann 9aeb23dfe9 db/upnp/Util: use string::back(), string::front() 2014-01-22 19:38:02 +01:00
Max Kellermann e59d8c9378 db/upnp/Device: clear the "value" pointer on unknown element
Avoid appending to an obsolete string object.
2014-01-22 19:38:02 +01:00
Max Kellermann 9747cc9e58 db/upnp/Device: replace std::vector with a std::string pointer 2014-01-22 09:55:51 +01:00
Max Kellermann 7b44dea4b1 db/upnp/Device: remove unused UPnPService attributes 2014-01-22 09:51:26 +01:00
Max Kellermann 18aea922e9 db/upnp/Directory: "emplace" items into the vector 2014-01-22 09:43:49 +01:00
Max Kellermann 7d194aceb6 db/upnp/Device: emplace/move the UPnPService into the vector
Reduce overhead.
2014-01-22 09:42:46 +01:00
Max Kellermann 2722b8a3df db/upnp/Util: "emplace" items into the list
Reduce overhead.
2014-01-22 09:40:38 +01:00
Max Kellermann fd754ff8f8 db/upnp/Directory: replace std::vector with a simple enum
Reduce bloat.
2014-01-22 09:32:11 +01:00
Max Kellermann b7738e7af3 db/upnp/Directory: join all CDATA nodes for tag values
Expat can call CharacterData() multiple times if the CDATA contains
entity references.  We need to collect all of them in one large
string.
2014-01-22 08:44:35 +01:00
Max Kellermann 99bebabac9 db/upnp/Directory: make "m_dir" private 2014-01-22 08:44:20 +01:00
Max Kellermann 0ed48b364a db/upnp: merge duplicate branches in Namei() 2014-01-21 23:42:02 +01:00
Max Kellermann b38b8b9c18 db/upnp: simplify Namei() 2014-01-21 23:37:27 +01:00
Max Kellermann 5434856136 db/upnp: use std::list instead of std::vector
Reduce overhead.
2014-01-21 23:33:28 +01:00
Max Kellermann aa1eb2f40d db/upnp: use iterator in Namei() 2014-01-21 23:32:42 +01:00
Max Kellermann 7260d7883c db/upnp: move "objid" declaration down
Don't allocate the object when it's not needed.
2014-01-21 23:10:30 +01:00
Max Kellermann 154250f551 db/upnp: eliminate redundant Namei() parameter "oobjid"
The caller should better obtain the object id from the returned
UPnPDirObject instance.
2014-01-21 23:07:33 +01:00
Max Kellermann 3e4fb92cfb db/upnp: remove redundant objid.empty() check from VisitServer()
If Namei() succeeds, the object id is guaranteed to be set.
2014-01-21 23:07:06 +01:00
Max Kellermann 0da713e278 db/upnp: use std::move() to extract server name
Reduce runtime overhead.
2014-01-21 22:57:54 +01:00
Max Kellermann 94cb1545b3 db/upnp: use vector::front() instead of [0] 2014-01-21 22:57:16 +01:00
Max Kellermann 411527a240 db/upnp: don't use stringToTokens() in ParseDuration()
Reduce bloat.
2014-01-21 22:52:12 +01:00
Max Kellermann 7777057d35 db/upnp: don't construct redundant empty vector<string> in Visit()
We know already that vpath is empty, let's use this instance.
2014-01-21 22:47:57 +01:00
Max Kellermann dc5ef9ad01 db/upnp: simplify GetSong() 2014-01-21 22:43:04 +01:00
Max Kellermann 7471f65d95 LightSong: add attribute "real_uri"
The UPnP database plugin can now show relative song URIs for remote
songs.
2014-01-21 21:08:11 +01:00
Max Kellermann ecac7a629e db/upnp: fix empty song URI
Fall back to UPnPDirObject::url if there is no override.
2014-01-21 21:02:21 +01:00
Max Kellermann f5ae1ce00b LightSong: new class to be used by DatabasePlugin callbacks
Detach the Song class completely from the public API, only to be used
by SimpleDatabase and the update thread.
2014-01-19 17:04:51 +01:00
Max Kellermann 738d6f1040 db/proxy: simplify error handling in GetSong()
Check mpd_response_finish() before using mpd_song.  Don't skip this
check even if the mpd_song is non-nullptr.
2014-01-19 11:37:42 +01:00
Max Kellermann ba372197fb db/simple: make borrowed_song_count "mutable"
Simpler to use than const_cast.
2014-01-19 11:23:02 +01:00
Max Kellermann d2cf74027c Song: embed the Tag object statically into class Song
Reduces overhead because we need to manage only one memory allocation.
According to valgrind/massif, we save 7%.
2014-01-19 02:58:55 +01:00
Max Kellermann fdf4dff561 db/upnp: move Tag from UPnPDirObject to Song
The UPnPDirObject is a temporary object, we can move its contents.
This reduces runtime overhead.
2014-01-18 19:09:42 +01:00
Max Kellermann fab6cbed75 db/upnp/Discovery: eliminate attribute "last_seen" 2014-01-18 16:28:12 +01:00
Max Kellermann 051eede1ed db/upnp/Discovery: use monotonic clock instead of time() 2014-01-18 16:26:11 +01:00
Max Kellermann 0696cac50b db/upnp/Discovery: eliminate full copy in getServer() 2014-01-18 16:18:51 +01:00
Max Kellermann 0c2485e86c db/upnp: use getServer() in Visit()
Reduce bloat.
2014-01-18 16:13:33 +01:00
Max Kellermann 7d696a7063 db/upnp/Discovery: eliminate Error attribute
Move code to method Start() and add Error& parameters to several
methods.
2014-01-18 16:08:30 +01:00
Max Kellermann 53573e950f db/upnp: remove unnecessary m_superdir nullptr checks 2014-01-18 16:02:21 +01:00
Max Kellermann 1e99983263 db/upnp: pass ContentDirectoryService references 2014-01-18 15:58:02 +01:00
Max Kellermann 5409e43fb5 db/upnp: cache m_path.back() 2014-01-18 15:44:41 +01:00
Max Kellermann f33f891c54 db/upnp: add UpnpMakeAction() helper function 2014-01-18 15:27:54 +01:00
Max Kellermann 6e55552292 db/upnp/ixmlwrap: getFirstElementValue() returns const char *
Eliminate the std::string bloat.
2014-01-18 15:01:19 +01:00
Max Kellermann e569f82dd3 db/upnp: merge duplicate nullptr check 2014-01-18 14:44:06 +01:00
Max Kellermann 1a4940bbda db/upnp: free IXML_Document *request manually 2014-01-18 14:38:52 +01:00
Max Kellermann 22dd3c8048 db/upnp/Device: move code to method Parse()
Forward the Error to the caller.
2014-01-18 14:29:31 +01:00
Max Kellermann 04b7648e00 db/upnp/Device: use ContentDirectoryDescriptor's move operator
Reduce bloat.
2014-01-18 14:26:24 +01:00
Max Kellermann be0759d465 db/upnp/Discovery: don't copy XML to std::string
Pass "const char *" to Expat.
2014-01-18 14:24:38 +01:00
Max Kellermann 339d939873 db/upnp/Discovery: fix memory leak 2014-01-18 14:03:18 +01:00
Max Kellermann c1950e40e6 db/upnp: remove unused typedef DevServIt 2014-01-18 13:42:54 +01:00
Max Kellermann ad76bad8fd db/upnp: use move operator to assign XML CDATA
Reduce runtime bloat.
2014-01-18 13:39:31 +01:00
Max Kellermann 55737e4ff6 db/upnp/Util: trimstring() constructs string from buffer
Reduce overhead by omitting the part of the buffer that consists only
of whitespace.
2014-01-18 13:36:50 +01:00
Max Kellermann f3b4ddee6c db/upnp/Discovery: free the response body
Memory leak.
2014-01-18 13:08:48 +01:00
Max Kellermann 758b504cf3 db/upnp/Discovery: don't copy the response body
Bloat.
2014-01-18 13:07:42 +01:00
Max Kellermann 416f7c2600 db/upnp: don't hold mutex while downloading device description
Must not perform blocking I/O while holding a mutex.
2014-01-18 13:04:01 +01:00
Max Kellermann b9f02f22c4 db/upnp: don't use WorkQueue for _ADVERTISEMENT_BYEBYE
Remove the ContentDirectoryDescriptor right away.  Reduces bloat.
2014-01-18 12:56:35 +01:00
Max Kellermann b635610409 db/upnp: include cleanup 2014-01-18 12:51:25 +01:00
Max Kellermann d4d4d6217f db/upnp: don't use LazyDatabase
Now that MPD forks early, this workaround is obsolete.
2014-01-18 12:48:28 +01:00
Max Kellermann e2812f722d db/upnp/Discovery: move callbacks and data structures into class
Eliminate global variables.
2014-01-17 10:13:04 +01:00
Max Kellermann aa64a5328e db/upnp: split cluCallback() 2014-01-17 09:46:51 +01:00
Max Kellermann 59510f509a db/upnp: add local reference variables
Prepare to refactor some code.
2014-01-17 00:17:20 +01:00
Max Kellermann a35c7bc81a db/upnp: move the LibUPnP instance to class UpnpDatabase
Delete the object when closing the database.
2014-01-16 09:30:24 +01:00
Max Kellermann 02769929b3 db/upnp: remove useless static Mutex 2014-01-16 09:29:11 +01:00
Max Kellermann 1a09003a6e db/upnp: move the UPnPDeviceDirectory instance to class UpnpDatabase
Delete the object when closing the database.
2014-01-16 09:08:04 +01:00
Max Kellermann a827714823 db/upnp: don't initialize attributes to nullptr
Not necessary, these are not used.
2014-01-16 09:07:52 +01:00
Max Kellermann 8f9e76ca42 db/upnp: remove redundant m_root nullptr checks 2014-01-16 08:51:39 +01:00
Max Kellermann 478ace984a db/upnp/WorkQueue: use emplace() and std::move() 2014-01-16 08:46:41 +01:00
Max Kellermann 028fd268b8 db/upnp/WorkQueue: simplify start() 2014-01-16 08:43:57 +01:00
Max Kellermann 14c3ff58a4 db/upnp/WorkQueue: fix pthread_t[] allocation size
Was using the wrong variable.
2014-01-15 18:51:10 +01:00
Max Kellermann 2819b302c3 db/upnp/Object: remove obsolete attribute "m_title" 2014-01-15 18:36:01 +01:00
Max Kellermann 676d8bb624 db/upnp/Object: add attribute "tag"
Replaces "m_title" and "m_props".  More bloat removed.
2014-01-14 22:33:18 +01:00
Max Kellermann 4bcaf5d306 db/upnp: move upnp_tags to Tags.cxx 2014-01-14 22:33:18 +01:00
Max Kellermann 46debfb8b5 db/upnp/Object: disallow copying, always move
Reduce bloat.
2014-01-14 14:11:07 +01:00
Max Kellermann 9a4b572d34 db/upnp: getTagValue() returns string pointer
Reduce bloat.
2014-01-14 13:42:08 +01:00
Max Kellermann ddc75cc46b db/upnp/Directory: merge m_containers and m_items
There is no use in duplicating these containers.  It only means that
we have to search both, duplicating the code.
2014-01-14 13:37:21 +01:00
Max Kellermann dafd0bc49a db/upnp: pass const reference to getTagValue() 2014-01-14 13:37:05 +01:00
Max Kellermann 2cb912e4f4 db/upnp: Namei() returns error when no object was found
Don't fail silently.
2014-01-14 12:34:49 +01:00
Max Kellermann 91a513e87d db/upnp/Directory: eliminate one std::string copy with std::move() 2014-01-14 12:27:21 +01:00
Max Kellermann efdb41f2a6 db/upnp/Object: add attribute "name"
Call titleToPathElt() only once for each object.
2014-01-14 12:22:37 +01:00
Max Kellermann 26b850c15c db/upnp: use std::replace() in titleToPath() 2014-01-14 12:15:21 +01:00
Max Kellermann 9941735ae7 db/upnp: pass std::string to titleToPathElt() 2014-01-14 12:03:36 +01:00
Max Kellermann 29e5dc4413 db/upnp: don't sanitize the title tag
We need this only for path names.
2014-01-14 12:00:58 +01:00
Max Kellermann 3a660c5527 db/upnp/WorkQueue: remove unused attributes "high", "low" 2014-01-14 11:49:42 +01:00
Max Kellermann 738991494a db/upnp/WorkQueue: initialize "ok" to false, eliminate redundant checks 2014-01-14 11:48:19 +01:00
Max Kellermann ee4c3ff1b8 db/upnp/WorkQueue: remove IsOK() check from put()
Not necessary, not worth the check.
2014-01-14 11:46:18 +01:00
Max Kellermann 60486bcc46 db/upnp/WorkQueue: remove redundant n_workers_exited check from IsOK() 2014-01-14 11:43:18 +01:00
Max Kellermann 79eed5182e db/upnp/WorkQueue: include cleanup 2014-01-14 11:41:28 +01:00
Max Kellermann 5de0f3f36a db/upnp/WorkQueue: remove unnecessary "waiting" attributes 2014-01-14 11:38:48 +01:00
Max Kellermann 9f316e11bd db/upnp/WorkQueue: remove unused method waitIdle()
Contrary to setTerminateAndWait()'s documentation, the method does
wait for worker threads to exit via pthread_join().
2014-01-14 11:31:49 +01:00
Max Kellermann c6d8f6da70 db/upnp/WorkQueue: use array instead of std::list
Reduce bloat further.
2014-01-14 11:23:13 +01:00
Max Kellermann 73fd98b82e db/upnp/WorkQueue: use std::list instead of std::unordered_map
Reduce bloat.
2014-01-14 11:11:08 +01:00
Max Kellermann 6cb725391d db/upnp/WorkQueue: rename attributes 2014-01-14 11:07:06 +01:00
Max Kellermann c13facdaca db/upnp/WorkQueue: pass reference to take() 2014-01-14 11:07:00 +01:00
Max Kellermann e259474362 db/upnp/WorkQueue: remove unused method qsize() 2014-01-14 11:06:55 +01:00
Max Kellermann 7740855a78 db/upnp/WorkQueue: remove unused "szp" parameter from take() 2014-01-14 11:06:43 +01:00
Max Kellermann d605170f9f db/upnp/WorkQueue: remove unused statistics 2014-01-14 10:51:33 +01:00
Max Kellermann 4f83c60296 copyright year 2014 2014-01-13 22:31:55 +01:00
Max Kellermann a4d580a6f8 db/upnp: add fallback for emplace()
The method emplace() was added in gcc 4.8.  This commit restores
compatibility with gcc 4.7.
2014-01-13 22:24:48 +01:00
Max Kellermann ca43e634b5 db/upnp: use std::function for the libupnp callback
Replaces the bloated std::map.
2014-01-13 22:24:02 +01:00
Max Kellermann 85324f80fe db/upnp: fix "upnp:class" parser
"upnp:class" is an element, not an attribute of element "item".  This
fixes a regression from commit 65ebfb16
2014-01-13 22:23:00 +01:00
Max Kellermann 65ebfb16c9 db/upnp/Directory: parse item_class in StartElement
Don't add to the std::map.
2014-01-11 01:40:21 +01:00
Max Kellermann 44a65fc5de db/upnp/Object: add attribute "url"
Don't store in the std::map.
2014-01-11 01:36:08 +01:00
Max Kellermann f031eb1ef2 db/upnp/Directory: parse duration
Don't put all <res/> attributes to the attributes map; parse the
"duration" attribute as soon as we receive it, and store it in an
integer attribute.  This reduces bloat.
2014-01-11 01:31:13 +01:00
Max Kellermann b50d79542c db/upnp: move stringToTokens() to Util.cxx 2014-01-11 01:30:05 +01:00
Max Kellermann 8351543c0f db/upnp: move lazy Open() call to new class LazyDatabase
Generic approach for the workaround.
2014-01-11 01:25:22 +01:00
Max Kellermann 8add78ed5e db/upnp/discovery: convert std::strings to const char *
Reduce bloat.
2014-01-11 01:21:54 +01:00
Max Kellermann 4b3a3d6faa db/upnp: remove unnecessary Mutex 2014-01-11 01:16:35 +01:00
Max Kellermann 71d012fa61 db/proxy: forward "idle" events
Send "idle" to the other MPD whenever there's nothing else to do and
forward incoming "idle database" events to all our MPD clients.
2014-01-11 01:11:19 +01:00
Max Kellermann 114df1f137 DatabasePlugin: add interface DatabaseListener
Allow database plugins to announce that they have been modified.
2014-01-11 01:01:54 +01:00
Max Kellermann 00adf7ff17 db/proxy: move code to Disconnect() 2014-01-11 00:46:33 +01:00
Max Kellermann e9ba5fcaf3 db/upnp: remove unused method setMaxContentLength() 2014-01-10 23:04:50 +01:00
Max Kellermann 48097745f6 db/upnp: remove "upnplog" option
We have removed all libupnp logging calls, and we don't need to debug
libupnp.
2014-01-10 23:00:27 +01:00
Max Kellermann 1091ca969f db/upnp: remove unused macro PLOGINF() 2014-01-10 23:00:18 +01:00
Max Kellermann 09d62cc630 db/upnp: remove unused method errAsString() 2014-01-10 23:00:10 +01:00
Max Kellermann a2ead993e6 db/upnp/Device: remove unused attribute "m_tabs" 2014-01-10 23:00:03 +01:00
Max Kellermann b330aa8dd5 db/upnp: remove unnecessary empty string checks from CharacterData() 2014-01-10 22:59:46 +01:00
Max Kellermann 1b8053a618 db/upnp/Directory: simplify checkobjok() 2014-01-10 22:59:28 +01:00
Max Kellermann 70e5ab3fde db/upnp/Directory: don't log unknown items 2014-01-10 22:59:16 +01:00
Max Kellermann f4490f6918 db/upnp/Directory: eliminate the "attributes" std::map
Look up attributes in the "atts" array.  Reduce bloat.
2014-01-10 22:59:01 +01:00
Max Kellermann dadd987bf4 db/upnp/Directory: move "res" attributes to array
Reduce bloat.
2014-01-10 22:58:37 +01:00
Max Kellermann a1ced29279 db/upnp: use nullptr-terminated array
Reduce bloat.
2014-01-10 22:58:23 +01:00
Max Kellermann 791d6c1336 db/upnp/Directory: eliminate struct StackEl, use std::string
Reduces bloat.
2014-01-10 22:57:57 +01:00
Max Kellermann 10abb07960 db/upnp/Directory: make "attributes" a local variable
We only need it inside StartElement().  Reduces bloat.
2014-01-10 22:57:46 +01:00
Max Kellermann 040a5ddad5 db/upnp/Directory: move "res" tag handler to StartElement()
No need to handle this in EndElement() - in StartElement(), we already
have all we need.
2014-01-10 22:57:22 +01:00
Max Kellermann e7eb04954d db/upnp/Directory: don't use std::map to parse upnp:class
Reduce excessive bloat.
2014-01-10 22:57:16 +01:00
Max Kellermann 09b00fa4e3 db/upnp/Object: use strictly-typed enums
At the same time, rename the enum types and the class attributes, and
add an "UNKNOWN" type/class.  The latter avoids the "-1" hack.
2014-01-10 22:56:52 +01:00
Max Kellermann 74842fd6d4 db/upnp: getprop() returns const char *
Return the return value, instead returning it in a reference
parameter.  Reduces bloat by reducing unnecessary std::string usage.
2014-01-10 22:56:45 +01:00
Max Kellermann 15eedfbb12 db/upnp: don't set mtime, start_ms, end_ms
Not necessary or useful.
2014-01-10 09:01:28 +01:00
Max Kellermann cfc25e08dc db/upnp: use TagTable in upnpItemToSong()
Reduces bloat by eliminating one std::map.
2014-01-10 08:57:31 +01:00
Jean-Francois Dockes 406452f019 UPnP database plugin
[mk: renamed source files, applied coding style, reduced bloat, using
MPD's threading library, using MPD's error reporting and logging
library and refactoring, fixed lots of bugs]
2014-01-09 20:56:00 +01:00
Max Kellermann 0c34555b02 Directory: remove method Free() 2014-01-09 13:21:56 +01:00
Max Kellermann 83a988e2e4 db/proxy: allocate Directory instance on the stack 2014-01-09 13:21:09 +01:00
Max Kellermann 322b061632 DetachedSong: fork of struct Song
From now on, struct Song will be used by the database only, and
DetachedSong will be used by everybody else.  DetachedSong is easier
to use, but Song has lower overhead.
2014-01-09 09:05:58 +01:00
Max Kellermann ac1983eae3 tag/TagBuilder: rename Commit() to CommitNew() 2014-01-08 19:48:55 +01:00
Denis Krjuchkov acba9c0f61 TextFile: move to fs subsystem 2013-12-08 04:15:27 +06:00
Denis Krjuchkov c161bb287c db/SimpleDatabasePlugin.cxx: don't use CheckAccess with mode on Windows 2013-12-05 15:05:01 +06:00
Max Kellermann f90abe9530 include cleanup using iwyu 2013-11-28 11:50:54 +01:00
Max Kellermann d22acc59c9 db/proxy: implement method GetUpdateStamp() 2013-11-22 00:45:27 +01:00
Max Kellermann c064e8d62f DatabasePlugin: add method GetUpdateStamp()
Refactor SimpleDatabase::GetLastModified() to be generic for all
plugins.  Remove the SimpleDatabase assumption from db_stats_print(),
allowing it to be implemented by all database plugins.
2013-11-22 00:35:29 +01:00
Max Kellermann 8555b65c50 *: update copyright year to 2013 2013-10-30 23:37:06 +01:00
Max Kellermann 1dc8a9f0e7 db/proxy: remove obsolete #undefs 2013-10-30 20:51:41 +01:00
Max Kellermann a62d54425c db/proxy: auto-reconnect 2013-10-30 19:50:22 +01:00
Max Kellermann 7bb3987acc db/proxy: return server errors using "enum ack" 2013-10-30 16:04:21 +01:00
Max Kellermann 6a147a17af db/proxy: pass search/find to remote MPD 2013-10-30 10:00:57 +01:00
Max Kellermann 2b7529e905 db/proxy: pass SongFilter to the remote MPD in VisitUniqueTags() 2013-10-30 09:40:23 +01:00
Max Kellermann 1ed321f964 db/proxy: add missing nullptr check 2013-10-30 09:37:20 +01:00
Jean-Francois Dockes 205448c1e8 db/proxy: enable song matching 2013-10-29 20:58:35 +01:00
Max Kellermann 2d5413fc3b DatabaseSelection: use std::string 2013-10-29 20:36:52 +01:00
Max Kellermann 20597b3632 *: use nullptr instead of NULL 2013-10-28 23:58:17 +01:00
Max Kellermann a78b2d84ed TagType: rename enum tag_type to TagType 2013-10-20 13:32:59 +02:00
Max Kellermann ff626ac763 *: use references instead of pointers 2013-10-19 18:48:38 +02:00
Max Kellermann 59f8144c50 *: use nullptr instead of NULL 2013-10-19 18:19:03 +02:00
Max Kellermann abfbd55305 fs/Path: rename to AllocatedPath
The new class Path only holds a string pointer without being
responsible for allocation/deallocation.  The FileSystem.hxx library
accepts Path arguments instead of AllocatedPath, to avoid forcing
callers to allocate another string object.
2013-10-17 23:43:46 +02:00
Max Kellermann dbd88e6aef Client, ...: remove unnecessary glib.h include 2013-10-15 22:51:09 +02:00
Max Kellermann be2951b45f gcc.h: rename to Compiler.h 2013-10-15 09:21:59 +02:00
Max Kellermann 060814daa8 Log: new logging library API
Prepare to migrate away from GLib.  Currently, we're still using GLib
as a backend.
2013-10-02 08:57:55 +02:00
Max Kellermann 43675717b8 filesystem/Path: use std::string 2013-10-02 08:56:27 +02:00
Max Kellermann c2d3ed2acc Listen, ...: add missing includes 2013-10-02 08:56:27 +02:00
Max Kellermann 662bed6a00 db/proxy: use class TagBuilder 2013-09-05 19:07:27 +02:00
Max Kellermann 3f267b1795 Tag, ...: move to libtag.a 2013-09-05 18:26:56 +02:00
Max Kellermann 26d92c80ed conf.h: remove obsolete header
Use only ConfigData.hxx in plugin sources to reduce header
dependencies.
2013-09-05 08:47:10 +02:00
Max Kellermann 29030b54c9 util/Error: new error passing library
Replaces GLib's GError.
2013-09-04 18:14:22 +02:00
Max Kellermann 3deca8fccd db_error: convert to C++ 2013-08-10 19:43:27 +02:00
Max Kellermann b76a29a69a ConfigPath: return a Path object
Migrate all callers to use Path directly, instead of doing the
conversion in each caller.
2013-08-07 19:59:09 +02:00
Max Kellermann 85b77b81ca *: use gcc.h macros instead of GLib 2013-08-04 23:48:01 +02:00
Max Kellermann 65842cd99e DatabasePlugin: pass config_param reference 2013-08-04 14:07:50 +02:00
Max Kellermann 06f898cc12 tag: convert to C++ 2013-07-30 20:19:53 +02:00
Max Kellermann 6a9ab8bc0e tag: move enum tag_type to TagType.h 2013-07-30 20:10:24 +02:00
Max Kellermann ba161ec572 song: convert header to C++ 2013-07-28 13:25:12 +02:00
Denis Krjuchkov 3b620112ca SimpleDatabasePlugin: use file system API, log in UTF-8 2013-02-02 20:52:03 +06:00
Max Kellermann 541192c941 db/Proxy: explicitly request first element of array
Works around gcc 4.6 bug.
2013-01-28 21:32:14 +01:00
Denis Krjuchkov e98e2a0b07 Path::FromUTF8() returns nulled instance on error, add error handling where required 2013-01-28 00:13:46 +06:00
Denis Krjuchkov ef93cdf4a8 Path: move to fs subdirectory 2013-01-22 01:24:53 +06:00
Max Kellermann e5039c478a Path: new class "Path" wraps filesystem path strings 2013-01-18 15:34:01 +01:00
Max Kellermann 975370c084 decoder_api.h, ...: add "extern C" 2013-01-07 10:07:40 +01:00
Max Kellermann 90fe4c5124 TextFile: convert to a class 2013-01-03 10:16:05 +01:00
Max Kellermann 3e8047e583 Directory: rename struct directory to Directory 2013-01-03 01:10:47 +01:00
Max Kellermann 0eb05b827f Directory: turn functions to methods 2013-01-02 23:06:10 +01:00
Max Kellermann 0c245bc271 Directory: make the header C++ only 2013-01-02 22:52:08 +01:00
Max Kellermann 8331de424a PlaylistInfo: rename class, use std::string 2013-01-02 22:16:05 +01:00
Max Kellermann 51a2d09eb7 db_lock: convert to C++ 2013-01-02 20:56:21 +01:00
Max Kellermann 22f0ef6d6b don't include stdbool.h in C++ sources
The "bool" type is built-in.
2013-01-02 20:56:04 +01:00
Max Kellermann 0023dffd0b playlist_vector: convert to C++ 2013-01-02 20:25:20 +01:00
Max Kellermann b715e522cf db_save, state_file: convert to C++ 2013-01-02 20:22:59 +01:00
Max Kellermann 886255e38a db/SimpleDatabasePlugin: fix memory leak in Visit()
When visiting a song, GetSong() was called, but this object was never
returned by calling ReturnSong().  This patch locks the database only
once in Visit() and passes the original song object to the visitor,
avoiding the copy.
2012-09-05 20:56:20 +02:00
Max Kellermann 0240e75426 db_lock: add C++ helper class ScopeDatabaseLock 2012-09-05 20:52:02 +02:00
Max Kellermann 333d226ed0 SongFilter: convert to a C++ class 2012-08-29 20:19:02 +02:00
Max Kellermann 6ee76b7154 DatabaseSelection: add method Match() 2012-08-29 20:03:37 +02:00
Max Kellermann 36b1c08ad7 locate: rename to SongFilter.cxx 2012-08-29 19:12:26 +02:00
Max Kellermann 7968fa3779 ProxyDatabase: implement GetSong() 2012-08-16 00:29:25 +02:00
Max Kellermann 31009bb1f6 ProxyDatabase: clear libmpdclient errors in CheckError()
Auto-recover from soft errors.
2012-08-16 00:29:25 +02:00
Max Kellermann 3b8532f3fb DatabasePlugin: add method ReturnSong()
Allow the plugin to allocate the GetSong() return value.
2012-08-16 00:04:14 +02:00
Max Kellermann e391f4b17b ProxyDatabase: pass "detached" objects to visitors
Fixes wrong object URIs with duplicate base names.
2012-08-15 23:10:59 +02:00
Max Kellermann 3c0dea811d DatabasePlugin: add method GetStats()
Optimize the ProxyDatabase by invoking "stats" on the peer, instead of
visiting all songs.
2012-08-15 23:05:08 +02:00
Max Kellermann a6ac0f8965 DatabasePlugin: add method VisitUniqueTags()
Optimize the ProxyDatabase by invoking "list" on the peer, instead of
visiting all songs.
2012-08-15 23:02:27 +02:00
Max Kellermann 4e1eb03287 ProxyDatabase: obey visitor return values 2012-08-15 23:02:00 +02:00
Max Kellermann fcf0f8291d ProxyDatabasePlugin: add OO wrapper for mpd_entity
Let the C++ compiler take care for freeing the objects safely.
2012-08-15 23:01:08 +02:00
Max Kellermann 0ed71fa027 ProxyDatabasePlugin: move tag table to the global name space 2012-08-15 23:00:44 +02:00
Max Kellermann affe21f7c1 db_visitor: delete obsolete header 2012-08-15 22:57:20 +02:00
Max Kellermann 346e31efa0 ProxyDatabasePlugin: obey the "recursive" flag 2012-08-08 09:28:13 +02:00
Max Kellermann b504d63117 ProxyDatabasePlugin: use an artificial "root" directory
Fixes assertion failures in the Directory library.
2012-08-08 09:27:42 +02:00
Max Kellermann 63a2ac21e1 ProxyDatabasePlugin: new database plugin using libmpdclient
Implementation incomplete, but sort-of-works.  DumpDatabase works, but
MPD is still hard-coded on the "simple" plugin.
2012-08-08 01:20:45 +02:00
Max Kellermann 733d6a6b16 DatabaseSelection: add "match" attribute
Let the database plugin do the match.
2012-08-08 00:55:02 +02:00
Max Kellermann ff58207034 db_selection: rename to DatabaseSelection 2012-08-07 23:12:26 +02:00
Max Kellermann 1a75abffa5 Database{Plugin,Visitor}: pass references 2012-08-07 21:32:08 +02:00
Max Kellermann af1c497759 DatabasePlugin: make Visit() const 2012-08-02 19:12:27 +02:00
Max Kellermann 8e331cfc65 gcc.h: re-add gcc_const and gcc_pure
Remove GLib dependency from some headers.
2012-08-02 19:12:18 +02:00
Max Kellermann 9dc9459f3a db_plugin: convert to C++ 2012-08-01 09:59:12 +02:00
Max Kellermann 5dfc0918c3 require GLib 2.16
GLib 2.16 was released more than 4 years ago.  Let's remove some cruft
from the glib_compat.h header, and avoid new cruft to it.
2012-07-10 01:28:52 +02:00
Max Kellermann ef5cf40fa6 directory: require the caller to lock the db_mutex
Reduce the number of lock/unlock cycles, and make database handling
safer.
2012-02-02 18:06:33 +01:00
Max Kellermann d99f074eb7 directory: replace dirvec with doubly linked list
Random access is not needed, and a linked list is easier to manage: we
don't need to (re-)allocate the pointer array.
2012-01-24 20:49:53 +01:00
Max Kellermann 420a4c163d directory: simplify constructors and clarify API documentation
Pass only the "name" to a directory, instead of the full (relative)
path.
2012-01-24 20:03:18 +01:00
Max Kellermann d83dea4463 db/simple: pass the correct GError pointer 2012-01-12 18:59:26 +01:00
Max Kellermann a94d4be466 db_plugin: add method visit() 2011-09-13 21:47:00 +02:00
Max Kellermann 2fe1b5034d db_plugin: add method get_song()
New db_get_song() implementation.
2011-09-13 21:01:35 +02:00
Max Kellermann 7819aa6b20 db_plugin: introducing a plugin API for the song database
First draft, not really pluggable currently - hard-coded to use the
"simple" plugin, and calls several of its internal functions.

The API is very simple currently, all searches are still performed
over the root "directory" object.  Future changes to the API will move
those search implementations into the plugin, to allow more efficient
implementations, or implementations that don't have the whole tree in
memory all the time.
2011-09-10 07:58:43 +02:00