The attached patch adds support for doing e.g.:

namespace {
  type = public
  prefix = Public/
  location = mdbox:/var/lib/public/mdbox:INDEXPVT=~/mdbox/public
  list = yes
}

So the private flags are stored in indexes under ~/mdbox/public/, while
the shared flags are stored under /var/lib/public/mdbox/. The patch
currently hardcodes the shared flags as only MAIL_SEEN. I'm not really
sure what would be the best place to configure which flags are private.
Perhaps a per-namespace default, but how to configure it per-mailbox?

Also per-user keywords aren't currently supported. And it's a little bit
annoying that each private flag update must increase the shared modseq
for the message, but that can't really be helped. (Alternative would be
for each user to have their own private modseqs, which could get
difficult.)

I'll probably commit this to v2.1 after some more testing.
diff -r 16f95654ddac src/doveadm/doveadm-dump-log.c
--- a/src/doveadm/doveadm-dump-log.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/doveadm/doveadm-dump-log.c	Tue Apr 03 15:52:59 2012 +0300
@@ -282,8 +282,8 @@
 		const struct mail_transaction_flag_update *u = data;
 
 		for (; size > 0; size -= sizeof(*u), u++) {
-			printf(" - uids=%u-%u (flags +%x-%x)\n",
-			       u->uid1, u->uid2, u->add_flags, u->remove_flags);
+			printf(" - uids=%u-%u (flags +%x-%x, modseq_inc_flag=%d)\n",
+			       u->uid1, u->uid2, u->add_flags, u->remove_flags, u->modseq_inc_flag);
 		}
 		break;
 	}
diff -r 16f95654ddac src/lib-index/mail-index-private.h
--- a/src/lib-index/mail-index-private.h	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-index/mail-index-private.h	Tue Apr 03 15:52:59 2012 +0300
@@ -39,8 +39,8 @@
 	 PTR_OFFSET((map)->rec_map->records, (idx) * (map)->hdr.record_size))
 
 #define MAIL_TRANSACTION_FLAG_UPDATE_IS_INTERNAL(u) \
-	((((u)->add_flags | (u)->remove_flags) & \
-	  MAIL_INDEX_FLAGS_MASK) == 0)
+	((((u)->add_flags | (u)->remove_flags) & MAIL_INDEX_FLAGS_MASK) == 0 && \
+	 (u)->modseq_inc_flag == 0)
 
 #define MAIL_INDEX_EXT_KEYWORDS "keywords"
 
diff -r 16f95654ddac src/lib-index/mail-index-transaction-export.c
--- a/src/lib-index/mail-index-transaction-export.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-index/mail-index-transaction-export.c	Tue Apr 03 15:52:59 2012 +0300
@@ -20,6 +20,34 @@
 					buf->data, buf->used);
 }
 
+static void log_append_flag_updates(struct mail_index_export_context *ctx,
+				    struct mail_index_transaction *t)
+{
+	ARRAY_DEFINE(log_updates, struct mail_transaction_flag_update);
+	const struct mail_index_flag_update *updates;
+	struct mail_transaction_flag_update *log_update;
+	unsigned int i, count;
+
+	updates = array_get(&t->updates, &count);
+	if (count == 0)
+		return;
+
+	i_array_init(&log_updates, count);
+
+	for (i = 0; i < count; i++) {
+		log_update = array_append_space(&log_updates);
+		log_update->uid1 = updates[i].uid1;
+		log_update->uid2 = updates[i].uid2;
+		log_update->add_flags = updates[i].add_flags & 0xff;
+		log_update->remove_flags = updates[i].remove_flags & 0xff;
+		if ((updates[i].add_flags & MAIL_INDEX_MAIL_FLAG_UPDATE_MODSEQ) != 0)
+			log_update->modseq_inc_flag = 1;
+	}
+	log_append_buffer(ctx, log_updates.arr.buffer,
+			  MAIL_TRANSACTION_FLAG_UPDATE);
+	array_free(&log_updates);
+}
+
 static const buffer_t *
 log_get_hdr_update_buffer(struct mail_index_transaction *t, bool prepend)
 {
@@ -373,8 +401,7 @@
 
 	if (array_is_created(&t->updates)) {
 		change_mask |= MAIL_INDEX_SYNC_TYPE_FLAGS;
-		log_append_buffer(&ctx, t->updates.arr.buffer, 
-				  MAIL_TRANSACTION_FLAG_UPDATE);
+		log_append_flag_updates(&ctx, t);
 	}
 
 	if (array_is_created(&t->ext_rec_updates)) {
diff -r 16f95654ddac src/lib-index/mail-index-transaction-finish.c
--- a/src/lib-index/mail-index-transaction-finish.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-index/mail-index-transaction-finish.c	Tue Apr 03 15:52:59 2012 +0300
@@ -80,7 +80,7 @@
 
 static unsigned int
 mail_transaction_drop_range(struct mail_index_transaction *t,
-			    struct mail_transaction_flag_update update,
+			    struct mail_index_flag_update update,
 			    unsigned int update_idx,
 			    ARRAY_TYPE(seq_range) *keeps)
 {
@@ -109,7 +109,7 @@
 static void
 mail_index_transaction_finish_flag_updates(struct mail_index_transaction *t)
 {
-	const struct mail_transaction_flag_update *updates, *u;
+	const struct mail_index_flag_update *updates, *u;
 	const struct mail_index_record *rec;
 	unsigned int i, count;
 	ARRAY_TYPE(seq_range) keeps;
diff -r 16f95654ddac src/lib-index/mail-index-transaction-private.h
--- a/src/lib-index/mail-index-transaction-private.h	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-index/mail-index-transaction-private.h	Tue Apr 03 15:52:59 2012 +0300
@@ -29,6 +29,12 @@
 	struct mail_index_module_register *reg;
 };
 
+struct mail_index_flag_update {
+	uint32_t uid1, uid2;
+	uint16_t add_flags;
+	uint16_t remove_flags;
+};
+
 struct mail_index_transaction {
 	int refcount;
 
@@ -46,7 +52,7 @@
 
 	ARRAY_DEFINE(modseq_updates, struct mail_transaction_modseq_update);
 	ARRAY_DEFINE(expunges, struct mail_transaction_expunge_guid);
-	ARRAY_DEFINE(updates, struct mail_transaction_flag_update);
+	ARRAY_DEFINE(updates, struct mail_index_flag_update);
 	size_t last_update_idx;
 
 	unsigned char pre_hdr_change[sizeof(struct mail_index_header)];
diff -r 16f95654ddac src/lib-index/mail-index-transaction-update.c
--- a/src/lib-index/mail-index-transaction-update.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-index/mail-index-transaction-update.c	Tue Apr 03 15:52:59 2012 +0300
@@ -393,7 +393,7 @@
 					   unsigned int right_idx,
 					   uint32_t seq)
 {
-	const struct mail_transaction_flag_update *updates;
+	const struct mail_index_flag_update *updates;
 	unsigned int idx, count;
 
 	updates = array_get(&t->updates, &count);
@@ -419,10 +419,10 @@
 
 static void
 mail_index_insert_flag_update(struct mail_index_transaction *t,
-			      struct mail_transaction_flag_update u,
+			      struct mail_index_flag_update u,
 			      unsigned int idx)
 {
-	struct mail_transaction_flag_update *updates, tmp_update;
+	struct mail_index_flag_update *updates, tmp_update;
 	unsigned int count, first_idx, max;
 
 	updates = array_get_modifiable(&t->updates, &count);
@@ -548,7 +548,7 @@
 				   enum mail_flags flags)
 {
 	struct mail_index_record *rec;
-	struct mail_transaction_flag_update u, *last_update;
+	struct mail_index_flag_update u, *last_update;
 	unsigned int idx, first_idx, count;
 
 	update_minmax_flagupdate_seq(t, seq1, seq2);
@@ -1092,7 +1092,7 @@
 bool mail_index_cancel_flag_updates(struct mail_index_transaction *t,
 				    uint32_t seq)
 {
-	struct mail_transaction_flag_update *updates, tmp_update;
+	struct mail_index_flag_update *updates, tmp_update;
 	unsigned int i, count;
 
 	if (!array_is_created(&t->updates))
diff -r 16f95654ddac src/lib-index/mail-index-transaction-view.c
--- a/src/lib-index/mail-index-transaction-view.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-index/mail-index-transaction-view.c	Tue Apr 03 15:52:59 2012 +0300
@@ -85,7 +85,7 @@
 			 const struct mail_index_record *rec, uint32_t seq)
 {
 	struct mail_index_transaction *t = tview->t;
-	const struct mail_transaction_flag_update *updates;
+	const struct mail_index_flag_update *updates;
 	struct mail_index_record *trec;
 	unsigned int idx, count;
 
diff -r 16f95654ddac src/lib-index/mail-index.h
--- a/src/lib-index/mail-index.h	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-index/mail-index.h	Tue Apr 03 15:52:59 2012 +0300
@@ -42,9 +42,11 @@
 
 enum mail_index_mail_flags {
 	/* For private use by backend. Replacing flags doesn't change this. */
-	MAIL_INDEX_MAIL_FLAG_BACKEND	= 0x40,
+	MAIL_INDEX_MAIL_FLAG_BACKEND		= 0x40,
 	/* Message flags haven't been written to backend */
-	MAIL_INDEX_MAIL_FLAG_DIRTY	= 0x80
+	MAIL_INDEX_MAIL_FLAG_DIRTY		= 0x80,
+	/* Force updating this message's modseq via a flag update record */
+	MAIL_INDEX_MAIL_FLAG_UPDATE_MODSEQ	= 0x100
 };
 
 #define MAIL_INDEX_FLAGS_MASK \
diff -r 16f95654ddac src/lib-index/mail-transaction-log.h
--- a/src/lib-index/mail-transaction-log.h	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-index/mail-transaction-log.h	Tue Apr 03 15:52:59 2012 +0300
@@ -87,7 +87,8 @@
 	uint32_t uid1, uid2;
 	uint8_t add_flags;
 	uint8_t remove_flags;
-	uint16_t padding;
+	uint8_t modseq_inc_flag;
+	uint8_t padding;
 };
 
 struct mail_transaction_keyword_update {
diff -r 16f95654ddac src/lib-index/test-mail-index-transaction-finish.c
--- a/src/lib-index/test-mail-index-transaction-finish.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-index/test-mail-index-transaction-finish.c	Tue Apr 03 15:52:59 2012 +0300
@@ -60,8 +60,8 @@
 static void test_mail_index_transaction_finish_flag_updates(void)
 {
 	struct mail_index_transaction *t;
-	const struct mail_transaction_flag_update *updates;
-	struct mail_transaction_flag_update u;
+	const struct mail_index_flag_update *updates;
+	struct mail_index_flag_update u;
 	unsigned int count;
 
 	t = t_new(struct mail_index_transaction, 1);
diff -r 16f95654ddac src/lib-index/test-mail-index-transaction-update.c
--- a/src/lib-index/test-mail-index-transaction-update.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-index/test-mail-index-transaction-update.c	Tue Apr 03 15:52:59 2012 +0300
@@ -125,7 +125,7 @@
 static void test_mail_index_flag_update_fastpath(void)
 {
 	struct mail_index_transaction *t;
-	const struct mail_transaction_flag_update *updates;
+	const struct mail_index_flag_update *updates;
 	unsigned int count;
 
 	hdr.messages_count = 20;
@@ -154,12 +154,10 @@
 	test_assert(updates[0].add_flags == MAIL_DELETED);
 	test_assert(updates[0].remove_flags ==
 		    (MAIL_ANSWERED | MAIL_FLAGGED | MAIL_SEEN | MAIL_DRAFT));
-	test_assert(updates[0].padding == 0);
 	test_assert(updates[1].uid1 == 16);
 	test_assert(updates[1].uid2 == 16);
 	test_assert(updates[1].add_flags == MAIL_DELETED);
 	test_assert(updates[1].remove_flags == 0);
-	test_assert(updates[1].padding == 0);
 	test_assert(!t->log_updates);
 	test_end();
 }
@@ -167,7 +165,7 @@
 static void test_mail_index_flag_update_simple_merges(void)
 {
 	struct mail_index_transaction *t;
-	const struct mail_transaction_flag_update *updates;
+	const struct mail_index_flag_update *updates;
 	unsigned int count;
 
 	hdr.messages_count = 20;
@@ -210,7 +208,7 @@
 static void test_mail_index_flag_update_complex_merges(void)
 {
 	struct mail_index_transaction *t;
-	const struct mail_transaction_flag_update *updates;
+	const struct mail_index_flag_update *updates;
 	unsigned int count;
 
 	hdr.messages_count = 20;
@@ -269,7 +267,7 @@
 flags_array_check(struct mail_index_transaction *t,
 		  const enum mail_flags *flags, unsigned int msg_count)
 {
-	const struct mail_transaction_flag_update *updates;
+	const struct mail_index_flag_update *updates;
 	unsigned int i, count, seq;
 
 	if (array_is_created(&t->updates))
@@ -343,7 +341,7 @@
 static void test_mail_index_cancel_flag_updates(void)
 {
 	struct mail_index_transaction *t;
-	const struct mail_transaction_flag_update *updates;
+	const struct mail_index_flag_update *updates;
 	unsigned int count;
 
 	hdr.messages_count = 20;
@@ -376,7 +374,7 @@
 {
 	struct mail_index_transaction *t;
 	const struct mail_index_record *appends;
-	const struct mail_transaction_flag_update *updates;
+	const struct mail_index_flag_update *updates;
 	unsigned int count;
 	uint32_t seq;
 
diff -r 16f95654ddac src/lib-storage/index/Makefile.am
--- a/src/lib-storage/index/Makefile.am	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-storage/index/Makefile.am	Tue Apr 03 15:52:59 2012 +0300
@@ -26,6 +26,7 @@
 	index-storage.c \
 	index-sync.c \
 	index-sync-changes.c \
+	index-sync-pvt.c \
 	index-sync-search.c \
 	index-thread.c \
 	index-thread-finish.c \
diff -r 16f95654ddac src/lib-storage/index/index-mail.c
--- a/src/lib-storage/index/index-mail.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-storage/index/index-mail.c	Tue Apr 03 15:52:59 2012 +0300
@@ -138,18 +138,45 @@
 					  size_r, sizeof(*size_r));
 }
 
-enum mail_flags index_mail_get_flags(struct mail *mail)
+static bool index_mail_get_pvt(struct mail *_mail)
 {
+	struct mail_private *mail = (struct mail_private *)_mail;
+
+	if (mail->seq_pvt != 0)
+		return TRUE;
+	if (_mail->box->view_pvt == NULL) {
+		/* no private view (set by view syncing) -> no private flags */
+		return FALSE;
+	}
+
+	index_transaction_init_pvt(_mail->transaction);
+	if (!mail_index_lookup_seq(_mail->transaction->view_pvt, _mail->uid,
+				   &mail->seq_pvt))
+		mail->seq_pvt = 0;
+	return mail->seq_pvt != 0;
+}
+
+enum mail_flags index_mail_get_flags(struct mail *_mail)
+{
+	struct mail_private *mail = (struct mail_private *)_mail;
 	const struct mail_index_record *rec;
-	enum mail_flags flags;
+	enum mail_flags flags, pvt_flags_mask;
 
-	rec = mail_index_lookup(mail->transaction->view, mail->seq);
+	rec = mail_index_lookup(_mail->transaction->view, _mail->seq);
 	flags = rec->flags & (MAIL_FLAGS_NONRECENT |
 			      MAIL_INDEX_MAIL_FLAG_BACKEND);
 
-	if (index_mailbox_is_recent(mail->box, mail->uid))
+	if (index_mailbox_is_recent(_mail->box, _mail->uid))
 		flags |= MAIL_RECENT;
 
+	if (index_mail_get_pvt(_mail)) {
+		/* mailbox has private flags */
+		pvt_flags_mask = mailbox_get_private_flags_mask(_mail->box);
+		flags &= ~pvt_flags_mask;
+		rec = mail_index_lookup(_mail->transaction->view_pvt,
+					mail->seq_pvt);
+		flags |= rec->flags & pvt_flags_mask;
+	}
 	return flags;
 }
 
@@ -1223,6 +1250,7 @@
 
 	mail->mail.mail.seq = 0;
 	mail->mail.mail.uid = 0;
+	mail->mail.seq_pvt = 0;
 	mail->mail.mail.expunged = FALSE;
 	mail->mail.mail.has_nuls = FALSE;
 	mail->mail.mail.has_no_nuls = FALSE;
@@ -1599,15 +1627,43 @@
 	}
 }
 
-void index_mail_update_flags(struct mail *mail, enum modify_type modify_type,
+void index_mail_update_flags(struct mail *_mail, enum modify_type modify_type,
 			     enum mail_flags flags)
 {
+	struct mail_private *mail = (struct mail_private *)_mail;
+	enum mail_flags pvt_flags_mask, pvt_flags = 0;
+	bool update_modseq = FALSE;
+
 	if ((flags & MAIL_RECENT) == 0 &&
-	    index_mailbox_is_recent(mail->box, mail->uid))
-		index_mail_drop_recent_flag(mail);
+	    index_mailbox_is_recent(_mail->box, _mail->uid))
+		index_mail_drop_recent_flag(_mail);
+	flags &= MAIL_FLAGS_NONRECENT | MAIL_INDEX_MAIL_FLAG_BACKEND;
 
-	flags &= MAIL_FLAGS_NONRECENT | MAIL_INDEX_MAIL_FLAG_BACKEND;
-	mail_index_update_flags(mail->transaction->itrans, mail->seq,
+	if (_mail->box->view_pvt != NULL) {
+		/* mailbox has private flags */
+		pvt_flags_mask = mailbox_get_private_flags_mask(_mail->box);
+		pvt_flags = flags & pvt_flags_mask;
+		flags &= ~pvt_flags_mask;
+		if (index_mail_get_pvt(_mail) &&
+		    (pvt_flags != 0 || modify_type == MODIFY_REPLACE)) {
+			mail_index_update_flags(_mail->transaction->itrans_pvt,
+						mail->seq_pvt,
+						modify_type, pvt_flags);
+			update_modseq = TRUE;
+		}
+	}
+
+	if (!update_modseq) {
+		/* no forced modseq update */
+	} else if (modify_type == MODIFY_REMOVE) {
+		/* add the modseq update separately */
+		mail_index_update_flags(_mail->transaction->itrans, _mail->seq,
+			MODIFY_ADD, (enum mail_flags )MAIL_INDEX_MAIL_FLAG_UPDATE_MODSEQ);
+	} else {
+		/* add as part of the flag updates */
+		flags |= MAIL_INDEX_MAIL_FLAG_UPDATE_MODSEQ;
+	}
+	mail_index_update_flags(_mail->transaction->itrans, _mail->seq,
 				modify_type, flags);
 }
 
diff -r 16f95654ddac src/lib-storage/index/index-storage.c
--- a/src/lib-storage/index/index-storage.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-storage/index/index-storage.c	Tue Apr 03 15:52:59 2012 +0300
@@ -332,6 +332,10 @@
 	if (box->input != NULL)
 		i_stream_unref(&box->input);
 
+	if (box->view_pvt != NULL)
+		mail_index_view_close(&box->view_pvt);
+	if (box->index_pvt != NULL)
+		mail_index_close(box->index_pvt);
 	mail_index_view_close(&box->view);
 	mail_index_close(box->index);
 	box->cache = NULL;
@@ -349,6 +353,8 @@
 
 void index_storage_mailbox_free(struct mailbox *box)
 {
+	if (box->index_pvt != NULL)
+		mail_index_alloc_cache_unref(&box->index_pvt);
 	if (box->index != NULL)
 		mail_index_alloc_cache_unref(&box->index);
 }
diff -r 16f95654ddac src/lib-storage/index/index-storage.h
--- a/src/lib-storage/index/index-storage.h	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-storage/index/index-storage.h	Tue Apr 03 15:52:59 2012 +0300
@@ -129,6 +129,7 @@
 void index_transaction_init(struct mailbox_transaction_context *t,
 			    struct mailbox *box,
 			    enum mailbox_transaction_flags flags);
+void index_transaction_init_pvt(struct mailbox_transaction_context *t);
 int index_transaction_commit(struct mailbox_transaction_context *t,
 			     struct mail_transaction_commit_changes *changes_r);
 void index_transaction_rollback(struct mailbox_transaction_context *t);
diff -r 16f95654ddac src/lib-storage/index/index-sync-private.h
--- a/src/lib-storage/index/index-sync-private.h	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-storage/index/index-sync-private.h	Tue Apr 03 15:52:59 2012 +0300
@@ -22,4 +22,6 @@
 void index_sync_search_results_update(struct index_mailbox_sync_context *ctx);
 void index_sync_search_results_expunge(struct index_mailbox_sync_context *ctx);
 
+int index_storage_mailbox_sync_pvt(struct mailbox *box);
+
 #endif
diff -r 16f95654ddac src/lib-storage/index/index-sync.c
--- a/src/lib-storage/index/index-sync.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-storage/index/index-sync.c	Tue Apr 03 15:52:59 2012 +0300
@@ -184,6 +184,9 @@
 	ctx->ctx.box = box;
 	ctx->ctx.flags = flags;
 
+	/* sync private index if needed */
+	(void)index_storage_mailbox_sync_pvt(box);
+
 	if (failed) {
 		ctx->failed = TRUE;
 		return &ctx->ctx;
diff -r 16f95654ddac src/lib-storage/index/index-transaction.c
--- a/src/lib-storage/index/index-transaction.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-storage/index/index-transaction.c	Tue Apr 03 15:52:59 2012 +0300
@@ -7,6 +7,8 @@
 
 static void index_transaction_free(struct mailbox_transaction_context *t)
 {
+	if (t->view_pvt != NULL)
+		mail_index_view_close(&t->view_pvt);
 	mail_cache_view_close(&t->cache_view);
 	mail_index_view_close(&t->view);
 	array_free(&t->module_contexts);
@@ -67,24 +69,46 @@
 	index_transaction_free(t);
 }
 
+static enum mail_index_transaction_flags
+index_transaction_flags_get(enum mailbox_transaction_flags flags)
+{
+	enum mail_index_transaction_flags itrans_flags;
+
+	itrans_flags = MAIL_INDEX_TRANSACTION_FLAG_AVOID_FLAG_UPDATES;
+	if ((flags & MAILBOX_TRANSACTION_FLAG_HIDE) != 0)
+		itrans_flags |= MAIL_INDEX_TRANSACTION_FLAG_HIDE;
+	if ((flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0)
+		itrans_flags |= MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL;
+	return itrans_flags;
+}
+
+void index_transaction_init_pvt(struct mailbox_transaction_context *t)
+{
+	enum mail_index_transaction_flags itrans_flags;
+
+	if (t->box->view_pvt == NULL || t->itrans_pvt != NULL)
+		return;
+
+	itrans_flags = index_transaction_flags_get(t->flags);
+	t->itrans_pvt = mail_index_transaction_begin(t->box->view_pvt,
+						     itrans_flags);
+	t->view_pvt = mail_index_transaction_open_updated_view(t->itrans_pvt);
+}
+
 void index_transaction_init(struct mailbox_transaction_context *t,
 			    struct mailbox *box,
 			    enum mailbox_transaction_flags flags)
 {
-	enum mail_index_transaction_flags trans_flags;
+	enum mail_index_transaction_flags itrans_flags;
 
 	i_assert(box->opened);
 
-	trans_flags = MAIL_INDEX_TRANSACTION_FLAG_AVOID_FLAG_UPDATES;
-	if ((flags & MAILBOX_TRANSACTION_FLAG_HIDE) != 0)
-		trans_flags |= MAIL_INDEX_TRANSACTION_FLAG_HIDE;
-	if ((flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0)
-		trans_flags |= MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL;
+	itrans_flags = index_transaction_flags_get(flags);
 	if ((flags & MAILBOX_TRANSACTION_FLAG_REFRESH) != 0)
 		(void)mail_index_refresh(box->index);
 
 	t->box = box;
-	t->itrans = mail_index_transaction_begin(box->view, trans_flags);
+	t->itrans = mail_index_transaction_begin(box->view, itrans_flags);
 	t->view = mail_index_transaction_open_updated_view(t->itrans);
 
 	array_create(&t->module_contexts, default_pool,
@@ -121,7 +145,7 @@
 	struct mailbox *box = t->box;
 	struct mail_index_transaction *itrans = t->itrans;
 	struct mail_index_transaction_commit_result result;
-	int ret;
+	int ret = 0;
 
 	memset(changes_r, 0, sizeof(*changes_r));
 	changes_r->pool = pool_alloconly_create(MEMPOOL_GROWING
@@ -129,7 +153,10 @@
 	p_array_init(&changes_r->saved_uids, changes_r->pool, 32);
 	t->changes = changes_r;
 
-	ret = mail_index_transaction_commit_full(&itrans, &result);
+	if (t->itrans_pvt != NULL)
+		ret = mail_index_transaction_commit(&t->itrans_pvt);
+	if (mail_index_transaction_commit_full(&itrans, &result) < 0)
+		ret = -1;
 	t = NULL;
 
 	if (ret < 0 && mail_index_is_deleted(box->index))
@@ -143,5 +170,7 @@
 {
 	struct mail_index_transaction *itrans = t->itrans;
 
+	if (t->itrans_pvt != NULL)
+		mail_index_transaction_rollback(&t->itrans_pvt);
 	mail_index_transaction_rollback(&itrans);
 }
diff -r 16f95654ddac src/lib-storage/index/shared/shared-list.c
--- a/src/lib-storage/index/shared/shared-list.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-storage/index/shared/shared-list.c	Tue Apr 03 15:52:59 2012 +0300
@@ -99,6 +99,7 @@
 		case MAILBOX_LIST_PATH_TYPE_MAILBOX:
 		case MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX:
 		case MAILBOX_LIST_PATH_TYPE_CONTROL:
+		case MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE:
 			break;
 		case MAILBOX_LIST_PATH_TYPE_INDEX:
 			/* we can safely say we don't use indexes */
diff -r 16f95654ddac src/lib-storage/list/mailbox-list-fs.c
--- a/src/lib-storage/list/mailbox-list-fs.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-storage/list/mailbox-list-fs.c	Tue Apr 03 15:52:59 2012 +0300
@@ -193,6 +193,11 @@
 					       set->mailbox_dir_name, name);
 		}
 		break;
+	case MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE:
+		if (set->index_pvt_dir == NULL)
+			return NULL;
+		return t_strdup_printf("%s/%s%s", set->index_pvt_dir,
+				       set->mailbox_dir_name, name);
 	}
 
 	if (type == MAILBOX_LIST_PATH_TYPE_ALT_DIR ||
diff -r 16f95654ddac src/lib-storage/list/mailbox-list-maildir.c
--- a/src/lib-storage/list/mailbox-list-maildir.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-storage/list/mailbox-list-maildir.c	Tue Apr 03 15:52:59 2012 +0300
@@ -225,6 +225,11 @@
 						_list->set.index_dir, name);
 		}
 		break;
+	case MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE:
+		if (_list->set.index_pvt_dir == NULL)
+			return NULL;
+		return maildir_list_get_dirname_path(_list,
+					_list->set.index_pvt_dir, name);
 	}
 
 	if (type == MAILBOX_LIST_PATH_TYPE_ALT_DIR ||
diff -r 16f95654ddac src/lib-storage/mail-storage-private.h
--- a/src/lib-storage/mail-storage-private.h	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-storage/mail-storage-private.h	Tue Apr 03 15:52:59 2012 +0300
@@ -220,6 +220,11 @@
 	struct mail_index *index;
 	struct mail_index_view *view;
 	struct mail_cache *cache;
+	/* Private per-user index/view for shared mailboxes. These are synced
+	   against the primary index and used to store per-user flags.
+	   These are non-NULL only when mailbox has per-user flags. */
+	struct mail_index *index_pvt;
+	struct mail_index_view *view_pvt;
 	/* Filled lazily by mailbox_get_permissions() */
 	struct mailbox_permissions _perm;
 	/* Filled lazily by mailbox_get_path() */
@@ -342,6 +347,8 @@
 	struct mail mail;
 	struct mail_vfuncs v, *vlast;
 
+	uint32_t seq_pvt;
+
 	/* initial wanted fields/headers, set by mail_alloc(): */
 	enum mail_fetch_field wanted_fields;
 	struct mailbox_header_lookup_ctx *wanted_headers;
@@ -384,6 +391,10 @@
 	/* view contains all changes done within this transaction */
 	struct mail_index_view *view;
 
+	/* for private index updates: */
+	struct mail_index_transaction *itrans_pvt;
+	struct mail_index_view *view_pvt;
+
 	struct mail_cache_view *cache_view;
 	struct mail_cache_transaction_ctx *cache_trans;
 
diff -r 16f95654ddac src/lib-storage/mail-storage.c
--- a/src/lib-storage/mail-storage.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-storage/mail-storage.c	Tue Apr 03 15:52:59 2012 +0300
@@ -1279,10 +1279,12 @@
 
 enum mail_flags mailbox_get_private_flags_mask(struct mailbox *box)
 {
-	if (box->v.get_private_flags_mask == NULL)
+	if (box->v.get_private_flags_mask != NULL)
+		return box->v.get_private_flags_mask(box);
+	else if (box->list->set.index_pvt_dir != NULL)
+		return MAIL_SEEN; // FIXME
+	else
 		return 0;
-	else
-		return box->v.get_private_flags_mask(box);
 }
 
 struct mailbox_sync_context *
diff -r 16f95654ddac src/lib-storage/mailbox-list-private.h
--- a/src/lib-storage/mailbox-list-private.h	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-storage/mailbox-list-private.h	Tue Apr 03 15:52:59 2012 +0300
@@ -199,6 +199,8 @@
 					const char **name);
 int mailbox_list_create_missing_index_dir(struct mailbox_list *list,
 					  const char *name);
+int mailbox_list_create_missing_index_pvt_dir(struct mailbox_list *list,
+					      const char *name);
 
 void mailbox_list_add_change(struct mailbox_list *list,
 			     enum mailbox_log_record_type type,
diff -r 16f95654ddac src/lib-storage/mailbox-list.c
--- a/src/lib-storage/mailbox-list.c	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-storage/mailbox-list.c	Tue Apr 03 15:52:59 2012 +0300
@@ -149,6 +149,9 @@
 		list->set.index_dir = set->index_dir == NULL ||
 			strcmp(set->index_dir, set->root_dir) == 0 ? NULL :
 			p_strdup(list->pool, set->index_dir);
+		list->set.index_pvt_dir = set->index_pvt_dir == NULL ||
+			strcmp(set->index_pvt_dir, set->root_dir) == 0 ? NULL :
+			p_strdup(list->pool, set->index_pvt_dir);
 		list->set.control_dir = set->control_dir == NULL ||
 			strcmp(set->control_dir, set->root_dir) == 0 ? NULL :
 			p_strdup(list->pool, set->control_dir);
@@ -175,10 +178,11 @@
 	list->set.utf8 = set->utf8;
 
 	if (ns->mail_set->mail_debug) {
-		i_debug("%s: root=%s, index=%s, control=%s, inbox=%s, alt=%s",
+		i_debug("%s: root=%s, index=%s, indexpvt=%s, control=%s, inbox=%s, alt=%s",
 			list->name,
 			list->set.root_dir == NULL ? "" : list->set.root_dir,
 			list->set.index_dir == NULL ? "" : list->set.index_dir,
+			list->set.index_pvt_dir == NULL ? "" : list->set.index_pvt_dir,
 			list->set.control_dir == NULL ?
 			"" : list->set.control_dir,
 			list->set.inbox_path == NULL ?
@@ -289,6 +293,8 @@
 			dest = &set_r->inbox_path;
 		else if (strcmp(key, "INDEX") == 0)
 			dest = &set_r->index_dir;
+		else if (strcmp(key, "INDEXPVT") == 0)
+			dest = &set_r->index_pvt_dir;
 		else if (strcmp(key, "CONTROL") == 0)
 			dest = &set_r->control_dir;
 		else if (strcmp(key, "ALT") == 0)
@@ -948,6 +954,8 @@
 	case MAILBOX_LIST_PATH_TYPE_INDEX:
 		return set->index_dir != NULL ?
 			set->index_dir : set->root_dir;
+	case MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE:
+		return set->index_pvt_dir;
 	}
 	i_unreached();
 }
@@ -1344,19 +1352,18 @@
 	return mailbox_list_mkdir(list, mailbox, t_strdup_until(path, p));
 }
 
-int mailbox_list_create_missing_index_dir(struct mailbox_list *list,
-					  const char *name)
+static int mailbox_list_create_missing_dir(struct mailbox_list *list,
+					   const char *name,
+					   enum mailbox_list_path_type type)
 {
 	const char *root_dir, *index_dir, *parent_dir, *p, *error;
 	struct mailbox_permissions perm;
 	unsigned int n = 0;
 
-	list->index_root_dir_created = TRUE;
 	root_dir = mailbox_list_get_path(list, name,
 					 MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	index_dir = mailbox_list_get_path(list, name,
-					  MAILBOX_LIST_PATH_TYPE_INDEX);
-	if (*index_dir == '\0')
+	index_dir = mailbox_list_get_path(list, name, type);
+	if (index_dir == NULL || *index_dir == '\0')
 		return 0;
 	if (strcmp(index_dir, root_dir) == 0) {
 		if ((list->props & MAILBOX_LIST_PROP_AUTOCREATE_DIRS) == 0)
@@ -1365,8 +1372,7 @@
 	}
 
 	if (name == NULL) {
-		if (mailbox_list_mkdir_root(list, index_dir,
-					    MAILBOX_LIST_PATH_TYPE_INDEX,
+		if (mailbox_list_mkdir_root(list, index_dir, type,
 					    &error) < 0) {
 			mailbox_list_set_critical(list,
 				"Couldn't create index root dir %s: %s",
@@ -1391,8 +1397,7 @@
 		}
 		/* create the parent directory first */
 		parent_dir = t_strdup_until(index_dir, p);
-		if (mailbox_list_mkdir_root(list, parent_dir,
-					    MAILBOX_LIST_PATH_TYPE_INDEX,
+		if (mailbox_list_mkdir_root(list, parent_dir, type,
 					    &error) < 0) {
 			mailbox_list_set_critical(list,
 				"Couldn't create index dir %s: %s",
@@ -1403,6 +1408,21 @@
 	return 0;
 }
 
+int mailbox_list_create_missing_index_dir(struct mailbox_list *list,
+					  const char *name)
+{
+	list->index_root_dir_created = TRUE;
+	return mailbox_list_create_missing_dir(list, name,
+		MAILBOX_LIST_PATH_TYPE_INDEX);
+}
+
+int mailbox_list_create_missing_index_pvt_dir(struct mailbox_list *list,
+					      const char *name)
+{
+	return mailbox_list_create_missing_dir(list, name,
+		MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE);
+}
+
 const char *mailbox_list_get_last_error(struct mailbox_list *list,
 					enum mail_error *error_r)
 {
diff -r 16f95654ddac src/lib-storage/mailbox-list.h
--- a/src/lib-storage/mailbox-list.h	Tue Apr 03 14:45:10 2012 +0300
+++ b/src/lib-storage/mailbox-list.h	Tue Apr 03 15:52:59 2012 +0300
@@ -101,8 +101,10 @@
 	MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX,
 	/* Return control directory */
 	MAILBOX_LIST_PATH_TYPE_CONTROL,
-	/* Return index file directory */
-	MAILBOX_LIST_PATH_TYPE_INDEX
+	/* Return index directory ("" for in-memory) */
+	MAILBOX_LIST_PATH_TYPE_INDEX,
+	/* Return the private index directory (NULL if none) */
+	MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE
 };
 
 enum mailbox_list_file_type {
@@ -117,6 +119,7 @@
 	const char *layout; /* FIXME: shouldn't be here */
 	const char *root_dir;
 	const char *index_dir;
+	const char *index_pvt_dir;
 	const char *control_dir;
 	const char *alt_dir; /* FIXME: dbox-specific.. */
 

Reply via email to