Lines Matching refs:fs
14 #include "istream-fs-stats.h"
15 #include "fs-api-private.h"
20 static ARRAY(const struct fs *) fs_classes;
25 fs_alloc(const struct fs *fs_class, const char *args,
26 const struct fs_settings *set, struct fs **fs_r, const char **error_r)
28 struct fs *fs;
31 fs = fs_class->v.alloc();
32 fs->refcount = 1;
33 fs->last_error = str_new(default_pool, 64);
34 fs->set.debug = set->debug;
35 fs->set.enable_timing = set->enable_timing;
36 i_array_init(&fs->module_contexts, 5);
39 ret = fs_class->v.init(fs, args, set);
46 fs_last_error(fs));
47 fs_unref(&fs);
50 fs->username = i_strdup(set->username);
51 fs->session_id = i_strdup(set->session_id);
52 *fs_r = fs;
56 void fs_class_register(const struct fs *fs_class)
81 static const struct fs *fs_class_find(const char *driver)
83 const struct fs *const *classp;
111 const struct fs *fs_class;
131 static struct event *fs_create_event(struct fs *fs, struct event *parent)
137 t_strdup_printf("fs-%s: ", fs->name));
143 struct fs **fs_r, const char **error_r)
145 const struct fs *fs_class;
156 *error_r = t_strdup_printf("Unknown fs driver: %s", driver);
175 struct fs **fs_r, const char **error_r)
185 void fs_deinit(struct fs **fs)
187 fs_unref(fs);
190 void fs_ref(struct fs *fs)
192 i_assert(fs->refcount > 0);
194 fs->refcount++;
197 void fs_unref(struct fs **_fs)
199 struct fs *fs = *_fs;
200 string_t *last_error = fs->last_error;
201 struct array module_contexts_arr = fs->module_contexts.arr;
204 i_assert(fs->refcount > 0);
208 if (--fs->refcount > 0)
211 if (fs->files_open_count > 0) {
212 i_panic("fs-%s: %u files still open (first = %s)",
213 fs->name, fs->files_open_count, fs_file_path(fs->files));
215 i_assert(fs->files == NULL);
217 event_unref(&fs->event);
218 i_free(fs->username);
219 i_free(fs->session_id);
220 i_free(fs->temp_path_prefix);
222 if (fs->stats.timings[i] != NULL)
223 stats_dist_deinit(&fs->stats.timings[i]);
226 fs->v.deinit(fs);
232 struct fs *fs_get_parent(struct fs *fs)
234 return fs->parent;
237 const char *fs_get_driver(struct fs *fs)
239 return fs->name;
242 const char *fs_get_root_driver(struct fs *fs)
244 while (fs->parent != NULL)
245 fs = fs->parent;
246 return fs->name;
249 struct fs_file *fs_file_init(struct fs *fs, const char *path, int mode_flags)
251 return fs_file_init_with_event(fs, fs->event, path, mode_flags);
254 struct fs_file *fs_file_init_with_event(struct fs *fs, struct event *event,
264 file = fs->v.file_alloc();
265 file->fs = fs;
267 file->event = fs_create_event(fs, event);
268 fs->v.file_init(file, path, mode_flags & FS_OPEN_MODE_MASK,
272 fs->files_open_count++;
273 DLLIST_PREPEND(&fs->files, file);
285 i_assert(file->fs->files_open_count > 0);
291 DLLIST_REMOVE(&file->fs->files, file);
292 file->fs->files_open_count--;
294 file->fs->v.file_deinit(file);
318 if (file->fs->v.file_close != NULL) T_BEGIN {
319 file->fs->v.file_close(file);
322 /* check this only after closing, because some of the fs backends keep
328 enum fs_properties fs_get_properties(struct fs *fs)
330 return fs->v.get_properties(fs);
337 file->metadata_pool = pool_alloconly_create("fs metadata", 1024);
405 if (file->fs->v.set_metadata != NULL) T_BEGIN {
406 file->fs->v.set_metadata(file, key, value);
418 if (!file->fs->set.enable_timing)
445 if (!file->fs->set.enable_timing || file->timing_start[op].tv_sec == 0)
448 fs_timing_end(&file->fs->stats.timings[op], &file->timing_start[op]);
458 if (file->fs->v.get_metadata == NULL) {
459 fs_set_error(file->fs, "Metadata not supported by backend");
465 file->fs->stats.lookup_metadata_count++;
469 ret = file->fs->v.get_metadata(file, metadata_r);
489 return file->fs->v.get_path == NULL ? file->path :
490 file->fs->v.get_path(file);
493 struct fs *fs_file_fs(struct fs_file *file)
495 return file->fs;
504 fs_set_verror(struct fs *fs, const char *fmt, va_list args)
506 /* the error is always kept in the parentmost fs */
507 if (fs->parent != NULL)
508 fs_set_verror(fs->parent, fmt, args);
510 str_truncate(fs->last_error, 0);
511 str_vprintfa(fs->last_error, fmt, args);
515 const char *fs_last_error(struct fs *fs)
517 /* the error is always kept in the parentmost fs */
518 if (fs->parent != NULL)
519 return fs_last_error(fs->parent);
521 if (str_len(fs->last_error) == 0)
522 return "BUG: Unknown fs error";
523 return str_c(fs->last_error);
528 return fs_last_error(file->fs);
537 file->fs->stats.prefetch_count++;
541 ret = file->fs->v.prefetch(file, length);
560 fs_set_error_async(file->fs);
564 fs_set_error(file->fs, "read(%s) failed: %s",
581 file->fs->stats.read_count++;
585 if (file->fs->v.read != NULL) {
587 ret = file->fs->v.read(file, buf, size);
616 file->fs->stats.read_count++;
628 input = file->fs->v.read_stream(file, max_buffer_size);
635 if (file->fs->set.enable_timing) {
652 file->fs->temp_path_prefix);
664 fs_wait_async(file->fs);
695 fs_set_error_async(file->fs);
707 if (file->fs->v.write != NULL) {
710 ret = file->fs->v.write(file, data, size);
713 file->fs->stats.write_count++;
714 file->fs->stats.write_bytes += size;
731 file->fs->stats.write_count++;
733 file->fs->v.write_stream(file);
748 ret = file->fs->v.write_stream_finish(file, success);
778 fs_set_error(file->fs, "write(%s) failed: %s",
783 file->fs->stats.write_bytes += file->output->offset;
812 fs_set_verror(file->fs, error_fmt, args);
838 if (file->fs->v.set_async_callback != NULL)
839 file->fs->v.set_async_callback(file, callback, context);
844 void fs_wait_async(struct fs *fs)
847 i_assert(fs->prev_ioloop == NULL);
849 if (fs->v.wait_async != NULL) T_BEGIN {
850 fs->prev_ioloop = current_ioloop;
851 fs->v.wait_async(fs);
852 i_assert(current_ioloop == fs->prev_ioloop);
853 fs->prev_ioloop = NULL;
857 bool fs_switch_ioloop(struct fs *fs)
861 if (fs->v.switch_ioloop != NULL) {
863 ret = fs->v.switch_ioloop(fs);
865 } else if (fs->parent != NULL) {
866 ret = fs_switch_ioloop(fs->parent);
876 ret = file->fs->v.lock(file, secs, lock_r);
887 lock->file->fs->v.unlock(lock);
896 if (file->fs->v.exists == NULL) {
905 ret = file->fs->v.exists(file);
908 file->fs->stats.exists_count++;
918 if (file->fs->v.stat == NULL) {
919 fs_set_error(file->fs, "fs_stat() not supported");
926 file->fs->stats.stat_count++;
930 ret = file->fs->v.stat(file, st_r);
941 if (file->fs->v.get_nlinks == NULL) {
953 file->fs->stats.stat_count++;
957 ret = file->fs->v.get_nlinks(file, nlinks_r);
969 dest->fs->stats.copy_count--;
990 fs_set_error_async(dest->fs);
1022 i_assert(src->fs == dest->fs);
1024 if (src->fs->v.copy == NULL) {
1025 fs_set_error(src->fs, "fs_copy() not supported");
1031 ret = src->fs->v.copy(src, dest);
1035 dest->fs->stats.copy_count++;
1046 ret = dest->fs->v.copy(NULL, dest);
1050 dest->fs->stats.copy_count++;
1060 i_assert(src->fs == dest->fs);
1064 ret = src->fs->v.rename(src, dest);
1067 dest->fs->stats.rename_count++;
1081 ret = file->fs->v.delete_file(file);
1084 file->fs->stats.delete_count++;
1091 fs_iter_init(struct fs *fs, const char *path, enum fs_iter_flags flags)
1093 return fs_iter_init_with_event(fs, fs->event, path, flags);
1097 fs_iter_init_with_event(struct fs *fs, struct event *event,
1104 (fs_get_properties(fs) & FS_PROPERTY_OBJECTIDS) != 0);
1106 fs->stats.iter_count++;
1107 if (fs->set.enable_timing) {
1111 if (fs->v.iter_init == NULL) {
1113 iter->fs = fs;
1115 iter = fs->v.iter_alloc();
1116 iter->fs = fs;
1118 iter->event = fs_create_event(fs, event);
1119 fs->v.iter_init(iter, path, flags);
1122 DLLIST_PREPEND(&fs->iters, iter);
1133 DLLIST_REMOVE(&iter->fs->iters, iter);
1135 if (iter->fs->v.iter_deinit == NULL) {
1136 fs_set_error(iter->fs, "FS iteration not supported");
1140 ret = iter->fs->v.iter_deinit(iter);
1150 if (iter->fs->v.iter_next == NULL)
1153 ret = iter->fs->v.iter_next(iter);
1160 fs_timing_end(&iter->fs->stats.timings[FS_OP_ITER], &iter->start_time);
1180 const struct fs_stats *fs_get_stats(struct fs *fs)
1182 return &fs->stats;
1185 void fs_set_error(struct fs *fs, const char *fmt, ...)
1190 fs_set_verror(fs, fmt, args);
1194 void fs_set_critical(struct fs *fs, const char *fmt, ...)
1199 fs_set_verror(fs, fmt, args);
1201 e_error(fs->event, "%s", fs_last_error(fs));
1205 void fs_set_error_async(struct fs *fs)
1207 fs_set_error(fs, "Asynchronous operation in progress");
1244 return fs_file_init_with_event(parent->fs->parent, parent->event,
1252 return fs_iter_init_with_event(parent->fs->parent, parent->event,