// ExpireFromIndex reads the expire index and expires messages as they are recorded func (store Store) ExpireFromIndex(cycles int) { // run from now backwards N cycles now := uint64(time.Now().Unix()) expireTime := (now / uint64(ExpireRun)) for i := cycles; i > 0; i-- { expireTime -= uint64(ExpireRun) log.Debugf("Expire index try: %d\n", expireTime) if expireTime > 0 { if store.expireindex.Index(utils.EncodeUInt64(expireTime)).Exists() { j := int64(0) log.Debugf("Expire index found: %d\n", expireTime) ExpireEntries: for { entry, err := store.expireindex.Index(utils.EncodeUInt64(expireTime)).ReadEntry(j) if err != nil { // no more entries log.Debugf("Expire index empty: %d\n", expireTime) break ExpireEntries } j++ if entry == nil { log.Debugf("Expire index bad entry: %d %d\n", j, expireTime) continue // bad entry } entryStruct := structs.ExpireStructDecode(entry) if entryStruct == nil { log.Debugf("Expire index bad entry decode: %d %d\n", j, expireTime) continue // bad entry } if entryStruct.ExpireTime > now { log.Debugf("Expire index bad entry not expired: %d %d\n", j, expireTime) continue // bad entry } store.messages.Index(entryStruct.MessageID[:]).Delete() // Delete message store.signers.Index(entryStruct.SignerPubKey[:]).Update(func(tx fileback.Tx) error { data := tx.GetLast() if data == nil { // we don't care about errors here return nil } signer := structs.SignerStructDecode(data) if signer == nil { return nil } signer.MessagesRetained-- tx.Append(signer.Encode().Fill()) return nil }) } // Remove expire list store.expireindex.Index(utils.EncodeUInt64(expireTime)).Delete() log.Debugf("Expire index deleted: %d\n", expireTime) } else { log.Debugf("Expire index does not exist: %d\n", expireTime) } } } }
// PreExpire expires a message in the next expire run func (store Store) PreExpire(messageID *[message.MessageIDSize]byte, pubkey *message.Curve25519Key) error { data := store.messages.Index(messageID[:]).GetLast() if data == nil || len(data) < MaxMessageSize+structs.MessageStructSize { return ErrNotFound } msgStruct := structs.MessageStructDecode(data[:structs.MessageStructSize]) if msgStruct.ReceiverConstantPubKey == *pubkey { // Add to expire expire := &structs.ExpireStruct{ ExpireTime: uint64(time.Now().Unix()), MessageID: msgStruct.MessageID, SignerPubKey: msgStruct.SignerPub, } expireTime := (uint64(time.Now().Unix()) / uint64(ExpireRun)) + uint64(ExpireRun) return store.expireindex.Index(utils.EncodeUInt64(expireTime)).CreateAppend(expire.Encode().Fill()) } return ErrNotFound }
// Put stores a message in the message store WITHOUT notifying the notify backend func (store Store) Put(msgStruct *structs.MessageStruct, signerStruct *structs.SignerStruct, message []byte) error { // Check if message exists if store.MessageExists(msgStruct.MessageID) { return ErrDuplicate } // Check if signer exists, load last from signer signerLoaded := structs.SignerStructDecode(store.signers.Index(signerStruct.PublicKey[:]).GetLast()) if signerLoaded != nil { // Old signer is better if signerLoaded.Bits > signerStruct.Bits { signerStruct.Bits = signerLoaded.Bits signerStruct.Nonce = signerLoaded.Nonce signerStruct.MaxMessagesPosted = signerLoaded.MaxMessagesPosted signerStruct.MaxMessagesRetained = signerLoaded.MaxMessagesRetained } // Update post data signerStruct.MessagesPosted = signerLoaded.MessagesPosted signerStruct.MessagesRetained = signerLoaded.MessagesRetained } // Verify signer if signerStruct.MessagesPosted >= signerStruct.MaxMessagesPosted { return ErrPostLimit } if signerStruct.MessagesRetained >= signerStruct.MaxMessagesRetained { // Retention is changed by expiring messages return ErrPostLimit } msgStruct.PostTime = uint64(time.Now().Unix()) msgStruct.ExpireTime = uint64(uint64(time.Now().Unix()) + signerStruct.ExpireTarget) if msgStruct.ExpireTime < msgStruct.ExpireRequest { msgStruct.ExpireTime = msgStruct.ExpireRequest } // Update signer err := store.signers.Index(signerStruct.PublicKey[:]).CreateAppend(signerStruct.Encode()) // Ignore errors on signer update. They don't matter much if err != nil { log.Errorf("messagestore, update signer: %s", err) } // Write message. Message is prefixed by encoded messageStruct msgStructEncoded := msgStruct.Encode().Fill() err = store.messages.Index(msgStruct.MessageID[:]).Create(append(msgStructEncoded, message...)) if err != nil { log.Errorf("messagestore, write message: %s", err) return err } if !msgStruct.OneTime && msgStruct.Sync { // TX: Add to global index if store.keyindex.Index(globalindex).Exists() { err := store.keyindex.Index(globalindex).Update(func(tx fileback.Tx) error { // Ignore errors return updateKeyIndex(tx, msgStruct, msgStructEncoded) }) if err != nil { log.Errorf("messagestore, globalindex append: %s", err) } } else { err := store.keyindex.Index(globalindex).CreateAppend(msgStructEncoded) if err != nil { log.Errorf("messagestore, globalindex createAppend: %s", err) } } } // TX: Add to key index if store.keyindex.Index(msgStruct.ReceiverConstantPubKey[:]).Exists() { err := store.keyindex.Index(msgStruct.ReceiverConstantPubKey[:]).Update(func(tx fileback.Tx) error { // Ignore errors return updateKeyIndex(tx, msgStruct, msgStructEncoded) }) if err != nil { log.Errorf("messagestore, receiverPub append: %s", err) } } else { err := store.keyindex.Index(msgStruct.ReceiverConstantPubKey[:]).CreateAppend(msgStructEncoded) if err != nil { log.Errorf("messagestore, receiverPub createAppend: %s", err) } } // Add to expire expire := &structs.ExpireStruct{ ExpireTime: msgStruct.ExpireTime, MessageID: msgStruct.MessageID, SignerPubKey: msgStruct.SignerPub, } expireTime := (msgStruct.ExpireTime / uint64(ExpireRun)) + uint64(ExpireRun) err = store.expireindex.Index(utils.EncodeUInt64(expireTime)).CreateAppend(expire.Encode().Fill()) if err != nil { log.Errorf("messagestore, record expire: %s", err) } return nil }