Beispiel #1
0
// Read is thread-safe
func (sr *StorageReader) Read(p []byte) (n int, err error) {
	sr.mutex.Lock()
	defer sr.mutex.Unlock()

	if !sr.parent.alive {
		return -1, errors.New("EOF")
	}

	chunkId := sr.Offset / CHUNK_SIZE
	internalMsgId := uint64(sr.Offset % CHUNK_SIZE)

	sr.parent.dataCond.L.Lock()
	for sr.currentSub == nil ||
		chunkId >= uint64(len(sr.parent.stores)) ||
		internalMsgId >= sr.parent.stores[chunkId].Size {
		// Block for new data
		sr.parent.dataCond.Wait()
		sr.handleRollover()
	}
	sr.parent.dataCond.L.Unlock()
	// We have a valid reader, and can read from it
	nextMsgSize, err := sr.parent.stores[chunkId].SizeOf(internalMsgId)
	if err != nil {
		return 0, err
	}
	if nextMsgSize > uint64(len(p)) {
		return 0, fmt.Errorf("Message, of size %d, does not fit into available buffer", nextMsgSize)
	}
	target := p[0:nextMsgSize]
	_, err = sr.currentSub.Read(target)
	utils.Check(err)
	sr.Offset++
	sr.handleRollover()
	return int(nextMsgSize), nil
}
Beispiel #2
0
func (t *Track) startWriter(startId uint64) {
	t.writeChan = make(chan []byte, CHUNK_SIZE/100) // Buffer 1% of a chunk
	go func() {
		msgId := startId
		for {
			msg, more := <-t.writeChan
			if !more {
				t.alive = false
				return
			}
			chunkId := msgId / CHUNK_SIZE
			if chunkId == uint64(len(t.stores)) {
				if chunkId > 0 {
					t.stores[chunkId-1].switchToReadOnly() // Migrate the old chunk to readonly
				}
				storeId := fmt.Sprintf("%s%d", t.Id, chunkId)
				t.stores = append(t.stores, NewFileStorage(t.RootPath, storeId, CHUNK_SIZE))
			}
			internalMsgId := int(msgId % CHUNK_SIZE)
			err := t.stores[chunkId].WriteMessage(internalMsgId, msg)
			utils.Check(err)
			msgId++

			// Tell any waiting routines that there's new data
			t.dataCond.Broadcast()
		}
	}()
}
Beispiel #3
0
func (t *Track) ReaderAt(offset uint64) (io.ReadCloser, error) {
	if offset < 0 {
		return nil, fmt.Errorf("Offset out of bounds: %d", offset)
	}
	r := &StorageReader{
		parent: t,
		Offset: offset,
		mutex:  &sync.Mutex{},
	}
	chunkIndex := offset / CHUNK_SIZE
	msgIndex := offset % CHUNK_SIZE
	if chunkIndex < uint64(len(t.stores)) && uint64(msgIndex) < t.stores[chunkIndex].Size {
		var err error
		r.currentSub, err = t.stores[chunkIndex].ReaderAt(msgIndex)
		utils.Check(err)
	}
	return r, nil
}