中文字幕第五页-中文字幕第页-中文字幕韩国-中文字幕最新-国产尤物二区三区在线观看-国产尤物福利视频一区二区

讀寫文件的鎖實(shí)例-創(chuàng)新互聯(lián)

讀寫文件的鎖實(shí)例

專注于為中小企業(yè)提供成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)洪江免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了數(shù)千家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

版本一:
datafile1.go:

package v1

import (
    "errors"
    "io"
    "os"
    "sync"
)

// Data 代表數(shù)據(jù)的類型。
type Data []byte

// DataFile 代表數(shù)據(jù)文件的接口類型。
type DataFile interface {
    // Read 會(huì)讀取一個(gè)數(shù)據(jù)塊。
    Read() (rsn int64, d Data, err error)
    // Write 會(huì)寫入一個(gè)數(shù)據(jù)塊。
   write(d Data) (wsn int64, err error)
    // RSN 會(huì)獲取最后讀取的數(shù)據(jù)塊的序列號(hào)。
    RSN() int64
    // WSN 會(huì)獲取最后寫入的數(shù)據(jù)塊的序列號(hào)。
   wSN() int64
    // DataLen 會(huì)獲取數(shù)據(jù)塊的長度。
    DataLen() uint32
    // Close 會(huì)關(guān)閉數(shù)據(jù)文件。
    Close() error
}

// myDataFile 代表數(shù)據(jù)文件的實(shí)現(xiàn)類型。
type myDataFile struct {
    f       *os.File     // 文件。
    fmutex  sync.RWMutex // 被用于文件的讀寫鎖。
   woffset int64        // 寫操作需要用到的偏移量。
    roffset int64        // 讀操作需要用到的偏移量。
   wmutex  sync.Mutex   // 寫操作需要用到的互斥鎖。
    rmutex  sync.Mutex   // 讀操作需要用到的互斥鎖。
    dataLen uint32       // 數(shù)據(jù)塊長度。
}

// NewDataFile 會(huì)新建一個(gè)數(shù)據(jù)文件的實(shí)例。
func NewDataFile(path string, dataLen uint32) (DataFile, error) {
    f, err := os.Create(path)
    if err != nil {
        return nil, err
    }
    if dataLen == 0 {
        return nil, errors.New("Invalid data length!")
    }
    df := &myDataFile{f: f, dataLen: dataLen}
    return df, nil
}

func (df *myDataFile) Read() (rsn int64, d Data, err error) {
    // 讀取并更新讀偏移量。
    var offset int64
    df.rmutex.Lock()
    offset = df.roffset
    df.roffset += int64(df.dataLen)
    df.rmutex.Unlock()

    //讀取一個(gè)數(shù)據(jù)塊。
    rsn = offset / int64(df.dataLen)
    bytes := make([]byte, df.dataLen)
    for {
        df.fmutex.RLock()
        _, err = df.f.ReadAt(bytes, offset)
        if err != nil {
            if err == io.EOF {
                df.fmutex.RUnlock()
                continue
            }
            df.fmutex.RUnlock()
            return
        }
        d = bytes
        df.fmutex.RUnlock()
        return
    }
}

func (df *myDataFile) Write(d Data) (wsn int64, err error) {
    // 讀取并更新寫偏移量。
    var offset int64
    df.wmutex.Lock()
    offset = df.woffset
    df.woffset += int64(df.dataLen)
    df.wmutex.Unlock()

    //寫入一個(gè)數(shù)據(jù)塊。
   wsn = offset / int64(df.dataLen)
    var bytes []byte
    if len(d) > int(df.dataLen) {
        bytes = d[0:df.dataLen]
    } else {
        bytes = d
    }
    df.fmutex.Lock()
    defer df.fmutex.Unlock()
    _, err = df.f.Write(bytes)
    return
}

func (df *myDataFile) RSN() int64 {
    df.rmutex.Lock()
    defer df.rmutex.Unlock()
    return df.roffset / int64(df.dataLen)
}

func (df *myDataFile) WSN() int64 {
    df.wmutex.Lock()
    defer df.wmutex.Unlock()
    return df.woffset / int64(df.dataLen)
}

func (df *myDataFile) DataLen() uint32 {
    return df.dataLen
}

func (df *myDataFile) Close() error {
    if df.f == nil {
        return nil
    }
    return df.f.Close()
}

datafile1_test.go:

package v1

import (
    "math/rand"
    "os"
    "path/filepath"
    "sync"
    "testing"
)

func removeFile(path string) error {
    file, err := os.Open(path)
    if err != nil {
        if !os.IsNotExist(err) {
            return err
        }
        return nil
    }
    file.Close()
    return os.Remove(path)
}

func TestIDataFile(t *testing.T) {
    t.Run("v1/all", func(t *testing.T) {
        dataLen := uint32(3)
        path2 := filepath.Join(os.TempDir(), "data_file_test_new.txt")
        defer func() {
            if err := removeFile(path2); err != nil {
                t.Errorf("Open file error: %s\n", err)
            }
        }()
        t.Run("New", func(t *testing.T) {
            testNew(path2, dataLen, t)
        })
        path3 := filepath.Join(os.TempDir(), "data_file_test.txt")
        defer func() {
            if err := removeFile(path3); err != nil {
                t.Fatalf("Open file error: %s\n", err)
            }
        }()
        max := 100000
        t.Run("WriteAndRead", func(t *testing.T) {
            testRW(path3, dataLen, max, t)
        })
    })
}

func testNew(path string, dataLen uint32, t *testing.T) {
    t.Logf("New a data file (path: %s, dataLen: %d)...\n",
        path, dataLen)
    dataFile, err := NewDataFile(path, dataLen)
    if err != nil {
        t.Logf("Couldn't new a data file: %s", err)
        t.FailNow()
    }
    if dataFile == nil {
        t.Log("Unnormal data file!")
        t.FailNow()
    }
    defer dataFile.Close()
    if dataFile.DataLen() != dataLen {
        t.Fatalf("Incorrect data length!")
    }
}

func testRW(path string, dataLen uint32, max int, t *testing.T) {
    t.Logf("New a data file (path: %s, dataLen: %d)...\n",
        path, dataLen)
    dataFile, err := NewDataFile(path, dataLen)
    if err != nil {
        t.Logf("Couldn't new a data file: %s", err)
        t.FailNow()
    }
    defer dataFile.Close()
    var wg sync.WaitGroup
   wg.Add(5)
    // 寫入。
    for i := 0; i < 3; i++ {
        go func() {
            defer wg.Done()
            var prevWSN int64 = -1
            for j := 0; j < max; j++ {
                data := Data{
                    byte(rand.Int31n(256)),
                    byte(rand.Int31n(256)),
                    byte(rand.Int31n(256)),
                }
               wsn, err := dataFile.Write(data)
                if err != nil {
                    t.Fatalf("Unexpected writing error: %s\n", err)
                }
                if prevWSN >= 0 && wsn <= prevWSN {
                    t.Fatalf("Incorect WSN %d! (lt %d)\n", wsn, prevWSN)
                }
                prevWSN = wsn
            }
        }()
    }
    // 讀取。
    for i := 0; i < 2; i++ {
        go func() {
            defer wg.Done()
            var prevRSN int64 = -1
            for i := 0; i < max; i++ {
                rsn, date, err := dataFile.Read()
                if err != nil {
                    t.Fatalf("Unexpected writing error: %s\n", err)
                }
                if date == nil {
                    t.Fatalf("Unnormal data!")
                }
                if prevRSN >= 0 && rsn <= prevRSN {
                    t.Fatalf("Incorect RSN %d! (lt %d)\n", rsn, prevRSN)
                }
                prevRSN = rsn
            }
        }()
    }
   wg.Wait()
}

版本二:
datafile2.go:

package v2

import (
    "errors"
    "io"
    "os"
    "sync"
)

// Data 代表數(shù)據(jù)的類型。
type Data []byte

// DataFile 代表數(shù)據(jù)文件的接口類型。
type DataFile interface {
    // Read 會(huì)讀取一個(gè)數(shù)據(jù)塊。
    Read() (rsn int64, d Data, err error)
    // Write 會(huì)寫入一個(gè)數(shù)據(jù)塊。
   write(d Data) (wsn int64, err error)
    // RSN 會(huì)獲取最后讀取的數(shù)據(jù)塊的序列號(hào)。
    RSN() int64
    // WSN 會(huì)獲取最后寫入的數(shù)據(jù)塊的序列號(hào)。
   wSN() int64
    // DataLen 會(huì)獲取數(shù)據(jù)塊的長度。
    DataLen() uint32
    // Close 會(huì)關(guān)閉數(shù)據(jù)文件。
    Close() error
}

// myDataFile 代表數(shù)據(jù)文件的實(shí)現(xiàn)類型。
type myDataFile struct {
    f       *os.File     // 文件。
    fmutex  sync.RWMutex // 被用于文件的讀寫鎖。
    rcond   *sync.Cond   //讀操作需要用到的條件變量
   woffset int64        // 寫操作需要用到的偏移量。
    roffset int64        // 讀操作需要用到的偏移量。
   wmutex  sync.Mutex   // 寫操作需要用到的互斥鎖。
    rmutex  sync.Mutex   // 讀操作需要用到的互斥鎖。
    dataLen uint32       // 數(shù)據(jù)塊長度。
}

// NewDataFile 會(huì)新建一個(gè)數(shù)據(jù)文件的實(shí)例。
func NewDataFile(path string, dataLen uint32) (DataFile, error) {
    f, err := os.Create(path)
    if err != nil {
        return nil, err
    }
    if dataLen == 0 {
        return nil, errors.New("Invalid data length!")
    }
    df := &myDataFile{f: f, dataLen: dataLen}
    df.rcond = sync.NewCond(df.fmutex.RLocker())
    return df, nil
}

func (df *myDataFile) Read() (rsn int64, d Data, err error) {
    // 讀取并更新讀偏移量。
    var offset int64
    df.rmutex.Lock()
    offset = df.roffset
    df.roffset += int64(df.dataLen)
    df.rmutex.Unlock()

    //讀取一個(gè)數(shù)據(jù)塊。
    rsn = offset / int64(df.dataLen)
    bytes := make([]byte, df.dataLen)
    df.fmutex.RLock()
    defer df.fmutex.RUnlock()
    for {
        _, err = df.f.ReadAt(bytes, offset)
        if err != nil {
            if err == io.EOF {
                df.rcond.Wait()
                continue
            }
            return
        }
        d = bytes
        return
    }
}

func (df *myDataFile) Write(d Data) (wsn int64, err error) {
    // 讀取并更新寫偏移量。
    var offset int64
    df.wmutex.Lock()
    offset = df.woffset
    df.woffset += int64(df.dataLen)
    df.wmutex.Unlock()

    //寫入一個(gè)數(shù)據(jù)塊。
   wsn = offset / int64(df.dataLen)
    var bytes []byte
    if len(d) > int(df.dataLen) {
        bytes = d[0:df.dataLen]
    } else {
        bytes = d
    }
    df.fmutex.Lock()
    defer df.fmutex.Unlock()
    _, err = df.f.Write(bytes)
    df.rcond.Signal()
    return
}

func (df *myDataFile) RSN() int64 {
    df.rmutex.Lock()
    defer df.rmutex.Unlock()
    return df.roffset / int64(df.dataLen)
}

func (df *myDataFile) WSN() int64 {
    df.wmutex.Lock()
    defer df.wmutex.Unlock()
    return df.woffset / int64(df.dataLen)
}

func (df *myDataFile) DataLen() uint32 {
    return df.dataLen
}

func (df *myDataFile) Close() error {
    if df.f == nil {
        return nil
    }
    return df.f.Close()
}

datafile2_test.go:

package v2

import (
    "math/rand"
    "os"
    "path/filepath"
    "sync"
    "testing"
)

func removeFile(path string) error {
    file, err := os.Open(path)
    if err != nil {
        if !os.IsNotExist(err) {
            return err
        }
        return nil
    }
    file.Close()
    return os.Remove(path)
}

func TestIDataFile(t *testing.T) {
    t.Run("v2/all", func(t *testing.T) {
        dataLen := uint32(3)
        path2 := filepath.Join(os.TempDir(), "data_file_test_new.txt")
        defer func() {
            if err := removeFile(path2); err != nil {
                t.Errorf("Open file error: %s\n", err)
            }
        }()
        t.Run("New", func(t *testing.T) {
            testNew(path2, dataLen, t)
        })
        path3 := filepath.Join(os.TempDir(), "data_file_test.txt")
        defer func() {
            if err := removeFile(path3); err != nil {
                t.Fatalf("Open file error: %s\n", err)
            }
        }()
        max := 100000
        t.Run("WriteAndRead", func(t *testing.T) {
            testRW(path3, dataLen, max, t)
        })
    })
}

func testNew(path string, dataLen uint32, t *testing.T) {
    t.Logf("New a data file (path: %s, dataLen: %d)...\n",
        path, dataLen)
    dataFile, err := NewDataFile(path, dataLen)
    if err != nil {
        t.Logf("Couldn't new a data file: %s", err)
        t.FailNow()
    }
    if dataFile == nil {
        t.Log("Unnormal data file!")
        t.FailNow()
    }
    defer dataFile.Close()
    if dataFile.DataLen() != dataLen {
        t.Fatalf("Incorrect data length!")
    }
}

func testRW(path string, dataLen uint32, max int, t *testing.T) {
    t.Logf("New a data file (path: %s, dataLen: %d)...\n",
        path, dataLen)
    dataFile, err := NewDataFile(path, dataLen)
    if err != nil {
        t.Logf("Couldn't new a data file: %s", err)
        t.FailNow()
    }
    defer dataFile.Close()
    var wg sync.WaitGroup
   wg.Add(5)
    // 寫入。
    for i := 0; i < 3; i++ {
        go func() {
            defer wg.Done()
            var prevWSN int64 = -1
            for j := 0; j < max; j++ {
                data := Data{
                    byte(rand.Int31n(256)),
                    byte(rand.Int31n(256)),
                    byte(rand.Int31n(256)),
                }
               wsn, err := dataFile.Write(data)
                if err != nil {
                    t.Fatalf("Unexpected writing error: %s\n", err)
                }
                if prevWSN >= 0 && wsn <= prevWSN {
                    t.Fatalf("Incorect WSN %d! (lt %d)\n", wsn, prevWSN)
                }
                prevWSN = wsn
            }
        }()
    }
    // 讀取。
    for i := 0; i < 2; i++ {
        go func() {
            defer wg.Done()
            var prevRSN int64 = -1
            for i := 0; i < max; i++ {
                rsn, date, err := dataFile.Read()
                if err != nil {
                    t.Fatalf("Unexpected writing error: %s\n", err)
                }
                if date == nil {
                    t.Fatalf("Unnormal data!")
                }
                if prevRSN >= 0 && rsn <= prevRSN {
                    t.Fatalf("Incorect RSN %d! (lt %d)\n", rsn, prevRSN)
                }
                prevRSN = rsn
            }
        }()
    }
   wg.Wait()
}

版本三
datafile3.go:

package v3

import (
    "errors"
    "io"
    "os"
    "sync"
    "sync/atomic"
)

// Data 代表數(shù)據(jù)的類型。
type Data []byte

// DataFile 代表數(shù)據(jù)文件的接口類型。
type DataFile interface {
    // Read 會(huì)讀取一個(gè)數(shù)據(jù)塊。
    Read() (rsn int64, d Data, err error)
    // Write 會(huì)寫入一個(gè)數(shù)據(jù)塊。
   write(d Data) (wsn int64, err error)
    // RSN 會(huì)獲取最后讀取的數(shù)據(jù)塊的序列號(hào)。
    RSN() int64
    // WSN 會(huì)獲取最后寫入的數(shù)據(jù)塊的序列號(hào)。
   wSN() int64
    // DataLen 會(huì)獲取數(shù)據(jù)塊的長度。
    DataLen() uint32
    // Close 會(huì)關(guān)閉數(shù)據(jù)文件。
    Close() error
}

// myDataFile 代表數(shù)據(jù)文件的實(shí)現(xiàn)類型。
type myDataFile struct {
    f       *os.File     // 文件。
    fmutex  sync.RWMutex // 被用于文件的讀寫鎖。
    rcond   *sync.Cond   // 讀操作需要用到的條件變量
   woffset int64        // 寫操作需要用到的偏移量。
    roffset int64        // 讀操作需要用到的偏移量。
    dataLen uint32       // 數(shù)據(jù)塊長度。
}

// NewDataFile 會(huì)新建一個(gè)數(shù)據(jù)文件的實(shí)例。
func NewDataFile(path string, dataLen uint32) (DataFile, error) {
    f, err := os.Create(path)
    if err != nil {
        return nil, err
    }
    if dataLen == 0 {
        return nil, errors.New("Invalid data length!")
    }
    df := &myDataFile{f: f, dataLen: dataLen}
    df.rcond = sync.NewCond(df.fmutex.RLocker())
    return df, nil
}

func (df *myDataFile) Read() (rsn int64, d Data, err error) {
    // 讀取并更新讀偏移量
    var offset int64
    for {
        offset = atomic.LoadInt64(&df.roffset)
        if atomic.CompareAndSwapInt64(&df.roffset, offset, (offset + int64(df.dataLen))) {
            break
        }
    }

    //讀取一個(gè)數(shù)據(jù)塊
    rsn = offset / int64(df.dataLen)
    bytes := make([]byte, df.dataLen)
    df.fmutex.RLock()
    defer df.fmutex.RUnlock()
    for {
        _, err = df.f.ReadAt(bytes, offset)
        if err != nil {
            if err == io.EOF {
                df.rcond.Wait()
                continue
            }
            return
        }
        d = bytes
        return
    }
}

func (df *myDataFile) Write(d Data) (wsn int64, err error) {
    // 讀取并更新寫偏移量
    var offset int64
    for {
        offset = atomic.LoadInt64(&df.woffset)
        if atomic.CompareAndSwapInt64(&df.woffset, offset, (offset + int64(df.dataLen))) {
            break
        }
    }

    //寫入一個(gè)數(shù)據(jù)塊
   wsn = offset / int64(df.dataLen)
    var bytes []byte
    if len(d) > int(df.dataLen) {
        bytes = d[0:df.dataLen]
    } else {
        bytes = d
    }
    df.fmutex.Lock()
    defer df.fmutex.Unlock()
    _, err = df.f.Write(bytes)
    df.rcond.Signal()
    return
}

func (df *myDataFile) RSN() int64 {
    offset := atomic.LoadInt64(&df.roffset)
    return offset / int64(df.dataLen)
}

func (df *myDataFile) WSN() int64 {
    offset := atomic.LoadInt64(&df.woffset)
    return offset / int64(df.dataLen)
}

func (df *myDataFile) DataLen() uint32 {
    return df.dataLen
}

func (df *myDataFile) Close() error {
    if df.f == nil {
        return nil
    }
    return df.f.Close()
}

datafile3_test.go:

package v3

import (
    "math/rand"
    "os"
    "path/filepath"
    "sync"
    "testing"
)

func removeFile(path string) error {
    file, err := os.Open(path)
    if err != nil {
        if !os.IsNotExist(err) {
            return err
        }
        return nil
    }
    file.Close()
    return os.Remove(path)
}

func TestIDataFile(t *testing.T) {
    t.Run("v3/all", func(t *testing.T) {
        dataLen := uint32(3)
        path2 := filepath.Join(os.TempDir(), "data_file_test_new.txt")
        defer func() {
            if err := removeFile(path2); err != nil {
                t.Errorf("Open file error: %s\n", err)
            }
        }()
        t.Run("New", func(t *testing.T) {
            testNew(path2, dataLen, t)
        })
        path3 := filepath.Join(os.TempDir(), "data_file_test.txt")
        defer func() {
            if err := removeFile(path3); err != nil {
                t.Fatalf("Open file error: %s\n", err)
            }
        }()
        max := 100000
        t.Run("WriteAndRead", func(t *testing.T) {
            testRW(path3, dataLen, max, t)
        })
    })
}

func testNew(path string, dataLen uint32, t *testing.T) {
    t.Logf("New a data file (path: %s, dataLen: %d)...\n",
        path, dataLen)
    dataFile, err := NewDataFile(path, dataLen)
    if err != nil {
        t.Logf("Couldn't new a data file: %s", err)
        t.FailNow()
    }
    if dataFile == nil {
        t.Log("Unnormal data file!")
        t.FailNow()
    }
    defer dataFile.Close()
    if dataFile.DataLen() != dataLen {
        t.Fatalf("Incorrect data length!")
    }
}

func testRW(path string, dataLen uint32, max int, t *testing.T) {
    t.Logf("New a data file (path: %s, dataLen: %d)...\n",
        path, dataLen)
    dataFile, err := NewDataFile(path, dataLen)
    if err != nil {
        t.Logf("Couldn't new a data file: %s", err)
        t.FailNow()
    }
    defer dataFile.Close()
    var wg sync.WaitGroup
   wg.Add(5)
    // 寫入。
    for i := 0; i < 3; i++ {
        go func() {
            defer wg.Done()
            var prevWSN int64 = -1
            for j := 0; j < max; j++ {
                data := Data{
                    byte(rand.Int31n(256)),
                    byte(rand.Int31n(256)),
                    byte(rand.Int31n(256)),
                }
               wsn, err := dataFile.Write(data)
                if err != nil {
                    t.Fatalf("Unexpected writing error: %s\n", err)
                }
                if prevWSN >= 0 && wsn <= prevWSN {
                    t.Fatalf("Incorect WSN %d! (lt %d)\n", wsn, prevWSN)
                }
                prevWSN = wsn
            }
        }()
    }
    // 讀取。
    for i := 0; i < 2; i++ {
        go func() {
            defer wg.Done()
            var prevRSN int64 = -1
            for i := 0; i < max; i++ {
                rsn, date, err := dataFile.Read()
                if err != nil {
                    t.Fatalf("Unexpected writing error: %s\n", err)
                }
                if date == nil {
                    t.Fatalf("Unnormal data!")
                }
                if prevRSN >= 0 && rsn <= prevRSN {
                    t.Fatalf("Incorect RSN %d! (lt %d)\n", rsn, prevRSN)
                }
                prevRSN = rsn
            }
        }()
    }
   wg.Wait()
}

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

本文題目:讀寫文件的鎖實(shí)例-創(chuàng)新互聯(lián)
URL地址:http://m.2m8n56k.cn/article28/dipicp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗(yàn)、Google、響應(yīng)式網(wǎng)站微信公眾號(hào)、小程序開發(fā)、面包屑導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
主站蜘蛛池模板: 九九欧美 | 亚洲在线免费观看视频 | 亚洲日本精品 | 国产精品日本一区二区在线播放 | 亚洲成人黄色在线观看 | 欧美视频一 | 免费一级欧美毛片 | 欧美亚洲综合网 | 国产成人综合亚洲 | 一区二区三区在线免费观看视频 | 欧美videosex性欧美成人 | 国产精品资源手机在线播放 | 久草视频在线免费看 | 99精品国产免费久久国语 | 免费亚洲黄色 | 1级毛片| 久久久久久99精品 | 国内精品小视频福利网址 | 日韩美女一级片 | 高清性色生活片久久久 | 黑人边吃奶边扎下面激情视频 | 99久久精品国产免看国产一区 | 亚洲女精品一区二区三区 | 免费视频一区二区三区四区 | 老湿菠萝蜜在线看 | 国产成人高清亚洲一区久久 | 性欧洲精品videos' | 日本一级特黄特色大片免费视频 | 欧美α一级毛片 | 国产成人一区二区三区影院免费 | 手机看片在线播放 | 小毛片在线观看 | 成人在线免费网站 | 91欧美激情一区二区三区成人 | 美女被免费网站在线视频软件 | 亚洲理论片在线中文字幕 | 美女一级毛片毛片在线播放 | 久久久久久久久中文字幕 | 精品国产90后在线观看 | 国产网站黄色 | 91香蕉国产亚洲一区二区三区 |