ii

package
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 16, 2023 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Database functions. Database is the file with line-bundles: msgid:base64 encoded msg. File db.idx is created and mantained automatically. There is also points.txt, db of users.

Simple log system.

Index

Constants

This section is empty.

Variables

View Source
var (
	Trace *log.Logger
	Info  *log.Logger
	Error *log.Logger
)
View Source
var MaxConnections = 6

Do not run more then MaxConnections goroutines in the same time

Functions

func FileLines

func FileLines(path string, fn func(string) bool) error

Utility to pass all lines of file (path) to fn(line). Stops on EOF or fn returns false.

func InitLog

func InitLog()

Default mode. All messages are shown.

func IsEcho

func IsEcho(e string) bool

Check if string is valid echoarea name

func IsEmptySubject

func IsEmptySubject(s string) bool

Check if subject is empty string Used when validate msg from points

func IsMsgId

func IsMsgId(id string) bool

Check if string is valid MsgId

func IsPassword

func IsPassword(u string) bool

Check password if it is valid to be used

func IsPrivate

func IsPrivate(e string) bool

Check if Echoarea is private area This is ii-go extension, echoareas that has "." prefix are for private messaging. Those areas can be fetched only with /u/point/auth/u/e/ scheme

func IsSubject

func IsSubject(s string) bool

Check if string is valid subject In fact, it is just return true stub :)

func IsUsername

func IsUsername(u string) bool

Check username if it is valid

func MakeSecret

func MakeSecret(msg string) string

Make secret from string. String is something like id + user + password

func MsgId

func MsgId(msg string) string

Make MsgId from raw text MsgId is unique identificator of message It is supposed that there is no collision of MsgId It is base64(sha256(text)) transformation

func OpenLog

func OpenLog(trace io.Writer, info io.Writer, error io.Writer)

Custom mode. Use io.Writers to select what verbose level is needed. For example: ii.OpenLog(ioutil.Discard, os.Stdout, os.Stderr)

Types

type DB

type DB struct {
	Path      string
	Idx       Index
	Sync      sync.RWMutex
	IdxSync   sync.RWMutex
	Name      string
	LockDepth int32
}

Database object. Returns by OpenDB. Idx: Index structure (like dictionary). Name: database name, 'db' by default. Sync: used to syncronize access to DB from goroutines (many readers, one writer). IdxSync: same, but for Index. LockDepth: used for recursive file lock, to avoid conflict between ii-tool and ii-node.

func OpenDB

func OpenDB(path string) *DB

Opens DB and returns pointer to DB object. path is the path to db. By default it is ./db Index will be named as path + ".idx"

func (*DB) Access

func (db *DB) Access(info *MsgInfo, user *User) bool

Check if message is private

func (*DB) Blacklist

func (db *DB) Blacklist(m *Msg) error

Blacklist decoded message. Blacklisting is adding special tag: access/blacklist and Edit operation to store it in DB. While loading index, blacklisted messages are marked by negative Off field (-1).

func (*DB) BundlePath

func (db *DB) BundlePath() string

Return path to database itself

func (*DB) CreateIndex

func (db *DB) CreateIndex() error

This function creates index. It locks.

func (*DB) Echoes

func (db *DB) Echoes(names []string, q Query) []*Echo

Make query and select Echoes Returns: slice of pointers to Echo. names: if not empty, lookup only in theese echoareas Does lock. Load/create index if needed. Echoes sorted by date of last messages.

func (*DB) Edit

func (db *DB) Edit(m *Msg) error

Store decoded message in database even it is exists. So, it's like Edit operation. While index loaded, it got last version of message data.

func (*DB) Exists

func (db *DB) Exists(Id string) *MsgInfo

Same as Lookup, but checks in blacklisted messages too

func (*DB) Get

func (db *DB) Get(Id string) *Msg

Get decoded message from db by message id. Does lock. Loads/create index if needed.

func (*DB) GetBundle

func (db *DB) GetBundle(Id string) string

Get bundle line by message id from db. Does lock! Loads/create index if needed.

func (*DB) GetBundleInfo

func (db *DB) GetBundleInfo(Id string) (string, *MsgInfo)

func (*DB) GetFast

func (db *DB) GetFast(Id string) *Msg

Fast varian (w/o locking) of Get. Get decoded message from db by message id. Does NOT lock! Loads/create index if needed.

func (*DB) GetTopics

func (db *DB) GetTopics(mi []*MsgInfo) map[string][]string

Internal function. Get slice of MsgInfo pointers and create information about topics. Information returns in form of: [topicid][]ids topic id is the msg id of most old parent in echo ids - is the messages in this topic

func (*DB) IndexPath

func (db *DB) IndexPath() string

Returns path to index file.

func (*DB) LoadIndex

func (db *DB) LoadIndex() error

Loads index. If index doesent exists, create and load it. If index was changed, reread tail. This function does lock.

func (*DB) Lock

func (db *DB) Lock() bool

Recursive file lock. Used to avoid conflicts between ii-tool and ii-node. Uses mkdir as atomic operation. Note: dirs created as db.LockPath() 16 sec is limit.

func (*DB) LockPath

func (db *DB) LockPath() string

Returns path to lock.

func (*DB) Lookup

func (db *DB) Lookup(Id string) *MsgInfo

Lookup message in index. Do not search blacklisted messages. Creates/load index if needed. Returns MsgInfo pointer. Does lock!

func (*DB) LookupFast

func (db *DB) LookupFast(Id string, bl bool) *MsgInfo

Lookup variant, but without locking. Useful if caller do locking logic himself.

func (*DB) LookupIDS

func (db *DB) LookupIDS(Ids []string) []*MsgInfo

Lookup messages in index. Gets: slice of message ids to get. Returns slice of MsgInfo pointers. Does lock!

func (*DB) Match

func (db *DB) Match(info *MsgInfo, r Query) bool

Default match function for queries.

func (*DB) SelectIDS

func (db *DB) SelectIDS(r Query) []string

Make query and retuen ids as slice of strings. Does lock. Can create/load index if needed. r: request, see Query

func (*DB) Store

func (db *DB) Store(m *Msg) error

Store decoded message in database If message exists, returns error

func (*DB) Unlock

func (db *DB) Unlock()

Recursive file lock: unlock See Lock comment.

type EDB

type EDB struct {
	Info map[string]string
	List []string
	Path string
}

Echo database entry Holds echo descriptions in Info hash. List - names of echoareas.

func LoadEcholist

func LoadEcholist(path string) *EDB

Loads echolist database and returns pointer to EDB Supposed to be called only once

func (*EDB) Allowed

func (db *EDB) Allowed(name string) bool

Check if echo is exists in echo database

type Echo

type Echo struct {
	Name   string
	Count  int
	Topics int
	Last   *MsgInfo
	Msg    *Msg
}

Used to get information about echoarea Count: number of messages Topics: number of topics Last: last MsgInfo Msg: last message pointer

type Index

type Index struct {
	Hash     map[string]*MsgInfo
	List     []string
	FileSize int64
}

Index object. Holds List and Hash for all MsgInfo entries FileSize is used to auto reread new entries if it has changed by someone.

type Msg

type Msg struct {
	MsgId string
	Tags  Tags
	Echo  string
	Date  int64
	From  string
	Addr  string
	To    string
	Subj  string
	Text  string
}

Decoded message. Has all atrributes of message including Tags.

func DecodeBundle

func DecodeBundle(msg string) (*Msg, error)

Decode bundle line in msgid:message format or just message Returns pointer to decoded Msg or nil, error if fail. Can parse URL safe and STD BASE64. This function does NOT add ii/ok tag and does NOT change Date

func DecodeMsgline

func DecodeMsgline(msg string, enc bool) (*Msg, error)

Decode message from point sent with /u/point scheme. Try to use URL save and STD base64. Returns pointrt to decoded Msg or nil (and error) Note: This function adds "ii/ok" to Tags and set Date field with UTC Unix time.

func (*Msg) Dump

func (m *Msg) Dump() string

Dump (returns string) decoded message for debug purposes.

func (*Msg) Encode

func (m *Msg) Encode() string

Encode Msg into bundle format (msgid:base64text).

func (*Msg) String

func (m *Msg) String() string

Translate decoded Msg to raw text format ready to encoding.

func (*Msg) Tag

func (m *Msg) Tag(n string) (string, bool)

Get if tag property with name n is associated with Msg

type MsgInfo

type MsgInfo struct {
	Num   int
	Id    string
	Echo  string
	To    string
	Off   int64
	Repto string
	From  string
	Topic string
}

This is index entry. Information about message that is loaded in memory. So, the index could not be very huge. Num: sequence number. Id: MsgId Echo: Echoarea To, From, Repto: message attributes Off: offset to bundle-line in database (in bytes)

type Node

type Node struct {
	Host     string
	Features map[string]bool
	Force    bool
}

Node object. Use Connect to create it. Host: url node Features: extensions map Force: force sync even last message is not new

func Connect

func Connect(addr string) (*Node, error)

Connect to node, get features and returns pointer to Node object.

func (*Node) Fetch

func (n *Node) Fetch(db *DB, Echolist []string, limit int) error

This is Fetcher master function. It makes fetch from node and run goroutines in parralel mode (one goroutine per echo). Echolist: list with echoarea names. If list is empty, function will try to get list via list.txt request. limit: see Fetcher function. Describe fetching mode/limit.

func (*Node) Fetcher

func (n *Node) Fetcher(db *DB, Echo string, limit int, wait *sync.WaitGroup, cond *sync.Cond)

Fetcher internal goroutine. DB: db to write Echo: echo to fetch wait: sync for Fetch master to detect finishing of work cond: used for wake-up new goroutines Can work in different modes. If limit > 0, just fetch last [limit] messages (-limit:limit slice) if limit < 0, use adaptive mode, probe (-(2*n)* limit:1) messages untill find old message. if node does not support u/e slices, than full sync performed if node connection is not in Force mode, do not perform sync if not needed

func (*Node) IsFeature

func (n *Node) IsFeature(f string) bool

Check if node has feature? Features are gets while Connect call.

func (*Node) List

func (n *Node) List() ([]string, error)

Return list.txt in []string if node supports it. WARNING: Only echo names are returned! Each string is just echoarea. Used for fetch all mode.

func (*Node) Post

func (n *Node) Post(pauth string, msg string) error

Send point message to node using POST method of /u/point scheme. pauth: secret string. msg - raw message in plaintext returns error

func (*Node) Send

func (n *Node) Send(pauth string, msg string) error

Send point message to node using GET method of /u/point scheme. pauth: secret string. msg - raw message in plaintext returns error

func (*Node) Store

func (n *Node) Store(db *DB, ids []string) error

Fetch and write selected messages in db. ids: selected message ids. db: Database. This function make /u/m request, decodes bundles, checks, and write them to db (line by line).

type Query

type Query struct {
	Echo        string
	Repto       string
	From        string
	To          string
	Start       int
	Lim         int
	Blacklisted bool
	User        User
	Match       func(mi *MsgInfo, q Query) bool
}

Query used to make queries to Index If some field of: Echo, Repto, From, To is not "" fields will be matched with MsgInfo entry (logical AND). If Match function is not nil, this function will be used for matching. Blacklisted: search in blacklisted messages if true. User: authorized access to private areas. Start & Lim: slice of query. For example: -1, 1 -- get last message in db. 0, 1 -- first.

type Tags

type Tags struct {
	Hash map[string]string
	List []string
}

II-tags, encoded in raw message as key1/value1/key2/value2.. string When message is decoded into Msg, key/value properties of tags associated with it. When encoding Msg, all properties will translated to tags string List - is the names of properties Hash - is the map of properties (Name->Value)

func MakeTags

func MakeTags(str string) (Tags, error)

Creates Tags from string in key1/value1/key2/value2/... format Can return error (with unfilled Tags) if format is wrong.

func NewTags

func NewTags(str string) Tags

Create Tags from string in key1/value1/key2/value2/... format ignoring errors. This is useful for creating new "ii/ok" tag.

func (*Tags) Add

func (t *Tags) Add(str string) error

Add tags in key/value/... format to existing Tags.

func (*Tags) Del

func (t *Tags) Del(tag string) bool

Remove tag with name tag from Tags.

func (*Tags) Get

func (t *Tags) Get(n string) (string, bool)

Returns Tags propertie with name n. Returns "", false if such propertie does not exists in Tags.

func (Tags) String

func (t Tags) String() string

Translate Tags to string in key1/value1/key2/value2/... format.

type UDB

type UDB struct {
	Path     string
	Names    map[string]User
	ById     map[int32]string
	Secrets  map[string]string
	List     []string
	Sync     sync.RWMutex
	FileSize int64
}

User database. FileSize - size of points.txt to detect DB changes. Names: holds User structure by user name ById: holds user name by user id Secrets: holds user name by user secret (pauth) List: holds user names as list

func OpenUsers

func OpenUsers(path string) *UDB

Open user database and return pointer to UDB object

func (*UDB) Access

func (db *UDB) Access(Secret string) bool

Returns true if Secret (pauth) is valid

func (*UDB) Add

func (db *UDB) Add(Name string, Mail string, Passwd string) error

Add (register) user in database Mail is optional but someday it will be used in registration process

func (*UDB) Auth

func (db *UDB) Auth(User string, Passwd string) bool

Returns true if user+password is valid

func (*UDB) Edit

func (db *UDB) Edit(u *User) error

Change (replace) information about user. Gets pointer to User object and write it in DB, replacing old information. Works atomically using rename.

func (*UDB) Id

func (db *UDB) Id(Secret string) int32

Return user id for given secret

func (*UDB) LoadUsers

func (db *UDB) LoadUsers() error

Load user information in memory if it is needed (FileSize changed). So, it is safe to call it on every request.

func (*UDB) Name

func (db *UDB) Name(Secret string) string

Return username for given Secret

func (*UDB) Secret

func (db *UDB) Secret(User string) string

Return secret for username or "" if no such user

func (*UDB) UserInfo

func (db *UDB) UserInfo(Secret string) *User

Return User pointer for given Secret

func (*UDB) UserInfoId

func (db *UDB) UserInfoId(id int32) *User

Return User pointer for user id

func (*UDB) UserInfoName

func (db *UDB) UserInfoName(name string) *User

Return User pointer for given user name

type User

type User struct {
	Id     int32
	Name   string
	Mail   string
	Secret string
	Tags   Tags
}

User entry in points.txt db User with Id == 1 is superuser. Tags: custom information (like avatars :) in Tags format

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL