| 1162 | } |
| 1163 | |
| 1164 | Status GcsFileSystem::UncachedStatForObject(const string& fname, |
| 1165 | const string& bucket, |
| 1166 | const string& object, |
| 1167 | GcsFileStat* stat) { |
| 1168 | std::vector<char> output_buffer; |
| 1169 | std::unique_ptr<HttpRequest> request; |
| 1170 | TF_RETURN_WITH_CONTEXT_IF_ERROR(CreateHttpRequest(&request), |
| 1171 | " when reading metadata of gs://", bucket, |
| 1172 | "/", object); |
| 1173 | |
| 1174 | request->SetUri(strings::StrCat(kGcsUriBase, "b/", bucket, "/o/", |
| 1175 | request->EscapeString(object), |
| 1176 | "?fields=size%2Cgeneration%2Cupdated")); |
| 1177 | request->SetResultBuffer(&output_buffer); |
| 1178 | request->SetTimeouts(timeouts_.connect, timeouts_.idle, timeouts_.metadata); |
| 1179 | |
| 1180 | if (stats_ != nullptr) { |
| 1181 | stats_->RecordStatObjectRequest(); |
| 1182 | } |
| 1183 | |
| 1184 | TF_RETURN_WITH_CONTEXT_IF_ERROR( |
| 1185 | request->Send(), " when reading metadata of gs://", bucket, "/", object); |
| 1186 | |
| 1187 | Json::Value root; |
| 1188 | TF_RETURN_IF_ERROR(ParseJson(output_buffer, &root)); |
| 1189 | |
| 1190 | // Parse file size. |
| 1191 | TF_RETURN_IF_ERROR(GetInt64Value(root, "size", &stat->base.length)); |
| 1192 | |
| 1193 | // Parse generation number. |
| 1194 | TF_RETURN_IF_ERROR( |
| 1195 | GetInt64Value(root, "generation", &stat->generation_number)); |
| 1196 | |
| 1197 | // Parse file modification time. |
| 1198 | string updated; |
| 1199 | TF_RETURN_IF_ERROR(GetStringValue(root, "updated", &updated)); |
| 1200 | TF_RETURN_IF_ERROR(ParseRfc3339Time(updated, &(stat->base.mtime_nsec))); |
| 1201 | |
| 1202 | VLOG(1) << "Stat of: gs://" << bucket << "/" << object << " -- " |
| 1203 | << " length: " << stat->base.length |
| 1204 | << " generation: " << stat->generation_number |
| 1205 | << "; mtime_nsec: " << stat->base.mtime_nsec |
| 1206 | << "; updated: " << updated; |
| 1207 | |
| 1208 | if (str_util::EndsWith(fname, "/")) { |
| 1209 | // In GCS a path can be both a directory and a file, both it is uncommon for |
| 1210 | // other file systems. To avoid the ambiguity, if a path ends with "/" in |
| 1211 | // GCS, we always regard it as a directory mark or a virtual directory. |
| 1212 | stat->base.is_directory = true; |
| 1213 | } else { |
| 1214 | stat->base.is_directory = false; |
| 1215 | } |
| 1216 | return Status::OK(); |
| 1217 | } |
| 1218 | |
| 1219 | Status GcsFileSystem::StatForObject(const string& fname, const string& bucket, |
| 1220 | const string& object, GcsFileStat* stat) { |
nothing calls this directly
no test coverage detected