summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortsaarni <tsaarni>2007-07-06 17:41:30 +0000
committertsaarni <tsaarni>2007-07-06 17:41:30 +0000
commita3eb60a67ad2870ccd4779a6418430e8d8a645ac (patch)
tree4affe1be01129b53cdf99237f4481be43d7e5139
parent338ade43517233b02279f93fc1154b01ba80a86f (diff)
downloadlibmtp-a3eb60a67ad2870ccd4779a6418430e8d8a645ac.tar.gz
update cache when manipulating objects
-rw-r--r--AUTHORS1
-rw-r--r--ChangeLog5
-rw-r--r--TODO7
-rw-r--r--src/libmtp.c167
4 files changed, 155 insertions, 25 deletions
diff --git a/AUTHORS b/AUTHORS
index 593a551..5d52096 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -27,3 +27,4 @@ Robert Reardon <rreardon@monkshatch.vispa.com>
Orson Teodoro <orsonteodoro@yahoo.com>
Ted Bullock <tbullock@canada.com>
Sean Kellogg <skellogg@gmail.com>
+Tero Saarni <tero.saarni@gmail.com>
diff --git a/ChangeLog b/ChangeLog
index 236ee9b..5a2eb80 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2007-07-05 Tero Saarni <tero.saarni@gmail.com>
+
+ * src/libmtp.c: update cache when manipulating objects instead of
+ always flushing the whole cache.
+
2007-07-03 Linus Walleij <triad@df.lth.se>
* src/libmtp.c: use the params->proplist metadata cache. Help
diff --git a/TODO b/TODO
index 3013b34..5f779c2 100644
--- a/TODO
+++ b/TODO
@@ -11,10 +11,6 @@ SPEEDUP fixes:
with a list for each format of the properties it will support. Notice
that this needs to be updated whenever flush_handles() is called too.
-2. SPEED: Whenever we add an object (file, track, playlist...) we
- should only need to update the cache with relevant data. Atleast for
- speedup caches.
-
FEATURE fixes:
1. FEATURE: Make abstract playlists really become size -1 when created as
@@ -63,3 +59,6 @@ THOSE ARE ALREADY DONE:
3. SPEED: Cache track metadata, file metadata etc in params->proplist.
+4. SPEED: Whenever we add an object (file, track, playlist...) we
+ should only need to update the cache with relevant data. Atleast for
+ speedup caches.
diff --git a/src/libmtp.c b/src/libmtp.c
index 5a2ac04..70faa92 100644
--- a/src/libmtp.c
+++ b/src/libmtp.c
@@ -119,6 +119,8 @@ static int create_new_abstract_list(LIBMTP_mtpdevice_t *device,
static MTPPropList *new_mtp_prop_entry();
static MTPPropList *add_mtp_prop_to_proplist(MTPPropList *proplist, MTPPropList *prop);
static void destroy_mtp_prop_list(MTPPropList *proplist);
+static void add_object_to_cache(LIBMTP_mtpdevice_t *device, uint32_t handle);
+static void update_metadata_cache(LIBMTP_mtpdevice_t *device, uint32_t handle);
/**
* Create a new file mapping entry
@@ -3490,9 +3492,7 @@ int LIBMTP_Send_Track_From_File_Descriptor(LIBMTP_mtpdevice_t *device,
}
}
- // Added object so flush handles
- // FIXME: just realloc and att the item and objectinfo (see how libgphoto2 does it!)
- flush_handles(device);
+ add_object_to_cache(device, metadata->item_id);
return 0;
}
@@ -3816,9 +3816,8 @@ int LIBMTP_Send_File_From_File_Descriptor(LIBMTP_mtpdevice_t *device,
return -1;
}
- // Added object so flush handles.
- // FIXME: just realloc and att the item and objectinfo (see how libgphoto2 does it!)
- flush_handles(device);
+ add_object_to_cache(device, filedata->item_id);
+
return 0;
}
@@ -4292,10 +4291,9 @@ int LIBMTP_Update_Track_Metadata(LIBMTP_mtpdevice_t *device,
return -1;
}
- // FIXME: This is needed to keep the metadata cache intact.
- // add code to update the cache in params->proplist instead!
+ // update cached object properties if metadata cache exists
if (params->proplist != NULL) {
- flush_handles(device);
+ update_metadata_cache(device, metadata->item_id);
}
return 0;
@@ -4314,15 +4312,60 @@ int LIBMTP_Delete_Object(LIBMTP_mtpdevice_t *device,
{
uint16_t ret;
PTPParams *params = (PTPParams *) device->params;
+ int i;
ret = ptp_deleteobject(params, object_id, 0);
if (ret != PTP_RC_OK) {
add_ptp_error_to_errorstack(device, ret, "LIBMTP_Delete_Object(): could not delete object.");
return -1;
}
- // Removed object so flush handles.
- // FIXME: just realloc and att the item and objectinfo (see how libgphoto2 does it!)
- flush_handles(device);
+
+ // remove object from object info cache
+ for (i = 0; i < params->handles.n; i++) {
+ if (params->handles.Handler[i] == object_id) {
+ ptp_free_objectinfo(&params->objectinfo[i]);
+ memmove(params->handles.Handler+i, params->handles.Handler+i+1,
+ (params->handles.n-i-1)*sizeof(uint32_t));
+ memmove(params->objectinfo+i, params->objectinfo+i+1,
+ (params->handles.n-i-1)*sizeof(PTPObjectInfo));
+ params->handles.n--;
+ realloc(params->handles.Handler, sizeof(uint32_t)*params->handles.n);
+ realloc(params->objectinfo, sizeof(PTPObjectInfo)*params->handles.n);
+ }
+ }
+
+ // delete cached object properties if metadata cache exists
+ if (params->proplist) {
+ MTPPropList *prop = params->proplist;
+ MTPPropList *prev = NULL;
+ MTPPropList *last_deleted = NULL;
+ MTPPropList *deleted_props = NULL;
+
+ // find the place where properties for this object begin
+ while (prop != NULL && prop->ObjectHandle != object_id) {
+ prev = prop;
+ prop = prop->next;
+ }
+
+ // safeguard in case object is not found
+ if (!prop) return 0;
+
+ // head of properties for the deleted object
+ deleted_props = prop;
+
+ // find the end of properties for this object
+ while (prop != NULL && prop->ObjectHandle == object_id) {
+ last_deleted = prop;
+ prop = prop->next;
+ }
+
+ // the properties to be deleted are split into separate list
+ prev->next = prop;
+ last_deleted->next = NULL;
+
+ destroy_mtp_prop_list(deleted_props);
+ }
+
return 0;
}
@@ -4539,9 +4582,9 @@ uint32_t LIBMTP_Create_Folder(LIBMTP_mtpdevice_t *device, char *name, uint32_t p
}
// NOTE: don't destroy the new_folder objectinfo, because it is statically referencing
// several strings.
- // Created new object so flush handles
- // FIXME: just realloc and att the item and objectinfo (see how libgphoto2 does it!)
- flush_handles(device);
+
+ add_object_to_cache(device, new_id);
+
return new_id;
}
@@ -4949,9 +4992,7 @@ static int create_new_abstract_list(LIBMTP_mtpdevice_t *device,
}
}
- // Created new item, so flush handles
- // FIXME: just realloc and att the item and objectinfo (see how libgphoto2 does it!)
- flush_handles(device);
+ add_object_to_cache(device, *newid);
return 0;
}
@@ -5642,10 +5683,8 @@ int LIBMTP_Update_Album(LIBMTP_mtpdevice_t *device,
}
}
- // FIXME: This is needed to keep the metadata cache intact.
- // add code to update the cache in params->proplist instead!
if (params->proplist != NULL) {
- flush_handles(device);
+ update_metadata_cache(device, metadata->album_id);
}
return 0;
}
@@ -5657,3 +5696,89 @@ int LIBMTP_Update_Album(LIBMTP_mtpdevice_t *device,
void ptp_nikon_getptpipguid (unsigned char* guid) {
return;
}
+
+/**
+ * Update cache after new object is added to the device
+ */
+void add_object_to_cache(LIBMTP_mtpdevice_t *device, uint32_t handle)
+{
+ PTPParams *params = (PTPParams *)device->params;
+ MTPPropList *prop = NULL;
+ uint16_t ret;
+ int n;
+
+ n = ++params->handles.n;
+
+ params->objectinfo = (PTPObjectInfo*)realloc(params->objectinfo,
+ sizeof(PTPObjectInfo)*n);
+ params->handles.Handler = (uint32_t*)realloc(params->handles.Handler,
+ sizeof(uint32_t)*n);
+
+ memset(&params->objectinfo[n-1], 0, sizeof(PTPObjectInfo));
+ params->handles.Handler[n-1] = handle;
+
+ ptp_getobjectinfo(params, handle, &params->objectinfo[n-1]);
+
+ if (params->proplist) {
+
+ ret = ptp_mtp_getobjectproplist(params, handle, &prop);
+ if (ret != PTP_RC_OK) {
+ add_ptp_error_to_errorstack(device, ret, "add_object_to_cache(): call to ptp_mtp_getobjectproplist() failed.");
+ return;
+ }
+ add_mtp_prop_to_proplist(params->proplist, prop);
+ }
+}
+
+
+/**
+ * Update cache after object has been modified
+ */
+void update_metadata_cache(LIBMTP_mtpdevice_t *device, uint32_t handle)
+{
+ PTPParams *params = (PTPParams *)device->params;
+ MTPPropList *prop = params->proplist;
+ MTPPropList *prev = NULL;
+ MTPPropList *deleted_props = NULL;
+ MTPPropList *updated_props;
+ uint16_t ret;
+
+ // find the place where the properties for this object begin
+ while (prop != NULL && prop->ObjectHandle != handle) {
+ prev = prop;
+ prop = prop->next;
+ }
+
+ // safeguard in case object is not found
+ if (!prop) return;
+
+ // fetch updated properties and add them to the metadata cache in the same
+ // place where outdated properties were found
+ ret = ptp_mtp_getobjectproplist(params, handle, &updated_props);
+ if (ret != PTP_RC_OK) {
+ add_ptp_error_to_errorstack(device, ret, "update_metadata_cache(): call to ptp_mtp_getobjectproplist() failed.");
+ return;
+ }
+ prev->next = updated_props;
+
+ // head of outdated object properties that will be deleted
+ deleted_props = prop;
+
+ // find the end of properties for this object
+ while (prop != NULL && prop->ObjectHandle == handle) {
+ prev = prop;
+ prop = prop->next;
+ }
+
+ // find the end of the fetched properties and link rest of the list to it
+ while (updated_props->next != NULL) {
+ updated_props = updated_props->next;
+ }
+ updated_props->next = prop;
+
+ // split outdated properties into separate list and delete it
+ prev->next = NULL;
+ destroy_mtp_prop_list(deleted_props);
+
+ return;
+}