1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "nacl_io/stream/stream_fs.h"
6
7#include <errno.h>
8
9#include "nacl_io/ossocket.h"
10#include "nacl_io/pepper_interface.h"
11
12namespace nacl_io {
13
14void DispatchStart(void* work_ptr, int32_t val) {
15  StreamFs::Work* work = static_cast<StreamFs::Work*>(work_ptr);
16
17  // Delete if it fails to Start, Run will never get called.
18  if (!work->Start(val))
19    delete work;
20}
21
22void DispatchRun(void* work_ptr, int32_t val) {
23  StreamFs::Work* work = static_cast<StreamFs::Work*>(work_ptr);
24
25  work->Run(val);
26  delete work;
27}
28
29void* StreamFs::StreamThreadThunk(void* fs_ptr) {
30  StreamFs* filesystem = static_cast<StreamFs*>(fs_ptr);
31  filesystem->StreamThread();
32  return NULL;
33}
34
35// All work is done via completions callbacks from posted work.
36void StreamFs::StreamThread() {
37  {
38    AUTO_LOCK(message_lock_)
39    message_loop_ =
40        ppapi_->GetMessageLoopInterface()->Create(ppapi()->GetInstance());
41    ppapi_->GetMessageLoopInterface()->AttachToCurrentThread(message_loop_);
42    pthread_cond_broadcast(&message_cond_);
43  }
44
45  // Run loop until Quit is posted.
46  ppapi_->GetMessageLoopInterface()->Run(message_loop_);
47}
48
49PP_CompletionCallback StreamFs::GetStartCompletion(Work* work) {
50  return PP_MakeCompletionCallback(DispatchStart, work);
51}
52
53PP_CompletionCallback StreamFs::GetRunCompletion(Work* work) {
54  return PP_MakeCompletionCallback(DispatchRun, work);
55}
56
57// Place enqueue onto the socket thread.
58void StreamFs::EnqueueWork(Work* work) {
59  if (message_loop_ == 0) {
60    AUTO_LOCK(message_lock_);
61
62    if (message_loop_ == 0) {
63      pthread_t thread;
64      pthread_create(&thread, NULL, StreamThreadThunk, this);
65    }
66
67    while (message_loop_ == 0)
68      pthread_cond_wait(&message_cond_, message_lock_.mutex());
69  }
70
71  PP_CompletionCallback cb = PP_MakeCompletionCallback(DispatchStart, work);
72  ppapi_->GetMessageLoopInterface()->PostWork(message_loop_, cb, 0);
73}
74
75StreamFs::StreamFs() : message_loop_(0) {
76  pthread_cond_init(&message_cond_, NULL);
77}
78
79StreamFs::~StreamFs() {
80  if (message_loop_) {
81    ppapi_->GetMessageLoopInterface()->PostQuit(message_loop_, PP_TRUE);
82    ppapi_->ReleaseResource(message_loop_);
83  }
84  pthread_cond_destroy(&message_cond_);
85}
86
87Error StreamFs::OpenWithMode(const Path& path, int o_flags, mode_t mode,
88                             ScopedNode* out_node) {
89  return EACCES;
90}
91
92Error StreamFs::Unlink(const Path& path) {
93  return EACCES;
94}
95
96Error StreamFs::Mkdir(const Path& path, int permissions) {
97  return EACCES;
98}
99
100Error StreamFs::Rmdir(const Path& path) {
101  return EACCES;
102}
103
104Error StreamFs::Remove(const Path& path) {
105  return EACCES;
106}
107
108Error StreamFs::Rename(const Path& path, const Path& newpath) {
109  return EACCES;
110}
111
112}  // namespace nacl_io
113