AddUser appends a new record to the index file and updates the header.
(userId int, username string)
| 368 | |
| 369 | // AddUser appends a new record to the index file and updates the header. |
| 370 | func (idx *UserIndex) AddUser(userId int, username string) error { |
| 371 | idx.mu.Lock() |
| 372 | defer idx.mu.Unlock() |
| 373 | |
| 374 | username = strings.ToLower(username) |
| 375 | |
| 376 | newRecord := IndexUserRecord{ |
| 377 | UserID: int64(userId), |
| 378 | } |
| 379 | copy(newRecord.Username[:], username) |
| 380 | |
| 381 | f, err := os.OpenFile(idx.Filename, os.O_RDWR, 0644) |
| 382 | if err != nil { |
| 383 | return err |
| 384 | } |
| 385 | defer f.Close() |
| 386 | |
| 387 | if _, err := f.Seek(0, io.SeekEnd); err != nil { |
| 388 | return fmt.Errorf("error seeking to file end: %w", err) |
| 389 | } |
| 390 | |
| 391 | var recBuf [IndexRecordSizeV1]byte |
| 392 | copy(recBuf[:80], newRecord.Username[:]) |
| 393 | binary.LittleEndian.PutUint64(recBuf[80:88], uint64(newRecord.UserID)) |
| 394 | recBuf[88] = IndexLineTerminatorV1 |
| 395 | if _, err := f.Write(recBuf[:]); err != nil { |
| 396 | return fmt.Errorf("error writing record: %w", err) |
| 397 | } |
| 398 | |
| 399 | if userId > idx.highestUserId { |
| 400 | idx.highestUserId = userId |
| 401 | } |
| 402 | |
| 403 | idx.metaData.RecordCount++ |
| 404 | |
| 405 | newHeaderBytes, err := idx.metaData.Format() |
| 406 | if err != nil { |
| 407 | return fmt.Errorf("error formatting header: %w", err) |
| 408 | } |
| 409 | if _, err := f.Seek(0, io.SeekStart); err != nil { |
| 410 | return fmt.Errorf("error seeking to beginning: %w", err) |
| 411 | } |
| 412 | if _, err := f.Write(newHeaderBytes); err != nil { |
| 413 | return fmt.Errorf("error writing updated header: %w", err) |
| 414 | } |
| 415 | |
| 416 | if err := f.Sync(); err != nil { |
| 417 | return fmt.Errorf("error syncing file: %w", err) |
| 418 | } |
| 419 | |
| 420 | idx.records = append(idx.records, newRecord) |
| 421 | idx.byUsername[username] = int64(userId) |
| 422 | idx.byUserId[int64(userId)] = username |
| 423 | |
| 424 | return nil |
| 425 | } |
| 426 | |
| 427 | // RemoveByUsername removes the first record matching the username and rewrites the index. |