diff --git a/dom/system/gonk/cloudstorage/CloudStorage.cpp b/dom/system/gonk/cloudstorage/CloudStorage.cpp index d69e82c92dccd..357bd3425c226 100644 --- a/dom/system/gonk/cloudstorage/CloudStorage.cpp +++ b/dom/system/gonk/cloudstorage/CloudStorage.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include "CloudStorageLog.h" @@ -56,7 +57,8 @@ CloudStorage::CloudStorage(const nsCString& aCloudStorageName) mResponseData(), mNodeHashTable(), mPathHashTable(), - mAttrHashTable() + mAttrHashTable(), + mEntryListHashTable() { mMountPoint.Append("/data/cloud"); if ( -1 == mkdir(mMountPoint.get(), S_IRWXU|S_IRWXG)) { @@ -182,9 +184,40 @@ CloudStorage::GetAttrByPath(nsCString aPath) return res; } +FuseAttr +CloudStorage::CreateAttr(bool aIsDir, uint64_t aSize, uint64_t aMTime, uint64_t aCTime) +{ + FuseAttr attr; + if (aIsDir) { + attr.size = 4096; + attr.blocks = 8; + attr.blksize = 512; + attr.mode = 0x41ff; + } else { + attr.size = aSize; + attr.blocks = aSize/512; + attr.blksize = 512; + attr.mode = 0x81fd; + } + if (aMTime != 0 && aCTime != 0) { + attr.atime = aMTime/1000; + attr.mtime = aMTime/1000; + attr.ctime = aCTime/1000; + } else { + attr.atime = time(NULL); + attr.mtime = attr.atime; + attr.ctime = attr.ctime; + } + attr.uid = 0; + attr.gid = 1015; + + return attr; +} + void -CloudStorage::SetAttrByPath(nsCString aPath, FuseAttr attr) +CloudStorage::SetAttrByPath(nsCString aPath, bool aIsDir, uint64_t aSize, uint64_t aMTime, uint64_t aCTime) { + FuseAttr attr = CreateAttr(aIsDir, aSize, aMTime, aCTime); mAttrHashTable.Put(aPath, attr); } @@ -194,6 +227,58 @@ CloudStorage::RemoveAttrByPath(nsCString aPath) mAttrHashTable.Remove(aPath); } +void +CloudStorage::AddEntryByPath(nsCString aPath, nsCString aEntry) +{ + nsTArray entryList; + if (!mEntryListHashTable.Get(aPath, &entryList)) { + LOG("No entry list for path %s", aPath.get()); + } + nsTArray::size_type numEntries = entryList.Length(); + nsTArray::index_type entryIndex; + for (entryIndex = 0; entryIndex < numEntries; ++entryIndex) { + if (entryList[entryIndex].Equals(aEntry)) { + return; + } + } + entryList.AppendElement(aEntry); + mEntryListHashTable.Put(aPath, entryList); +} + +void +CloudStorage::RemoveEntryByPath(nsCString aPath, nsCString aEntry) +{ + nsTArray entryList; + if (!mEntryListHashTable.Get(aPath, &entryList)) { + LOG("No entry list for path %s", aPath.get()); + return; + } + nsTArray::size_type numEntries = entryList.Length(); + nsTArray::index_type entryIndex; + for (entryIndex = 0; entryIndex < numEntries; ++entryIndex) { + if (entryList[entryIndex].Equals(aEntry)) { + entryList.RemoveElementAt(entryIndex); + } + } + if (entryList.Length() != 0) { + mEntryListHashTable.Put(aPath, entryList); + } else { + mEntryListHashTable.Remove(aPath); + } +} + +nsCString +CloudStorage::GetEntryByPathAndOffset(nsCString aPath, uint64_t aOffset) +{ + nsTArray entryList; + if (mEntryListHashTable.Get(aPath, &entryList)) { + if (aOffset >= entryList.Length()) { + return NS_LITERAL_CSTRING(""); + } + return entryList[aOffset]; + } + return NS_LITERAL_CSTRING(""); +} } // end namespace cloudstorage } // end namespace system diff --git a/dom/system/gonk/cloudstorage/CloudStorage.h b/dom/system/gonk/cloudstorage/CloudStorage.h index 6516b72b7111e..63040a7197201 100644 --- a/dom/system/gonk/cloudstorage/CloudStorage.h +++ b/dom/system/gonk/cloudstorage/CloudStorage.h @@ -10,6 +10,7 @@ #include "nsCOMPtr.h" #include "nsRefPtr.h" #include "nsDataHashtable.h" +#include "nsTArray.h" #include "fuse.h" namespace mozilla { @@ -105,13 +106,20 @@ class CloudStorage final void RemoveNIdByPath(nsCString aKey); FuseAttr GetAttrByPath(nsCString aPath); - void SetAttrByPath(nsCString aPath, FuseAttr aAttr); + void SetAttrByPath(nsCString aPath, bool aIsDir, uint64_t aSize, uint64_t aMTime, uint64_t aCTime); void RemoveAttrByPath(nsCString aPath); + nsCString GetEntryByPathAndOffset(nsCString aPath, uint64_t aOffset); + void AddEntryByPath(nsCString aPath, nsCString aEntry); + void RemoveEntryByPath(nsCString aPath, nsCString aEntry); + void StartStorage(); void StopStorage(); private: + + FuseAttr CreateAttr(bool aIsDir, uint64_t aSize, uint64_t aMTime, uint64_t aCTime); + nsCString mCloudStorageName; nsCString mMountPoint; eState mState; @@ -122,6 +130,7 @@ class CloudStorage final nsDataHashtable mNodeHashTable; nsDataHashtable mPathHashTable; nsDataHashtable mAttrHashTable; + nsDataHashtable > mEntryListHashTable; }; } // end namespace cloudstorage diff --git a/dom/system/gonk/cloudstorage/CloudStorageRequestHandler.cpp b/dom/system/gonk/cloudstorage/CloudStorageRequestHandler.cpp index 99300a8f76dc3..cb50a64576336 100644 --- a/dom/system/gonk/cloudstorage/CloudStorageRequestHandler.cpp +++ b/dom/system/gonk/cloudstorage/CloudStorageRequestHandler.cpp @@ -52,12 +52,33 @@ class CloudStorageRequestRunnable : public nsRunnable LOG("fail to get csi [%x]", rv); } if (csi) { - LOG("cloud name: %s", mCloudStorage->Name().get()); - LOG("path: %s", mCloudStorage->RequestData().Path.get()); - LOG("call GetFileMeta"); - rv = csi->GetFileMeta(mCloudStorage->Name(), mCloudStorage->RequestData().Path); - if (NS_FAILED(rv)) { - LOG("fail to call cloudstorageinterface->GetFileMeta(%s) [%x]", mCloudStorage->RequestData().Path.get(), rv); + switch (mCloudStorage->RequestData().RequestType) { + case FUSE_GETATTR: { + LOG("cloud name: %s", mCloudStorage->Name().get()); + LOG("path: %s", mCloudStorage->RequestData().Path.get()); + LOG("call GetFileMeta"); + rv = csi->GetFileMeta(mCloudStorage->Name(), mCloudStorage->RequestData().Path); + if (NS_FAILED(rv)) { + LOG("fail to call cloudstorageinterface->GetFileMeta(%s) [%x]", mCloudStorage->RequestData().Path.get(), rv); + } + break; + } + case FUSE_READDIR: { + LOG("cloud name: %s", mCloudStorage->Name().get()); + LOG("path: %s", mCloudStorage->RequestData().Path.get()); + LOG("call GetFileList"); + rv = csi->GetFileList(mCloudStorage->Name(), mCloudStorage->RequestData().Path); + if (NS_FAILED(rv)) { + LOG("fail to call cloudstorageinterface->GetFileMeta(%s) [%x]", mCloudStorage->RequestData().Path.get(), rv); + } + break; + } + default: { + LOG("Unknown request type [%u]", mCloudStorage->RequestData().RequestType); + if (mCloudStorage->IsWaitForRequest()) { + mCloudStorage->SetWaitForRequest(false); + } + } } } else { LOG("fail to get cloudstorageinterface"); @@ -422,11 +443,6 @@ CloudStorageRequestHandler::HandleGetAttr(const FuseInHeader *hdr, const FuseGet LOG("path: %s", path.get()); FuseAttrOut attrOut; - -/* - CloudStorageTester tester; - tester.GetAttrByPath(path, hdr->nodeid); -*/ attrOut.attr.ino = hdr->nodeid; attrOut.attr = mCloudStorage->GetAttrByPath(path); LOG("attr.size: %llu", attrOut.attr.size); @@ -672,22 +688,39 @@ CloudStorageRequestHandler::HandleReadDir(const FuseInHeader* hdr, const FuseRea if (path.Equals(NS_LITERAL_CSTRING(""))) { return -ENOENT; } - LOG("path: %s", path.get()); + LOG("path: %s, offset: %llu", path.get(), req->offset); char buffer[8192]; FuseDirent *fde = (FuseDirent*) buffer; fde->ino = FUSE_UNKNOWN_INO; fde->off = req->offset + 1; nsCString entryName; - uint32_t entryType; - CloudStorageTester tester; - tester.GetEntry(path, req->offset, entryName, entryType); - LOG("entry name: %s, entry type: %s", entryName.get(), (entryType == DT_REG)?"file":"directory"); + + entryName = mCloudStorage->GetEntryByPathAndOffset(path, req->offset); + if (entryName.Equals(NS_LITERAL_CSTRING(""))) { + CloudStorageRequestData reqData; + reqData.RequestType = (uint32_t) FUSE_READDIR; + reqData.Path = path; + mCloudStorage->SetRequestData(reqData); + SendRequestToMainThread(); + entryName = mCloudStorage->GetEntryByPathAndOffset(path, req->offset); + } if (mCloudStorage->State() == CloudStorage::STATE_RUNNING) { if (entryName.Equals("")) { + LOG("No entry"); return 0; } - fde->type = entryType; + nsCString childPath = path; + if (!path.Equals(NS_LITERAL_CSTRING("/"))) { + childPath.Append(NS_LITERAL_CSTRING("/")); + } + childPath.Append(entryName); + + if (S_ISDIR(mCloudStorage->GetAttrByPath(childPath).mode)) { + fde->type = DT_DIR; + } else { + fde->type = DT_REG; + } fde->namelen = entryName.Length(); memcpy(fde->name, entryName.get(), fde->namelen + 1); diff --git a/dom/system/gonk/cloudstorage/nsCloudStorageGeckoInterface.cpp b/dom/system/gonk/cloudstorage/nsCloudStorageGeckoInterface.cpp index b02c68cadb39b..784dc12fa0e5e 100644 --- a/dom/system/gonk/cloudstorage/nsCloudStorageGeckoInterface.cpp +++ b/dom/system/gonk/cloudstorage/nsCloudStorageGeckoInterface.cpp @@ -28,6 +28,15 @@ nsCloudStorageGeckoInterface::Init() return NS_OK; } +NS_IMETHODIMP +nsCloudStorageGeckoInterface::FinishRequest(const nsACString_internal& aCloudName) +{ + nsCString cloudName(aCloudName); + RefPtr cloudStorage = CloudStorageManager::FindCloudStorageByName(cloudName); + cloudStorage->SetWaitForRequest(false); + return NS_OK; +} + NS_IMETHODIMP nsCloudStorageGeckoInterface::SetFileMeta(const nsACString_internal& aCloudName, const nsACString_internal& aPath, @@ -39,35 +48,31 @@ nsCloudStorageGeckoInterface::SetFileMeta(const nsACString_internal& aCloudName, nsCString cloudName(aCloudName); nsCString path(aPath); RefPtr cloudStorage = CloudStorageManager::FindCloudStorageByName(cloudName); - LOG("in CloudStorageGeckoInterface::SetFileMeta"); - LOG("file type: %s, size: %llu, modified time: %llu, created time: %llu", aIsDir?"Directory":"File", aSize, aMTime, aCTime); + cloudStorage->SetAttrByPath(path, aIsDir, aSize, aMTime, aCTime); + return NS_OK; +} - FuseAttr attr; - if (aIsDir) { - attr.size = 4096; - attr.blocks = 8; - attr.blksize = 512; - attr.mode = 0x41ff; - } else { - attr.size = aSize; - attr.blocks = aSize/512; - attr.blksize = 512; - attr.mode = 0x81fd; - } - if (aMTime != 0 && aCTime != 0) { - attr.atime = aMTime/1000; - attr.mtime = aMTime/1000; - attr.ctime = aCTime/1000; +NS_IMETHODIMP +nsCloudStorageGeckoInterface::SetFileList(const nsACString_internal& aCloudName, + const nsACString_internal& aPath, + const nsACString_internal& aChildPath, + bool aIsDir, + uint64_t aSize, + uint64_t aMTime, + uint64_t aCTime) +{ + nsCString cloudName(aCloudName); + nsCString path(aPath); + nsCString childPath(aChildPath); + RefPtr cloudStorage = CloudStorageManager::FindCloudStorageByName(cloudName); + nsCString entry; + if (path.Equals(NS_LITERAL_CSTRING("/"))) { + childPath.Right(entry, childPath.Length()-path.Length()); } else { - attr.atime = time(NULL); - attr.mtime = attr.atime; - attr.ctime = attr.ctime; + childPath.Right(entry, childPath.Length()-path.Length()-1); } - attr.uid = 0; - attr.gid = 1015; - - cloudStorage->SetAttrByPath(path, attr); - cloudStorage->SetWaitForRequest(false); + cloudStorage->SetAttrByPath(childPath, aIsDir, aSize, aMTime, aCTime); + cloudStorage->AddEntryByPath(path, entry); return NS_OK; } diff --git a/dom/system/gonk/cloudstorage/nsCloudStorageInterface.js b/dom/system/gonk/cloudstorage/nsCloudStorageInterface.js index 72ad6030159eb..00a8cc2942420 100644 --- a/dom/system/gonk/cloudstorage/nsCloudStorageInterface.js +++ b/dom/system/gonk/cloudstorage/nsCloudStorageInterface.js @@ -53,6 +53,23 @@ nsCloudStorageInterface.prototype = { cls = Components.classes["@mozilla.org/cloudstoragegeckointerface;1"]; instance = cls.createInstance(Components.interfaces.nsICloudStorageGeckoInterface); instance.setFileMeta(cloudname, path, response.data.list[0].isdir, response.data.list[0].size, response.data.list[0].mtime, response.data.list[0].ctime); + instance.finishRequest(cloudname); + }); + }, + + getFileList: function(cloudname, path) { + log("cloudname: " + cloudname + " " + "path: " + path); + log("call udManager.getFileList"); + udManager.getFileList(path, function (error, response) { + log(JSON.stringify(response.data)); + var cls, instance; + cls = Components.classes["@mozilla.org/cloudstoragegeckointerface;1"]; + instance = cls.createInstance(Components.interfaces.nsICloudStorageGeckoInterface); + for (var pathIdx = 0; pathIdx < response.data.list.length; pathIdx++ ) { + var fileData = response.data.list[pathIdx]; + instance.setFileList(cloudname, path, fileData.path, fileData.isdir, fileData.size, fileData.mtime, fileData.ctime); + } + instance.finishRequest(cloudname); }); } }; diff --git a/dom/system/gonk/cloudstorage/nsICloudStorageGeckoInterface.idl b/dom/system/gonk/cloudstorage/nsICloudStorageGeckoInterface.idl index 7894ca918bd02..64b56dbcf60eb 100644 --- a/dom/system/gonk/cloudstorage/nsICloudStorageGeckoInterface.idl +++ b/dom/system/gonk/cloudstorage/nsICloudStorageGeckoInterface.idl @@ -13,5 +13,16 @@ interface nsICloudStorageGeckoInterface : nsISupports in unsigned long long size, in unsigned long long mtime, in unsigned long long ctime); + + void setFileList(in AUTF8String cloudname, + in AUTF8String path, + in AUTF8String childpath, + in boolean isdir, + in unsigned long long size, + in unsigned long long mtime, + in unsigned long long ctime); + + void finishRequest(in AUTF8String cloudname); + }; diff --git a/dom/system/gonk/cloudstorage/nsICloudStorageInterface.idl b/dom/system/gonk/cloudstorage/nsICloudStorageInterface.idl index e7ee924a3efb7..da3c4316b096a 100644 --- a/dom/system/gonk/cloudstorage/nsICloudStorageInterface.idl +++ b/dom/system/gonk/cloudstorage/nsICloudStorageInterface.idl @@ -9,5 +9,8 @@ interface nsICloudStorageInterface : nsISupports { void getFileMeta(in AUTF8String cloudname, in AUTF8String path); + + void getFileList(in AUTF8String cloudname, + in AUTF8String path); };